Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <tools/time.hxx>
31 : :
32 : : #include <vcl/svapp.hxx>
33 : : #include <vcl/timer.hxx>
34 : :
35 : : #include <saltimer.hxx>
36 : : #include <svdata.hxx>
37 : : #include <salinst.hxx>
38 : :
39 : :
40 : : // =======================================================================
41 : :
42 : : #define MAX_TIMER_PERIOD ((sal_uLong)0xFFFFFFFF)
43 : :
44 : : // ---------------------
45 : : // - TimeManager-Types -
46 : : // ---------------------
47 : :
48 : : struct ImplTimerData
49 : : {
50 : : ImplTimerData* mpNext; // Pointer to the next Instance
51 : : Timer* mpSVTimer; // Pointer to SV Timer instance
52 : : sal_uLong mnUpdateTime; // Last Update Time
53 : : sal_uLong mnTimerUpdate; // TimerCallbackProcs on stack
54 : : sal_Bool mbDelete; // Was timer deleted during Update()?
55 : : sal_Bool mbInTimeout; // Are we in a timeout handler?
56 : : };
57 : :
58 : : // =======================================================================
59 : :
60 : 158 : void Timer::ImplDeInitTimer()
61 : : {
62 : 158 : ImplSVData* pSVData = ImplGetSVData();
63 : 158 : ImplTimerData* pTimerData = pSVData->mpFirstTimerData;
64 : :
65 [ + - ]: 158 : if ( pTimerData )
66 : : {
67 [ + + ]: 362 : do
68 : : {
69 : 362 : ImplTimerData* pTempTimerData = pTimerData;
70 [ + + ]: 362 : if ( pTimerData->mpSVTimer )
71 : : {
72 : 155 : pTimerData->mpSVTimer->mbActive = sal_False;
73 : 155 : pTimerData->mpSVTimer->mpTimerData = NULL;
74 : : }
75 : 362 : pTimerData = pTimerData->mpNext;
76 : 362 : delete pTempTimerData;
77 : : }
78 : : while ( pTimerData );
79 : :
80 : 158 : pSVData->mpFirstTimerData = NULL;
81 : 158 : pSVData->mnTimerPeriod = 0;
82 [ + - ]: 158 : delete pSVData->mpSalTimer;
83 : 158 : pSVData->mpSalTimer = NULL;
84 : : }
85 : 158 : }
86 : :
87 : : // -----------------------------------------------------------------------
88 : :
89 : 52609 : static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
90 : : {
91 [ + + ]: 52609 : if ( !nMS )
92 : 2602 : nMS = 1;
93 : :
94 [ + + ]: 52609 : if ( nMS != pSVData->mnTimerPeriod )
95 : : {
96 : 43475 : pSVData->mnTimerPeriod = nMS;
97 : 43475 : pSVData->mpSalTimer->Start( nMS );
98 : : }
99 : 52609 : }
100 : :
101 : : // -----------------------------------------------------------------------
102 : :
103 : 33012 : void Timer::ImplTimerCallbackProc()
104 : : {
105 : 33012 : ImplSVData* pSVData = ImplGetSVData();
106 : : ImplTimerData* pTimerData;
107 : : ImplTimerData* pPrevTimerData;
108 : 33012 : sal_uLong nMinPeriod = MAX_TIMER_PERIOD;
109 : : sal_uLong nDeltaTime;
110 : 33012 : sal_uLong nTime = Time::GetSystemTicks();
111 : :
112 [ - + ]: 33012 : if ( pSVData->mbNoCallTimer )
113 : 33012 : return;
114 : :
115 : 33012 : pSVData->mnTimerUpdate++;
116 : 33012 : pSVData->mbNotAllTimerCalled = sal_True;
117 : :
118 : : // find timer where the timer handler needs to be called
119 : 33012 : pTimerData = pSVData->mpFirstTimerData;
120 [ + + ]: 266061 : while ( pTimerData )
121 : : {
122 : : // If the timer is not new, was not deleted, and if it is not in the timeout handler, then
123 : : // call the handler as soon as the time is up.
124 [ + + ][ + + ]: 233049 : if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
[ + - ]
125 : 433423 : !pTimerData->mbDelete && !pTimerData->mbInTimeout )
126 : : {
127 : : // time has expired
128 [ + + ]: 206662 : if ( (pTimerData->mnUpdateTime+pTimerData->mpSVTimer->mnTimeout) <= nTime )
129 : : {
130 : : // set new update time
131 : 58935 : pTimerData->mnUpdateTime = nTime;
132 : :
133 : : // if no AutoTimer than stop
134 [ + + ]: 58935 : if ( !pTimerData->mpSVTimer->mbAuto )
135 : : {
136 : 45528 : pTimerData->mpSVTimer->mbActive = sal_False;
137 : 45528 : pTimerData->mbDelete = sal_True;
138 : : }
139 : :
140 : : // call Timeout
141 : 58935 : pTimerData->mbInTimeout = sal_True;
142 : 58935 : pTimerData->mpSVTimer->Timeout();
143 : 58935 : pTimerData->mbInTimeout = sal_False;
144 : : }
145 : : }
146 : :
147 : 233049 : pTimerData = pTimerData->mpNext;
148 : : }
149 : :
150 : : // determine new time
151 : 33012 : sal_uLong nNewTime = Time::GetSystemTicks();
152 : 33012 : pPrevTimerData = NULL;
153 : 33012 : pTimerData = pSVData->mpFirstTimerData;
154 [ + + ]: 266061 : while ( pTimerData )
155 : : {
156 : : // ignore if timer is still in timeout handler
157 [ - + ]: 233049 : if ( pTimerData->mbInTimeout )
158 : : {
159 : 0 : pPrevTimerData = pTimerData;
160 : 0 : pTimerData = pTimerData->mpNext;
161 : : }
162 : : // Was timer destroyed in the meantime?
163 [ + + ]: 233049 : else if ( pTimerData->mbDelete )
164 : : {
165 [ + + ]: 50039 : if ( pPrevTimerData )
166 : 49611 : pPrevTimerData->mpNext = pTimerData->mpNext;
167 : : else
168 : 428 : pSVData->mpFirstTimerData = pTimerData->mpNext;
169 [ + + ]: 50039 : if ( pTimerData->mpSVTimer )
170 : 32535 : pTimerData->mpSVTimer->mpTimerData = NULL;
171 : 50039 : ImplTimerData* pTempTimerData = pTimerData;
172 : 50039 : pTimerData = pTimerData->mpNext;
173 : 50039 : delete pTempTimerData;
174 : : }
175 : : else
176 : : {
177 : 183010 : pTimerData->mnTimerUpdate = 0;
178 : : // determine smallest time slot
179 [ + + ]: 183010 : if ( pTimerData->mnUpdateTime == nTime )
180 : : {
181 : 19301 : nDeltaTime = pTimerData->mpSVTimer->mnTimeout;
182 [ + + ]: 19301 : if ( nDeltaTime < nMinPeriod )
183 : 12117 : nMinPeriod = nDeltaTime;
184 : : }
185 : : else
186 : : {
187 : 163709 : nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpSVTimer->mnTimeout;
188 [ + + ]: 163709 : if ( nDeltaTime < nNewTime )
189 : 22364 : nMinPeriod = 1;
190 : : else
191 : : {
192 : 141345 : nDeltaTime -= nNewTime;
193 [ + + ]: 141345 : if ( nDeltaTime < nMinPeriod )
194 : 79630 : nMinPeriod = nDeltaTime;
195 : : }
196 : : }
197 : 183010 : pPrevTimerData = pTimerData;
198 : 183010 : pTimerData = pTimerData->mpNext;
199 : : }
200 : : }
201 : :
202 : : // delete clock if no more timers available
203 [ + + ]: 33012 : if ( !pSVData->mpFirstTimerData )
204 : : {
205 : 93 : pSVData->mpSalTimer->Stop();
206 : 93 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
207 : : }
208 : : else
209 : 32919 : ImplStartTimer( pSVData, nMinPeriod );
210 : :
211 : 33012 : pSVData->mnTimerUpdate--;
212 : 33012 : pSVData->mbNotAllTimerCalled = sal_False;
213 : : }
214 : :
215 : : // =======================================================================
216 : :
217 : 280561 : Timer::Timer()
218 : : {
219 : 280561 : mpTimerData = NULL;
220 : 280561 : mnTimeout = 1;
221 : 280561 : mbAuto = sal_False;
222 : 280561 : mbActive = sal_False;
223 : 280561 : }
224 : :
225 : : // -----------------------------------------------------------------------
226 : :
227 : 602 : Timer::Timer( const Timer& rTimer )
228 : : {
229 : 602 : mpTimerData = NULL;
230 : 602 : mnTimeout = rTimer.mnTimeout;
231 : 602 : mbAuto = sal_False;
232 : 602 : mbActive = sal_False;
233 : 602 : maTimeoutHdl = rTimer.maTimeoutHdl;
234 : :
235 [ + + ]: 602 : if ( rTimer.IsActive() )
236 : 44 : Start();
237 : 602 : }
238 : :
239 : : // -----------------------------------------------------------------------
240 : :
241 : 278941 : Timer::~Timer()
242 : : {
243 [ + + ]: 275575 : if ( mpTimerData )
244 : : {
245 : 20105 : mpTimerData->mbDelete = sal_True;
246 : 20105 : mpTimerData->mpSVTimer = NULL;
247 : : }
248 [ - + ]: 278941 : }
249 : :
250 : : // -----------------------------------------------------------------------
251 : :
252 : 54392 : void Timer::Timeout()
253 : : {
254 : 54392 : maTimeoutHdl.Call( this );
255 : 54392 : }
256 : :
257 : : // -----------------------------------------------------------------------
258 : :
259 : 377160 : void Timer::SetTimeout( sal_uLong nNewTimeout )
260 : : {
261 : 377160 : mnTimeout = nNewTimeout;
262 : :
263 : : // if timer is active then renew clock
264 [ + + ]: 377160 : if ( mbActive )
265 : : {
266 : 14144 : ImplSVData* pSVData = ImplGetSVData();
267 [ - + ][ + + ]: 14144 : if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
268 : 0 : ImplStartTimer( pSVData, mnTimeout );
269 : : }
270 : 377160 : }
271 : :
272 : : // -----------------------------------------------------------------------
273 : :
274 : 265979 : void Timer::Start()
275 : : {
276 : 265979 : mbActive = sal_True;
277 : :
278 : 265979 : ImplSVData* pSVData = ImplGetSVData();
279 [ + + ]: 265979 : if ( !mpTimerData )
280 : : {
281 [ + + ]: 53263 : if ( !pSVData->mpFirstTimerData )
282 : : {
283 : 326 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
284 [ + + ]: 326 : if( ! pSVData->mpSalTimer )
285 : : {
286 : 233 : pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
287 : 233 : pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
288 : : }
289 : : }
290 : :
291 : : // insert timer and start
292 : 53263 : mpTimerData = new ImplTimerData;
293 : 53263 : mpTimerData->mpSVTimer = this;
294 : 53263 : mpTimerData->mnUpdateTime = Time::GetSystemTicks();
295 : 53263 : mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
296 : 53263 : mpTimerData->mbDelete = sal_False;
297 : 53263 : mpTimerData->mbInTimeout = sal_False;
298 : :
299 : : // insert last due to SFX!
300 : 53263 : ImplTimerData* pPrev = NULL;
301 : 53263 : ImplTimerData* pData = pSVData->mpFirstTimerData;
302 [ + + ]: 722919 : while ( pData )
303 : : {
304 : 669656 : pPrev = pData;
305 : 669656 : pData = pData->mpNext;
306 : : }
307 : 53263 : mpTimerData->mpNext = NULL;
308 [ + + ]: 53263 : if ( pPrev )
309 : 52937 : pPrev->mpNext = mpTimerData;
310 : : else
311 : 326 : pSVData->mpFirstTimerData = mpTimerData;
312 : :
313 [ + + ]: 53263 : if ( mnTimeout < pSVData->mnTimerPeriod )
314 : 19690 : ImplStartTimer( pSVData, mnTimeout );
315 : : }
316 [ + - ]: 212716 : else if( !mpTimerData->mpSVTimer ) // TODO: remove when guilty found
317 : : {
318 : : OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
319 : : }
320 : : else
321 : : {
322 : 212716 : mpTimerData->mnUpdateTime = Time::GetSystemTicks();
323 : 212716 : mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
324 : 212716 : mpTimerData->mbDelete = sal_False;
325 : : }
326 : 265979 : }
327 : :
328 : : // -----------------------------------------------------------------------
329 : :
330 : 596196 : void Timer::Stop()
331 : : {
332 : 596196 : mbActive = sal_False;
333 : :
334 [ + + ]: 596196 : if ( mpTimerData )
335 : 261291 : mpTimerData->mbDelete = sal_True;
336 : 596196 : }
337 : :
338 : : // -----------------------------------------------------------------------
339 : :
340 : 48 : Timer& Timer::operator=( const Timer& rTimer )
341 : : {
342 [ + + ]: 48 : if ( IsActive() )
343 : 14 : Stop();
344 : :
345 : 48 : mbActive = sal_False;
346 : 48 : mnTimeout = rTimer.mnTimeout;
347 : 48 : maTimeoutHdl = rTimer.maTimeoutHdl;
348 : :
349 [ + + ]: 48 : if ( rTimer.IsActive() )
350 : 16 : Start();
351 : :
352 : 48 : return *this;
353 : : }
354 : :
355 : : // =======================================================================
356 : :
357 : 19681 : AutoTimer::AutoTimer()
358 : : {
359 : 19681 : mbAuto = sal_True;
360 : 19681 : }
361 : :
362 : : // -----------------------------------------------------------------------
363 : :
364 : 602 : AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
365 : : {
366 : 602 : mbAuto = sal_True;
367 : 602 : }
368 : :
369 : : // -----------------------------------------------------------------------
370 : :
371 : 48 : AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
372 : : {
373 : 48 : Timer::operator=( rTimer );
374 : 48 : return *this;
375 : : }
376 : :
377 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|