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 : bool mbDelete; // Was timer deleted during Update()?
46 : bool mbInTimeout; // Are we in a timeout handler?
47 : };
48 :
49 : // =======================================================================
50 :
51 94 : void Timer::ImplDeInitTimer()
52 : {
53 94 : ImplSVData* pSVData = ImplGetSVData();
54 94 : ImplTimerData* pTimerData = pSVData->mpFirstTimerData;
55 :
56 94 : if ( pTimerData )
57 : {
58 195 : do
59 : {
60 195 : ImplTimerData* pTempTimerData = pTimerData;
61 195 : if ( pTimerData->mpSVTimer )
62 : {
63 73 : pTimerData->mpSVTimer->mbActive = sal_False;
64 73 : pTimerData->mpSVTimer->mpTimerData = NULL;
65 : }
66 195 : pTimerData = pTimerData->mpNext;
67 195 : delete pTempTimerData;
68 : }
69 : while ( pTimerData );
70 :
71 94 : pSVData->mpFirstTimerData = NULL;
72 94 : pSVData->mnTimerPeriod = 0;
73 94 : delete pSVData->mpSalTimer;
74 94 : pSVData->mpSalTimer = NULL;
75 : }
76 94 : }
77 :
78 : // -----------------------------------------------------------------------
79 :
80 27618 : static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
81 : {
82 27618 : if ( !nMS )
83 1511 : nMS = 1;
84 :
85 27618 : if ( nMS != pSVData->mnTimerPeriod )
86 : {
87 22876 : pSVData->mnTimerPeriod = nMS;
88 22876 : pSVData->mpSalTimer->Start( nMS );
89 : }
90 27618 : }
91 :
92 : // -----------------------------------------------------------------------
93 :
94 16965 : void Timer::ImplTimerCallbackProc()
95 : {
96 16965 : ImplSVData* pSVData = ImplGetSVData();
97 : ImplTimerData* pTimerData;
98 : ImplTimerData* pPrevTimerData;
99 16965 : sal_uLong nMinPeriod = MAX_TIMER_PERIOD;
100 : sal_uLong nDeltaTime;
101 16965 : sal_uLong nTime = Time::GetSystemTicks();
102 :
103 16965 : if ( pSVData->mbNoCallTimer )
104 16965 : return;
105 :
106 16965 : pSVData->mnTimerUpdate++;
107 16965 : pSVData->mbNotAllTimerCalled = sal_True;
108 :
109 : // find timer where the timer handler needs to be called
110 16965 : pTimerData = pSVData->mpFirstTimerData;
111 146752 : 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 221784 : if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
116 205577 : !pTimerData->mbDelete && !pTimerData->mbInTimeout )
117 : {
118 : // time has expired
119 96615 : if ( (pTimerData->mnUpdateTime+pTimerData->mpSVTimer->mnTimeout) <= nTime )
120 : {
121 : // set new update time
122 27983 : pTimerData->mnUpdateTime = nTime;
123 :
124 : // if no AutoTimer than stop
125 27983 : if ( !pTimerData->mpSVTimer->mbAuto )
126 : {
127 21168 : pTimerData->mpSVTimer->mbActive = sal_False;
128 21168 : pTimerData->mbDelete = true;
129 : }
130 :
131 : // call Timeout
132 27983 : pTimerData->mbInTimeout = true;
133 27983 : pTimerData->mpSVTimer->Timeout();
134 27983 : pTimerData->mbInTimeout = false;
135 : }
136 : }
137 :
138 112822 : pTimerData = pTimerData->mpNext;
139 : }
140 :
141 : // determine new time
142 16965 : sal_uLong nNewTime = Time::GetSystemTicks();
143 16965 : pPrevTimerData = NULL;
144 16965 : pTimerData = pSVData->mpFirstTimerData;
145 146752 : while ( pTimerData )
146 : {
147 : // ignore if timer is still in timeout handler
148 112822 : if ( pTimerData->mbInTimeout )
149 : {
150 0 : pPrevTimerData = pTimerData;
151 0 : pTimerData = pTimerData->mpNext;
152 : }
153 : // Was timer destroyed in the meantime?
154 112822 : else if ( pTimerData->mbDelete )
155 : {
156 28867 : if ( pPrevTimerData )
157 28644 : pPrevTimerData->mpNext = pTimerData->mpNext;
158 : else
159 223 : pSVData->mpFirstTimerData = pTimerData->mpNext;
160 28867 : if ( pTimerData->mpSVTimer )
161 17052 : pTimerData->mpSVTimer->mpTimerData = NULL;
162 28867 : ImplTimerData* pTempTimerData = pTimerData;
163 28867 : pTimerData = pTimerData->mpNext;
164 28867 : delete pTempTimerData;
165 : }
166 : else
167 : {
168 83955 : pTimerData->mnTimerUpdate = 0;
169 : // determine smallest time slot
170 83955 : if ( pTimerData->mnUpdateTime == nTime )
171 : {
172 9500 : nDeltaTime = pTimerData->mpSVTimer->mnTimeout;
173 9500 : if ( nDeltaTime < nMinPeriod )
174 6267 : nMinPeriod = nDeltaTime;
175 : }
176 : else
177 : {
178 74455 : nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpSVTimer->mnTimeout;
179 74455 : if ( nDeltaTime < nNewTime )
180 9989 : nMinPeriod = 1;
181 : else
182 : {
183 64466 : nDeltaTime -= nNewTime;
184 64466 : if ( nDeltaTime < nMinPeriod )
185 33282 : nMinPeriod = nDeltaTime;
186 : }
187 : }
188 83955 : pPrevTimerData = pTimerData;
189 83955 : pTimerData = pTimerData->mpNext;
190 : }
191 : }
192 :
193 : // delete clock if no more timers available
194 16965 : if ( !pSVData->mpFirstTimerData )
195 : {
196 50 : pSVData->mpSalTimer->Stop();
197 50 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
198 : }
199 : else
200 16915 : ImplStartTimer( pSVData, nMinPeriod );
201 :
202 16965 : pSVData->mnTimerUpdate--;
203 16965 : pSVData->mbNotAllTimerCalled = sal_False;
204 : }
205 :
206 : // =======================================================================
207 :
208 170786 : Timer::Timer()
209 : {
210 170786 : mpTimerData = NULL;
211 170786 : mnTimeout = 1;
212 170786 : mbAuto = sal_False;
213 170786 : mbActive = sal_False;
214 170786 : }
215 :
216 : // -----------------------------------------------------------------------
217 :
218 417 : Timer::Timer( const Timer& rTimer )
219 : {
220 417 : mpTimerData = NULL;
221 417 : mnTimeout = rTimer.mnTimeout;
222 417 : mbAuto = sal_False;
223 417 : mbActive = sal_False;
224 417 : maTimeoutHdl = rTimer.maTimeoutHdl;
225 :
226 417 : if ( rTimer.IsActive() )
227 38 : Start();
228 417 : }
229 :
230 : // -----------------------------------------------------------------------
231 :
232 172149 : Timer::~Timer()
233 : {
234 170103 : if ( mpTimerData )
235 : {
236 13219 : mpTimerData->mbDelete = true;
237 13219 : mpTimerData->mpSVTimer = NULL;
238 : }
239 172149 : }
240 :
241 : // -----------------------------------------------------------------------
242 :
243 25913 : void Timer::Timeout()
244 : {
245 25913 : maTimeoutHdl.Call( this );
246 25913 : }
247 :
248 : // -----------------------------------------------------------------------
249 :
250 227531 : void Timer::SetTimeout( sal_uLong nNewTimeout )
251 : {
252 227531 : mnTimeout = nNewTimeout;
253 :
254 : // if timer is active then renew clock
255 227531 : if ( mbActive )
256 : {
257 8171 : ImplSVData* pSVData = ImplGetSVData();
258 8171 : if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
259 0 : ImplStartTimer( pSVData, mnTimeout );
260 : }
261 227531 : }
262 :
263 : // -----------------------------------------------------------------------
264 :
265 491228 : void Timer::Start()
266 : {
267 491228 : mbActive = sal_True;
268 :
269 491228 : ImplSVData* pSVData = ImplGetSVData();
270 491228 : if ( !mpTimerData )
271 : {
272 30575 : if ( !pSVData->mpFirstTimerData )
273 : {
274 183 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
275 183 : if( ! pSVData->mpSalTimer )
276 : {
277 133 : pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
278 133 : pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
279 : }
280 : }
281 :
282 : // insert timer and start
283 30575 : mpTimerData = new ImplTimerData;
284 30575 : mpTimerData->mpSVTimer = this;
285 30575 : mpTimerData->mnUpdateTime = Time::GetSystemTicks();
286 30575 : mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
287 30575 : mpTimerData->mbDelete = false;
288 30575 : mpTimerData->mbInTimeout = false;
289 :
290 : // insert last due to SFX!
291 30575 : ImplTimerData* pPrev = NULL;
292 30575 : ImplTimerData* pData = pSVData->mpFirstTimerData;
293 712621 : while ( pData )
294 : {
295 651471 : pPrev = pData;
296 651471 : pData = pData->mpNext;
297 : }
298 30575 : mpTimerData->mpNext = NULL;
299 30575 : if ( pPrev )
300 30392 : pPrev->mpNext = mpTimerData;
301 : else
302 183 : pSVData->mpFirstTimerData = mpTimerData;
303 :
304 30575 : if ( mnTimeout < pSVData->mnTimerPeriod )
305 10703 : ImplStartTimer( pSVData, mnTimeout );
306 : }
307 460653 : else if( !mpTimerData->mpSVTimer ) // TODO: remove when guilty found
308 : {
309 : OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
310 : }
311 : else
312 : {
313 460653 : mpTimerData->mnUpdateTime = Time::GetSystemTicks();
314 460653 : mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
315 460653 : mpTimerData->mbDelete = false;
316 : }
317 491228 : }
318 :
319 : // -----------------------------------------------------------------------
320 :
321 350182 : void Timer::Stop()
322 : {
323 350182 : mbActive = sal_False;
324 :
325 350182 : if ( mpTimerData )
326 153277 : mpTimerData->mbDelete = true;
327 350182 : }
328 :
329 : // -----------------------------------------------------------------------
330 :
331 49 : Timer& Timer::operator=( const Timer& rTimer )
332 : {
333 49 : if ( IsActive() )
334 12 : Stop();
335 :
336 49 : mbActive = sal_False;
337 49 : mnTimeout = rTimer.mnTimeout;
338 49 : maTimeoutHdl = rTimer.maTimeoutHdl;
339 :
340 49 : if ( rTimer.IsActive() )
341 14 : Start();
342 :
343 49 : return *this;
344 : }
345 :
346 : // =======================================================================
347 :
348 11987 : AutoTimer::AutoTimer()
349 : {
350 11987 : mbAuto = sal_True;
351 11987 : }
352 :
353 : // -----------------------------------------------------------------------
354 :
355 417 : AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
356 : {
357 417 : mbAuto = sal_True;
358 417 : }
359 :
360 : // -----------------------------------------------------------------------
361 :
362 49 : AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
363 : {
364 49 : Timer::operator=( rTimer );
365 49 : return *this;
366 465 : }
367 :
368 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|