update credits
[LibreOffice.git] / vcl / source / app / timer.cxx
blobde5efcae8bbbf84e3debc98e7c6225e06d257112
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <tools/time.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/timer.hxx>
26 #include <saltimer.hxx>
27 #include <svdata.hxx>
28 #include <salinst.hxx>
31 // =======================================================================
33 #define MAX_TIMER_PERIOD ((sal_uLong)0xFFFFFFFF)
35 // ---------------------
36 // - TimeManager-Types -
37 // ---------------------
39 struct ImplTimerData
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?
49 // =======================================================================
51 void Timer::ImplDeInitTimer()
53 ImplSVData* pSVData = ImplGetSVData();
54 ImplTimerData* pTimerData = pSVData->mpFirstTimerData;
56 if ( pTimerData )
60 ImplTimerData* pTempTimerData = pTimerData;
61 if ( pTimerData->mpSVTimer )
63 pTimerData->mpSVTimer->mbActive = sal_False;
64 pTimerData->mpSVTimer->mpTimerData = NULL;
66 pTimerData = pTimerData->mpNext;
67 delete pTempTimerData;
69 while ( pTimerData );
71 pSVData->mpFirstTimerData = NULL;
72 pSVData->mnTimerPeriod = 0;
73 delete pSVData->mpSalTimer;
74 pSVData->mpSalTimer = NULL;
78 // -----------------------------------------------------------------------
80 static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
82 if ( !nMS )
83 nMS = 1;
85 if ( nMS != pSVData->mnTimerPeriod )
87 pSVData->mnTimerPeriod = nMS;
88 pSVData->mpSalTimer->Start( nMS );
92 // -----------------------------------------------------------------------
94 void Timer::ImplTimerCallbackProc()
96 ImplSVData* pSVData = ImplGetSVData();
97 ImplTimerData* pTimerData;
98 ImplTimerData* pPrevTimerData;
99 sal_uLong nMinPeriod = MAX_TIMER_PERIOD;
100 sal_uLong nDeltaTime;
101 sal_uLong nTime = Time::GetSystemTicks();
103 if ( pSVData->mbNoCallTimer )
104 return;
106 pSVData->mnTimerUpdate++;
107 pSVData->mbNotAllTimerCalled = sal_True;
109 // find timer where the timer handler needs to be called
110 pTimerData = pSVData->mpFirstTimerData;
111 while ( pTimerData )
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 if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
116 !pTimerData->mbDelete && !pTimerData->mbInTimeout )
118 // time has expired
119 if ( (pTimerData->mnUpdateTime+pTimerData->mpSVTimer->mnTimeout) <= nTime )
121 // set new update time
122 pTimerData->mnUpdateTime = nTime;
124 // if no AutoTimer than stop
125 if ( !pTimerData->mpSVTimer->mbAuto )
127 pTimerData->mpSVTimer->mbActive = sal_False;
128 pTimerData->mbDelete = true;
131 // call Timeout
132 pTimerData->mbInTimeout = true;
133 pTimerData->mpSVTimer->Timeout();
134 pTimerData->mbInTimeout = false;
138 pTimerData = pTimerData->mpNext;
141 // determine new time
142 sal_uLong nNewTime = Time::GetSystemTicks();
143 pPrevTimerData = NULL;
144 pTimerData = pSVData->mpFirstTimerData;
145 while ( pTimerData )
147 // ignore if timer is still in timeout handler
148 if ( pTimerData->mbInTimeout )
150 pPrevTimerData = pTimerData;
151 pTimerData = pTimerData->mpNext;
153 // Was timer destroyed in the meantime?
154 else if ( pTimerData->mbDelete )
156 if ( pPrevTimerData )
157 pPrevTimerData->mpNext = pTimerData->mpNext;
158 else
159 pSVData->mpFirstTimerData = pTimerData->mpNext;
160 if ( pTimerData->mpSVTimer )
161 pTimerData->mpSVTimer->mpTimerData = NULL;
162 ImplTimerData* pTempTimerData = pTimerData;
163 pTimerData = pTimerData->mpNext;
164 delete pTempTimerData;
166 else
168 pTimerData->mnTimerUpdate = 0;
169 // determine smallest time slot
170 if ( pTimerData->mnUpdateTime == nTime )
172 nDeltaTime = pTimerData->mpSVTimer->mnTimeout;
173 if ( nDeltaTime < nMinPeriod )
174 nMinPeriod = nDeltaTime;
176 else
178 nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpSVTimer->mnTimeout;
179 if ( nDeltaTime < nNewTime )
180 nMinPeriod = 1;
181 else
183 nDeltaTime -= nNewTime;
184 if ( nDeltaTime < nMinPeriod )
185 nMinPeriod = nDeltaTime;
188 pPrevTimerData = pTimerData;
189 pTimerData = pTimerData->mpNext;
193 // delete clock if no more timers available
194 if ( !pSVData->mpFirstTimerData )
196 pSVData->mpSalTimer->Stop();
197 pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
199 else
200 ImplStartTimer( pSVData, nMinPeriod );
202 pSVData->mnTimerUpdate--;
203 pSVData->mbNotAllTimerCalled = sal_False;
206 // =======================================================================
208 Timer::Timer()
210 mpTimerData = NULL;
211 mnTimeout = 1;
212 mbAuto = sal_False;
213 mbActive = sal_False;
216 // -----------------------------------------------------------------------
218 Timer::Timer( const Timer& rTimer )
220 mpTimerData = NULL;
221 mnTimeout = rTimer.mnTimeout;
222 mbAuto = sal_False;
223 mbActive = sal_False;
224 maTimeoutHdl = rTimer.maTimeoutHdl;
226 if ( rTimer.IsActive() )
227 Start();
230 // -----------------------------------------------------------------------
232 Timer::~Timer()
234 if ( mpTimerData )
236 mpTimerData->mbDelete = true;
237 mpTimerData->mpSVTimer = NULL;
241 // -----------------------------------------------------------------------
243 void Timer::Timeout()
245 maTimeoutHdl.Call( this );
248 // -----------------------------------------------------------------------
250 void Timer::SetTimeout( sal_uLong nNewTimeout )
252 mnTimeout = nNewTimeout;
254 // if timer is active then renew clock
255 if ( mbActive )
257 ImplSVData* pSVData = ImplGetSVData();
258 if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
259 ImplStartTimer( pSVData, mnTimeout );
263 // -----------------------------------------------------------------------
265 void Timer::Start()
267 mbActive = sal_True;
269 ImplSVData* pSVData = ImplGetSVData();
270 if ( !mpTimerData )
272 if ( !pSVData->mpFirstTimerData )
274 pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
275 if( ! pSVData->mpSalTimer )
277 pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
278 pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
282 // insert timer and start
283 mpTimerData = new ImplTimerData;
284 mpTimerData->mpSVTimer = this;
285 mpTimerData->mnUpdateTime = Time::GetSystemTicks();
286 mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
287 mpTimerData->mbDelete = false;
288 mpTimerData->mbInTimeout = false;
290 // insert last due to SFX!
291 ImplTimerData* pPrev = NULL;
292 ImplTimerData* pData = pSVData->mpFirstTimerData;
293 while ( pData )
295 pPrev = pData;
296 pData = pData->mpNext;
298 mpTimerData->mpNext = NULL;
299 if ( pPrev )
300 pPrev->mpNext = mpTimerData;
301 else
302 pSVData->mpFirstTimerData = mpTimerData;
304 if ( mnTimeout < pSVData->mnTimerPeriod )
305 ImplStartTimer( pSVData, mnTimeout );
307 else if( !mpTimerData->mpSVTimer ) // TODO: remove when guilty found
309 OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
311 else
313 mpTimerData->mnUpdateTime = Time::GetSystemTicks();
314 mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
315 mpTimerData->mbDelete = false;
319 // -----------------------------------------------------------------------
321 void Timer::Stop()
323 mbActive = sal_False;
325 if ( mpTimerData )
326 mpTimerData->mbDelete = true;
329 // -----------------------------------------------------------------------
331 Timer& Timer::operator=( const Timer& rTimer )
333 if ( IsActive() )
334 Stop();
336 mbActive = sal_False;
337 mnTimeout = rTimer.mnTimeout;
338 maTimeoutHdl = rTimer.maTimeoutHdl;
340 if ( rTimer.IsActive() )
341 Start();
343 return *this;
346 // =======================================================================
348 AutoTimer::AutoTimer()
350 mbAuto = sal_True;
353 // -----------------------------------------------------------------------
355 AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
357 mbAuto = sal_True;
360 // -----------------------------------------------------------------------
362 AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
364 Timer::operator=( rTimer );
365 return *this;
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */