LibreOffice Module salhelper (master) 1
timer.cxx
Go to the documentation of this file.
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#include <salhelper/timer.hxx>
20
21#include <osl/thread.hxx>
22#include <osl/conditn.hxx>
23
24#include <mutex>
25
26using namespace salhelper;
27
28class salhelper::TimerManager : public osl::Thread
29{
30public:
32
34 void registerTimer(salhelper::Timer* pTimer);
35
37 void unregisterTimer(salhelper::Timer const * pTimer);
38
40 bool lookupTimer(const salhelper::Timer* pTimer);
41
42protected:
44 virtual void SAL_CALL run() override;
45
47 void checkForTimeout();
48
52 std::mutex m_Lock;
54 osl::Condition m_notEmpty;
55
57 //static salhelper::TimerManager* m_pManager;
58
59};
60
61namespace
62{
63 salhelper::TimerManager& getTimerManager()
64 {
65 static salhelper::TimerManager aManager;
66 return aManager;
67 }
68}
69
70
72 : m_aTimeOut(0),
73 m_aExpired(0),
74 m_aRepeatDelta(0),
75 m_pNext(nullptr)
76{
77}
78
80 : m_aTimeOut(rTime),
81 m_aExpired(0),
82 m_aRepeatDelta(0),
83 m_pNext(nullptr)
84{
85}
86
87Timer::Timer(const TTimeValue& rTime, const TTimeValue& Repeat)
88 : m_aTimeOut(rTime),
89 m_aExpired(0),
90 m_aRepeatDelta(Repeat),
91 m_pNext(nullptr)
92{
93}
94
96{
97 stop();
98}
99
101{
102 if (!isTicking())
103 {
104 if (!m_aTimeOut.isEmpty())
106
107 getTimerManager().registerTimer(this);
108 }
109}
110
112{
113 getTimerManager().unregisterTimer(this);
114}
115
117{
118 return getTimerManager().lookupTimer(this);
119}
120
122{
123 TTimeValue Now;
124
125 osl_getSystemTime(&Now);
126
127 return !(Now < m_aExpired);
128}
129
131{
132 if (pTimer)
133 return m_aExpired < pTimer->m_aExpired;
134 else
135 return false;
136}
137
139{
140 m_aTimeOut = 0;
142 m_aRepeatDelta = 0;
143
145}
146
148{
149 osl_getSystemTime(&m_aExpired);
150
151 m_aExpired.addTime(Remaining);
152}
153
154void Timer::setRemainingTime(const TTimeValue& Remaining, const TTimeValue& Repeat)
155{
156 osl_getSystemTime(&m_aExpired);
157
158 m_aExpired.addTime(Remaining);
159
161}
162
163void Timer::addTime(const TTimeValue& Delta)
164{
166}
167
169{
170 TTimeValue Now;
171
172 osl_getSystemTime(&Now);
173
174 sal_Int32 secs = m_aExpired.Seconds - Now.Seconds;
175
176 if (secs < 0)
177 return TTimeValue(0, 0);
178
179 sal_Int32 nsecs = m_aExpired.Nanosec - Now.Nanosec;
180
181 if (nsecs < 0)
182 {
183 if (secs > 0)
184 {
185 secs -= 1;
186 nsecs += 1000000000;
187 }
188 else
189 return TTimeValue(0, 0);
190 }
191
192 return TTimeValue(secs, nsecs);
193}
194
206 m_pHead(nullptr)
207{
208 m_notEmpty.reset();
209
210 // start thread
211 create();
212}
213
215{
216 if (!pTimer)
217 return;
218
219 std::lock_guard Guard(m_Lock);
220
221 // try to find one with equal or lower remaining time.
222 Timer** ppIter = &m_pHead;
223
224 while (*ppIter)
225 {
226 if (pTimer->expiresBefore(*ppIter))
227 {
228 // next element has higher remaining time,
229 // => insert new timer before
230 break;
231 }
232 ppIter= &((*ppIter)->m_pNext);
233 }
234
235 // next element has higher remaining time,
236 // => insert new timer before
237 pTimer->m_pNext= *ppIter;
238 *ppIter = pTimer;
239
240
241 if (pTimer == m_pHead)
242 {
243 // it was inserted as new head
244 // signal it to TimerManager Thread
245 m_notEmpty.set();
246 }
247}
248
250{
251 if (!pTimer)
252 return;
253
254 // lock access
255 std::lock_guard Guard(m_Lock);
256
257 Timer** ppIter = &m_pHead;
258
259 while (*ppIter)
260 {
261 if (pTimer == (*ppIter))
262 {
263 // remove timer from list
264 *ppIter = (*ppIter)->m_pNext;
265 return;
266 }
267 ppIter= &((*ppIter)->m_pNext);
268 }
269}
270
272{
273 if (!pTimer)
274 return false;
275
276 // lock access
277 std::lock_guard Guard(m_Lock);
278
279 // check the list
280 for (Timer* pIter = m_pHead; pIter != nullptr; pIter= pIter->m_pNext)
281 {
282 if (pIter == pTimer)
283 return true;
284 }
285
286 return false;
287}
288
290{
291 std::unique_lock aLock (m_Lock);
292
293 if (!m_pHead)
294 {
295 return;
296 }
297
298 Timer* pTimer = m_pHead;
299
300 if (!pTimer->isExpired())
301 return;
302
303 // remove expired timer
304 m_pHead = pTimer->m_pNext;
305
306 pTimer->acquire();
307
308 aLock.unlock();
309
310 pTimer->onShot();
311
312 // restart timer if specified
313 if (!pTimer->m_aRepeatDelta.isEmpty())
314 {
315 TTimeValue Now;
316
317 osl_getSystemTime(&Now);
318
319 Now.Seconds += pTimer->m_aRepeatDelta.Seconds;
320 Now.Nanosec += pTimer->m_aRepeatDelta.Nanosec;
321
322 pTimer->m_aExpired = Now;
323
324 registerTimer(pTimer);
325 }
326 pTimer->release();
327}
328
330{
331 osl_setThreadName("salhelper::TimerManager");
332
333 setPriority( osl_Thread_PriorityBelowNormal );
334
335 while (schedule())
336 {
337 TTimeValue delay;
338 TTimeValue* pDelay=nullptr;
339
340 {
341 std::lock_guard a_Guard(m_Lock);
342
343 if (m_pHead != nullptr)
344 {
345 delay = m_pHead->getRemainingTime();
346 pDelay=&delay;
347 }
348 else
349 {
350 pDelay=nullptr;
351 }
352
353
354 m_notEmpty.reset();
355 }
356
357 m_notEmpty.wait(pDelay);
358
360 }
361
362}
363
364/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Timer(const char *pDebugName)
osl::Condition m_notEmpty
Signal the insertion of a timer.
Definition: timer.cxx:54
bool lookupTimer(const salhelper::Timer *pTimer)
lookup timer
Definition: timer.cxx:271
salhelper::Timer * m_pHead
sorted-queue data
Definition: timer.cxx:50
std::mutex m_Lock
List Protection.
Definition: timer.cxx:52
TimerManager()
The timer manager cleanup has been removed (no thread is killed anymore), so the thread leaks.
Definition: timer.cxx:205
virtual void SAL_CALL run() override
worker-function of thread
Definition: timer.cxx:329
void unregisterTimer(salhelper::Timer const *pTimer)
unregister timer
Definition: timer.cxx:249
void checkForTimeout()
Checking and triggering of a timer event.
Definition: timer.cxx:289
void registerTimer(salhelper::Timer *pTimer)
register timer
Definition: timer.cxx:214
Interface for the Timer and handling the event.
Definition: timer.hxx:124
TTimeValue SAL_CALL getRemainingTime() const
Returns the remaining time before timer expiration relative to now.
Definition: timer.cxx:168
virtual ~Timer() SAL_OVERRIDE
Destructor.
Definition: timer.cxx:95
void SAL_CALL start()
Start timer.
Definition: timer.cxx:100
virtual void SAL_CALL onShot()=0
What should be done when the 'timer fires'.
TTimeValue m_aTimeOut
holds (initial) expiration time of this timer.
Definition: timer.hxx:194
Timer()
Constructor.
Definition: timer.cxx:71
void SAL_CALL stop()
Abort timer prematurely.
Definition: timer.cxx:111
sal_Bool SAL_CALL isExpired() const
Is the timer expired?
Definition: timer.cxx:121
sal_Bool SAL_CALL expiresBefore(const Timer *pTimer) const
Does pTimer expires before us?
Definition: timer.cxx:130
Timer * m_pNext
Pointer to the next timer (to fire).
Definition: timer.hxx:206
void SAL_CALL setAbsoluteTime(const TTimeValue &Time)
Set the absolute time when the timer should fire.
Definition: timer.cxx:138
TTimeValue m_aExpired
holds the time of expiration of this timer.
Definition: timer.hxx:198
void SAL_CALL setRemainingTime(const TTimeValue &Remaining)
Set the time to fire to 'now' + Remaining.
Definition: timer.cxx:147
TTimeValue m_aRepeatDelta
holds the time interveal of successive expirations.
Definition: timer.hxx:202
void SAL_CALL addTime(const TTimeValue &Time)
Adds Time to the 'fire time'.
Definition: timer.cxx:163
sal_Bool SAL_CALL isTicking() const
Returns sal_True if timer is running.
Definition: timer.cxx:116
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
Delta
Helper class for easier manipulation with TimeValue.
Definition: timer.hxx:39
void SAL_CALL normalize()
Definition: timer.hxx:70
bool SAL_CALL isEmpty() const
Definition: timer.hxx:87
void SAL_CALL addTime(const TTimeValue &Delta)
Definition: timer.hxx:79
unsigned char sal_Bool