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 : #include <tools/time.hxx>
21 :
22 : #include <vcl/svapp.hxx>
23 : #include <vcl/timer.hxx>
24 :
25 : #include <saltimer.hxx>
26 : #include <svdata.hxx>
27 : #include <salinst.hxx>
28 :
29 : #define MAX_TIMER_PERIOD ((sal_uLong)0xFFFFFFFF)
30 :
31 : struct ImplTimerData
32 : {
33 : ImplTimerData* mpNext; // Pointer to the next Instance
34 : Timer* mpTimer; // Pointer to VCL Timer instance
35 : sal_uLong mnUpdateTime; // Last Update Time
36 : sal_uLong mnTimerUpdate; // TimerCallbackProcs on stack
37 : bool mbDelete; // Was timer deleted during Update()?
38 : bool mbInTimeout; // Are we in a timeout handler?
39 : };
40 :
41 174 : void Timer::ImplDeInitTimer()
42 : {
43 174 : ImplSVData* pSVData = ImplGetSVData();
44 174 : ImplTimerData* pTimerData = pSVData->mpFirstTimerData;
45 :
46 174 : if ( pTimerData )
47 : {
48 1184 : do
49 : {
50 1184 : ImplTimerData* pTempTimerData = pTimerData;
51 1184 : if ( pTimerData->mpTimer )
52 : {
53 146 : pTimerData->mpTimer->mbActive = false;
54 146 : pTimerData->mpTimer->mpTimerData = NULL;
55 : }
56 1184 : pTimerData = pTimerData->mpNext;
57 1184 : delete pTempTimerData;
58 : }
59 : while ( pTimerData );
60 :
61 159 : pSVData->mpFirstTimerData = NULL;
62 159 : pSVData->mnTimerPeriod = 0;
63 159 : delete pSVData->mpSalTimer;
64 159 : pSVData->mpSalTimer = NULL;
65 : }
66 174 : }
67 :
68 36879 : static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
69 : {
70 36879 : if ( !nMS )
71 2570 : nMS = 1;
72 :
73 36879 : if ( nMS != pSVData->mnTimerPeriod )
74 : {
75 30755 : pSVData->mnTimerPeriod = nMS;
76 30755 : pSVData->mpSalTimer->Start( nMS );
77 : }
78 36879 : }
79 :
80 21960 : void Timer::ImplTimerCallbackProc()
81 : {
82 21960 : ImplSVData* pSVData = ImplGetSVData();
83 : ImplTimerData* pTimerData;
84 : ImplTimerData* pPrevTimerData;
85 21960 : sal_uLong nMinPeriod = MAX_TIMER_PERIOD;
86 : sal_uLong nDeltaTime;
87 21960 : sal_uLong nTime = Time::GetSystemTicks();
88 :
89 21960 : if ( pSVData->mbNoCallTimer )
90 21960 : return;
91 :
92 21960 : pSVData->mnTimerUpdate++;
93 21960 : pSVData->mbNotAllTimerCalled = true;
94 :
95 : // find timer where the timer handler needs to be called
96 21960 : pTimerData = pSVData->mpFirstTimerData;
97 193015 : while ( pTimerData )
98 : {
99 : // If the timer is not new, was not deleted, and if it is not in the timeout handler, then
100 : // call the handler as soon as the time is up.
101 295714 : if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
102 270663 : !pTimerData->mbDelete && !pTimerData->mbInTimeout )
103 : {
104 : // time has expired
105 124044 : if ( (pTimerData->mnUpdateTime+pTimerData->mpTimer->mnTimeout) <= nTime )
106 : {
107 : // set new update time
108 33724 : pTimerData->mnUpdateTime = nTime;
109 :
110 : // if no AutoTimer than stop
111 33724 : if ( !pTimerData->mpTimer->mbAuto )
112 : {
113 26339 : pTimerData->mpTimer->mbActive = false;
114 26339 : pTimerData->mbDelete = true;
115 : }
116 :
117 : // call Timeout
118 33724 : pTimerData->mbInTimeout = true;
119 33724 : pTimerData->mpTimer->Timeout();
120 33724 : pTimerData->mbInTimeout = false;
121 : }
122 : }
123 :
124 149095 : pTimerData = pTimerData->mpNext;
125 : }
126 :
127 : // determine new time
128 21960 : sal_uLong nNewTime = Time::GetSystemTicks();
129 21960 : pPrevTimerData = NULL;
130 21960 : pTimerData = pSVData->mpFirstTimerData;
131 193015 : while ( pTimerData )
132 : {
133 : // ignore if timer is still in timeout handler
134 149095 : if ( pTimerData->mbInTimeout )
135 : {
136 0 : pPrevTimerData = pTimerData;
137 0 : pTimerData = pTimerData->mpNext;
138 : }
139 : // Was timer destroyed in the meantime?
140 149095 : else if ( pTimerData->mbDelete )
141 : {
142 41962 : if ( pPrevTimerData )
143 41710 : pPrevTimerData->mpNext = pTimerData->mpNext;
144 : else
145 252 : pSVData->mpFirstTimerData = pTimerData->mpNext;
146 41962 : if ( pTimerData->mpTimer )
147 22774 : pTimerData->mpTimer->mpTimerData = NULL;
148 41962 : ImplTimerData* pTempTimerData = pTimerData;
149 41962 : pTimerData = pTimerData->mpNext;
150 41962 : delete pTempTimerData;
151 : }
152 : else
153 : {
154 107133 : pTimerData->mnTimerUpdate = 0;
155 : // determine smallest time slot
156 107133 : if ( pTimerData->mnUpdateTime == nTime )
157 : {
158 12799 : nDeltaTime = pTimerData->mpTimer->mnTimeout;
159 12799 : if ( nDeltaTime < nMinPeriod )
160 8962 : nMinPeriod = nDeltaTime;
161 : }
162 : else
163 : {
164 94334 : nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpTimer->mnTimeout;
165 94334 : if ( nDeltaTime < nNewTime )
166 9810 : nMinPeriod = 1;
167 : else
168 : {
169 84524 : nDeltaTime -= nNewTime;
170 84524 : if ( nDeltaTime < nMinPeriod )
171 45545 : nMinPeriod = nDeltaTime;
172 : }
173 : }
174 107133 : pPrevTimerData = pTimerData;
175 107133 : pTimerData = pTimerData->mpNext;
176 : }
177 : }
178 :
179 : // delete clock if no more timers available
180 21960 : if ( !pSVData->mpFirstTimerData )
181 : {
182 61 : pSVData->mpSalTimer->Stop();
183 61 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
184 : }
185 : else
186 21899 : ImplStartTimer( pSVData, nMinPeriod );
187 :
188 21960 : pSVData->mnTimerUpdate--;
189 21960 : pSVData->mbNotAllTimerCalled = false;
190 : }
191 :
192 248729 : Timer::Timer():
193 : mpTimerData(NULL),
194 : mnTimeout(1),
195 : mbActive(false),
196 248729 : mbAuto(false)
197 : {
198 248729 : }
199 :
200 417 : Timer::Timer( const Timer& rTimer ):
201 : mpTimerData(NULL),
202 : mnTimeout(rTimer.mnTimeout),
203 : mbActive(false),
204 : mbAuto(false),
205 417 : maTimeoutHdl(rTimer.maTimeoutHdl)
206 : {
207 417 : if ( rTimer.IsActive() )
208 38 : Start();
209 417 : }
210 :
211 244365 : Timer::~Timer()
212 : {
213 240593 : if ( mpTimerData )
214 : {
215 21084 : mpTimerData->mbDelete = true;
216 21084 : mpTimerData->mpTimer = NULL;
217 : }
218 244365 : }
219 :
220 30845 : void Timer::Timeout()
221 : {
222 30845 : maTimeoutHdl.Call( this );
223 30845 : }
224 :
225 331518 : void Timer::SetTimeout( sal_uLong nNewTimeout )
226 : {
227 331518 : mnTimeout = nNewTimeout;
228 :
229 : // if timer is active then renew clock
230 331518 : if ( mbActive )
231 : {
232 14513 : ImplSVData* pSVData = ImplGetSVData();
233 14513 : if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
234 0 : ImplStartTimer( pSVData, mnTimeout );
235 : }
236 331518 : }
237 :
238 539070 : void Timer::Start()
239 : {
240 539070 : mbActive = true;
241 :
242 539070 : ImplSVData* pSVData = ImplGetSVData();
243 539070 : if ( !mpTimerData )
244 : {
245 44386 : if ( !pSVData->mpFirstTimerData )
246 : {
247 272 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
248 272 : if( ! pSVData->mpSalTimer )
249 : {
250 211 : pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
251 211 : pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
252 : }
253 : }
254 :
255 : // insert timer and start
256 44386 : mpTimerData = new ImplTimerData;
257 44386 : mpTimerData->mpTimer = this;
258 44386 : mpTimerData->mnUpdateTime = Time::GetSystemTicks();
259 44386 : mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
260 44386 : mpTimerData->mbDelete = false;
261 44386 : mpTimerData->mbInTimeout = false;
262 :
263 : // insert last due to SFX!
264 44386 : ImplTimerData* pPrev = NULL;
265 44386 : ImplTimerData* pData = pSVData->mpFirstTimerData;
266 887347 : while ( pData )
267 : {
268 798575 : pPrev = pData;
269 798575 : pData = pData->mpNext;
270 : }
271 44386 : mpTimerData->mpNext = NULL;
272 44386 : if ( pPrev )
273 44114 : pPrev->mpNext = mpTimerData;
274 : else
275 272 : pSVData->mpFirstTimerData = mpTimerData;
276 :
277 44386 : if ( mnTimeout < pSVData->mnTimerPeriod )
278 14980 : ImplStartTimer( pSVData, mnTimeout );
279 : }
280 494684 : else if( !mpTimerData->mpTimer ) // TODO: remove when guilty found
281 : {
282 : OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
283 : }
284 : else
285 : {
286 494684 : mpTimerData->mnUpdateTime = Time::GetSystemTicks();
287 494684 : mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
288 494684 : mpTimerData->mbDelete = false;
289 : }
290 539070 : }
291 :
292 463864 : void Timer::Stop()
293 : {
294 463864 : mbActive = false;
295 :
296 463864 : if ( mpTimerData )
297 204789 : mpTimerData->mbDelete = true;
298 463864 : }
299 :
300 49 : Timer& Timer::operator=( const Timer& rTimer )
301 : {
302 49 : if ( IsActive() )
303 12 : Stop();
304 :
305 49 : mbActive = false;
306 49 : mnTimeout = rTimer.mnTimeout;
307 49 : maTimeoutHdl = rTimer.maTimeoutHdl;
308 :
309 49 : if ( rTimer.IsActive() )
310 14 : Start();
311 :
312 49 : return *this;
313 : }
314 :
315 18075 : AutoTimer::AutoTimer()
316 : {
317 18075 : mbAuto = true;
318 18075 : }
319 :
320 417 : AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
321 : {
322 417 : mbAuto = true;
323 417 : }
324 :
325 49 : AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
326 : {
327 49 : Timer::operator=( rTimer );
328 49 : return *this;
329 : }
330 :
331 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|