Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <tools/time.hxx>
22 :
23 : #include <vcl/svapp.hxx>
24 : #include <vcl/timer.hxx>
25 :
26 : #include <saltimer.hxx>
27 : #include <svdata.hxx>
28 : #include <salinst.hxx>
29 :
30 :
31 : // =======================================================================
32 :
33 : #define MAX_TIMER_PERIOD ((sal_uLong)0xFFFFFFFF)
34 :
35 : // ---------------------
36 : // - TimeManager-Types -
37 : // ---------------------
38 :
39 : struct ImplTimerData
40 : {
41 : ImplTimerData* mpNext; // Pointer to the next Instance
42 : Timer* mpSVTimer; // Pointer to SV Timer instance
43 : sal_uLong mnUpdateTime; // Last Update Time
44 : sal_uLong mnTimerUpdate; // TimerCallbackProcs on stack
45 : sal_Bool mbDelete; // Was timer deleted during Update()?
46 : sal_Bool mbInTimeout; // Are we in a timeout handler?
47 : };
48 :
49 : // =======================================================================
50 :
51 0 : void Timer::ImplDeInitTimer()
52 : {
53 0 : ImplSVData* pSVData = ImplGetSVData();
54 0 : ImplTimerData* pTimerData = pSVData->mpFirstTimerData;
55 :
56 0 : if ( pTimerData )
57 : {
58 0 : do
59 : {
60 0 : ImplTimerData* pTempTimerData = pTimerData;
61 0 : if ( pTimerData->mpSVTimer )
62 : {
63 0 : pTimerData->mpSVTimer->mbActive = sal_False;
64 0 : pTimerData->mpSVTimer->mpTimerData = NULL;
65 : }
66 0 : pTimerData = pTimerData->mpNext;
67 0 : delete pTempTimerData;
68 : }
69 : while ( pTimerData );
70 :
71 0 : pSVData->mpFirstTimerData = NULL;
72 0 : pSVData->mnTimerPeriod = 0;
73 0 : delete pSVData->mpSalTimer;
74 0 : pSVData->mpSalTimer = NULL;
75 : }
76 0 : }
77 :
78 : // -----------------------------------------------------------------------
79 :
80 973 : static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
81 : {
82 973 : if ( !nMS )
83 237 : nMS = 1;
84 :
85 973 : if ( nMS != pSVData->mnTimerPeriod )
86 : {
87 593 : pSVData->mnTimerPeriod = nMS;
88 593 : pSVData->mpSalTimer->Start( nMS );
89 : }
90 973 : }
91 :
92 : // -----------------------------------------------------------------------
93 :
94 473 : void Timer::ImplTimerCallbackProc()
95 : {
96 473 : ImplSVData* pSVData = ImplGetSVData();
97 : ImplTimerData* pTimerData;
98 : ImplTimerData* pPrevTimerData;
99 473 : sal_uLong nMinPeriod = MAX_TIMER_PERIOD;
100 : sal_uLong nDeltaTime;
101 473 : sal_uLong nTime = Time::GetSystemTicks();
102 :
103 473 : if ( pSVData->mbNoCallTimer )
104 473 : return;
105 :
106 473 : pSVData->mnTimerUpdate++;
107 473 : pSVData->mbNotAllTimerCalled = sal_True;
108 :
109 : // find timer where the timer handler needs to be called
110 473 : pTimerData = pSVData->mpFirstTimerData;
111 6437 : while ( pTimerData )
112 : {
113 : // If the timer is not new, was not deleted, and if it is not in the timeout handler, then
114 : // call the handler as soon as the time is up.
115 15373 : if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
116 9882 : !pTimerData->mbDelete && !pTimerData->mbInTimeout )
117 : {
118 : // time has expired
119 4505 : if ( (pTimerData->mnUpdateTime+pTimerData->mpSVTimer->mnTimeout) <= nTime )
120 : {
121 : // set new update time
122 1857 : pTimerData->mnUpdateTime = nTime;
123 :
124 : // if no AutoTimer than stop
125 1857 : if ( !pTimerData->mpSVTimer->mbAuto )
126 : {
127 1640 : pTimerData->mpSVTimer->mbActive = sal_False;
128 1640 : pTimerData->mbDelete = sal_True;
129 : }
130 :
131 : // call Timeout
132 1857 : pTimerData->mbInTimeout = sal_True;
133 1857 : pTimerData->mpSVTimer->Timeout();
134 1857 : pTimerData->mbInTimeout = sal_False;
135 : }
136 : }
137 :
138 5491 : pTimerData = pTimerData->mpNext;
139 : }
140 :
141 : // determine new time
142 473 : sal_uLong nNewTime = Time::GetSystemTicks();
143 473 : pPrevTimerData = NULL;
144 473 : pTimerData = pSVData->mpFirstTimerData;
145 6437 : while ( pTimerData )
146 : {
147 : // ignore if timer is still in timeout handler
148 5491 : if ( pTimerData->mbInTimeout )
149 : {
150 0 : pPrevTimerData = pTimerData;
151 0 : pTimerData = pTimerData->mpNext;
152 : }
153 : // Was timer destroyed in the meantime?
154 5491 : else if ( pTimerData->mbDelete )
155 : {
156 2109 : if ( pPrevTimerData )
157 2102 : pPrevTimerData->mpNext = pTimerData->mpNext;
158 : else
159 7 : pSVData->mpFirstTimerData = pTimerData->mpNext;
160 2109 : if ( pTimerData->mpSVTimer )
161 1494 : pTimerData->mpSVTimer->mpTimerData = NULL;
162 2109 : ImplTimerData* pTempTimerData = pTimerData;
163 2109 : pTimerData = pTimerData->mpNext;
164 2109 : delete pTempTimerData;
165 : }
166 : else
167 : {
168 3382 : pTimerData->mnTimerUpdate = 0;
169 : // determine smallest time slot
170 3382 : if ( pTimerData->mnUpdateTime == nTime )
171 : {
172 201 : nDeltaTime = pTimerData->mpSVTimer->mnTimeout;
173 201 : if ( nDeltaTime < nMinPeriod )
174 67 : nMinPeriod = nDeltaTime;
175 : }
176 : else
177 : {
178 3181 : nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpSVTimer->mnTimeout;
179 3181 : if ( nDeltaTime < nNewTime )
180 637 : nMinPeriod = 1;
181 : else
182 : {
183 2544 : nDeltaTime -= nNewTime;
184 2544 : if ( nDeltaTime < nMinPeriod )
185 1262 : nMinPeriod = nDeltaTime;
186 : }
187 : }
188 3382 : pPrevTimerData = pTimerData;
189 3382 : pTimerData = pTimerData->mpNext;
190 : }
191 : }
192 :
193 : // delete clock if no more timers available
194 473 : if ( !pSVData->mpFirstTimerData )
195 : {
196 0 : pSVData->mpSalTimer->Stop();
197 0 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
198 : }
199 : else
200 473 : ImplStartTimer( pSVData, nMinPeriod );
201 :
202 473 : pSVData->mnTimerUpdate--;
203 473 : pSVData->mbNotAllTimerCalled = sal_False;
204 : }
205 :
206 : // =======================================================================
207 :
208 28666 : Timer::Timer()
209 : {
210 28666 : mpTimerData = NULL;
211 28666 : mnTimeout = 1;
212 28666 : mbAuto = sal_False;
213 28666 : mbActive = sal_False;
214 28666 : }
215 :
216 : // -----------------------------------------------------------------------
217 :
218 8 : Timer::Timer( const Timer& rTimer )
219 : {
220 8 : mpTimerData = NULL;
221 8 : mnTimeout = rTimer.mnTimeout;
222 8 : mbAuto = sal_False;
223 8 : mbActive = sal_False;
224 8 : maTimeoutHdl = rTimer.maTimeoutHdl;
225 :
226 8 : if ( rTimer.IsActive() )
227 0 : Start();
228 8 : }
229 :
230 : // -----------------------------------------------------------------------
231 :
232 19920 : Timer::~Timer()
233 : {
234 19669 : if ( mpTimerData )
235 : {
236 924 : mpTimerData->mbDelete = sal_True;
237 924 : mpTimerData->mpSVTimer = NULL;
238 : }
239 19920 : }
240 :
241 : // -----------------------------------------------------------------------
242 :
243 1855 : void Timer::Timeout()
244 : {
245 1855 : maTimeoutHdl.Call( this );
246 1855 : }
247 :
248 : // -----------------------------------------------------------------------
249 :
250 32593 : void Timer::SetTimeout( sal_uLong nNewTimeout )
251 : {
252 32593 : mnTimeout = nNewTimeout;
253 :
254 : // if timer is active then renew clock
255 32593 : if ( mbActive )
256 : {
257 1512 : ImplSVData* pSVData = ImplGetSVData();
258 1512 : if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
259 0 : ImplStartTimer( pSVData, mnTimeout );
260 : }
261 32593 : }
262 :
263 : // -----------------------------------------------------------------------
264 :
265 24405 : void Timer::Start()
266 : {
267 24405 : mbActive = sal_True;
268 :
269 24405 : ImplSVData* pSVData = ImplGetSVData();
270 24405 : if ( !mpTimerData )
271 : {
272 2966 : if ( !pSVData->mpFirstTimerData )
273 : {
274 19 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
275 19 : if( ! pSVData->mpSalTimer )
276 : {
277 19 : pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
278 19 : pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
279 : }
280 : }
281 :
282 : // insert timer and start
283 2966 : mpTimerData = new ImplTimerData;
284 2966 : mpTimerData->mpSVTimer = this;
285 2966 : mpTimerData->mnUpdateTime = Time::GetSystemTicks();
286 2966 : mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
287 2966 : mpTimerData->mbDelete = sal_False;
288 2966 : mpTimerData->mbInTimeout = sal_False;
289 :
290 : // insert last due to SFX!
291 2966 : ImplTimerData* pPrev = NULL;
292 2966 : ImplTimerData* pData = pSVData->mpFirstTimerData;
293 191471 : while ( pData )
294 : {
295 185539 : pPrev = pData;
296 185539 : pData = pData->mpNext;
297 : }
298 2966 : mpTimerData->mpNext = NULL;
299 2966 : if ( pPrev )
300 2947 : pPrev->mpNext = mpTimerData;
301 : else
302 19 : pSVData->mpFirstTimerData = mpTimerData;
303 :
304 2966 : if ( mnTimeout < pSVData->mnTimerPeriod )
305 500 : ImplStartTimer( pSVData, mnTimeout );
306 : }
307 21439 : else if( !mpTimerData->mpSVTimer ) // TODO: remove when guilty found
308 : {
309 : OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
310 : }
311 : else
312 : {
313 21439 : mpTimerData->mnUpdateTime = Time::GetSystemTicks();
314 21439 : mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
315 21439 : mpTimerData->mbDelete = sal_False;
316 : }
317 24405 : }
318 :
319 : // -----------------------------------------------------------------------
320 :
321 30567 : void Timer::Stop()
322 : {
323 30567 : mbActive = sal_False;
324 :
325 30567 : if ( mpTimerData )
326 9441 : mpTimerData->mbDelete = sal_True;
327 30567 : }
328 :
329 : // -----------------------------------------------------------------------
330 :
331 8 : Timer& Timer::operator=( const Timer& rTimer )
332 : {
333 8 : if ( IsActive() )
334 0 : Stop();
335 :
336 8 : mbActive = sal_False;
337 8 : mnTimeout = rTimer.mnTimeout;
338 8 : maTimeoutHdl = rTimer.maTimeoutHdl;
339 :
340 8 : if ( rTimer.IsActive() )
341 0 : Start();
342 :
343 8 : return *this;
344 : }
345 :
346 : // =======================================================================
347 :
348 1413 : AutoTimer::AutoTimer()
349 : {
350 1413 : mbAuto = sal_True;
351 1413 : }
352 :
353 : // -----------------------------------------------------------------------
354 :
355 8 : AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
356 : {
357 8 : mbAuto = sal_True;
358 8 : }
359 :
360 : // -----------------------------------------------------------------------
361 :
362 8 : AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
363 : {
364 8 : Timer::operator=( rTimer );
365 8 : return *this;
366 : }
367 :
368 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|