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