1//
2// Timer.h
3//
4// Library: Foundation
5// Package: Threading
6// Module: Timer
7//
8// Definition of the Timer and related classes.
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_Timer_INCLUDED
18#define Foundation_Timer_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Runnable.h"
23#include "Poco/Mutex.h"
24#include "Poco/Event.h"
25#include "Poco/Thread.h"
26#include "Poco/Clock.h"
27
28
29namespace Poco {
30
31
32class AbstractTimerCallback;
33class ThreadPool;
34
35
36class Foundation_API Timer: protected Runnable
37 /// This class implements a thread-based timer.
38 /// A timer starts a thread that first waits for a given start interval.
39 /// Once that interval expires, the timer callback is called repeatedly
40 /// in the given periodic interval. If the interval is 0, the timer is only
41 /// called once.
42 /// The timer callback method can stop the timer by setting the
43 /// timer's periodic interval to 0.
44 ///
45 /// The timer callback runs in its own thread, so multithreading
46 /// issues (proper synchronization) have to be considered when writing
47 /// the callback method.
48 ///
49 /// The exact interval at which the callback is called depends on many
50 /// factors like operating system, CPU performance and system load and
51 /// may differ from the specified interval.
52 ///
53 /// The time needed to execute the timer callback is not included
54 /// in the interval between invocations. For example, if the interval
55 /// is 500 milliseconds, and the callback needs 400 milliseconds to
56 /// execute, the callback function is nevertheless called every 500
57 /// milliseconds. If the callback takes longer to execute than the
58 /// interval, the callback function will not be called until the next
59 /// proper interval. The number of skipped invocations since the last
60 /// invocation will be recorded and can be obtained by the callback
61 /// by calling skipped().
62 ///
63 /// The timer thread is taken from a thread pool, so
64 /// there is a limit to the number of available concurrent timers.
65{
66public:
67 Timer(long startInterval = 0, long periodicInterval = 0);
68 /// Creates a new timer object. StartInterval and periodicInterval
69 /// are given in milliseconds. If a periodicInterval of zero is
70 /// specified, the callback will only be called once, after the
71 /// startInterval expires.
72 /// To start the timer, call the Start() method.
73
74 virtual ~Timer();
75 /// Stops and destroys the timer.
76
77 void start(const AbstractTimerCallback& method);
78 /// Starts the timer.
79 /// Create the TimerCallback as follows:
80 /// TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
81 /// timer.start(callback);
82 ///
83 /// The timer thread is taken from the global default thread pool.
84
85 void start(const AbstractTimerCallback& method, Thread::Priority priority);
86 /// Starts the timer in a thread with the given priority.
87 /// Create the TimerCallback as follows:
88 /// TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
89 /// timer.start(callback);
90 ///
91 /// The timer thread is taken from the global default thread pool.
92
93 void start(const AbstractTimerCallback& method, ThreadPool& threadPool);
94 /// Starts the timer.
95 /// Create the TimerCallback as follows:
96 /// TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
97 /// timer.start(callback);
98
99 void start(const AbstractTimerCallback& method, Thread::Priority priority, ThreadPool& threadPool);
100 /// Starts the timer in a thread with the given priority.
101 /// Create the TimerCallback as follows:
102 /// TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
103 /// timer.start(callback);
104
105 void stop();
106 /// Stops the timer. If the callback method is currently running
107 /// it will be allowed to finish first.
108 /// WARNING: Never call this method from within the callback method,
109 /// as a deadlock would result. To stop the timer from within the
110 /// callback method, call restart(0).
111
112 void restart();
113 /// Restarts the periodic interval. If the callback method is already running,
114 /// nothing will happen.
115
116 void restart(long milliseconds);
117 /// Sets a new periodic interval and restarts the timer.
118 /// An interval of 0 will stop the timer.
119
120 long getStartInterval() const;
121 /// Returns the start interval.
122
123 void setStartInterval(long milliseconds);
124 /// Sets the start interval. Will only be
125 /// effective before start() is called.
126
127 long getPeriodicInterval() const;
128 /// Returns the periodic interval.
129
130 void setPeriodicInterval(long milliseconds);
131 /// Sets the periodic interval. If the timer is already running
132 /// the new interval will be effective when the current interval
133 /// expires.
134
135 long skipped() const;
136 /// Returns the number of skipped invocations since the last invocation.
137 /// Skipped invocations happen if the timer callback function takes
138 /// longer to execute than the timer interval.
139
140protected:
141 void run();
142
143private:
144 volatile long _startInterval;
145 volatile long _periodicInterval;
146 Event _wakeUp;
147 Event _done;
148 long _skipped;
149 AbstractTimerCallback* _pCallback;
150 Clock _nextInvocation;
151 mutable FastMutex _mutex;
152
153 Timer(const Timer&);
154 Timer& operator = (const Timer&);
155};
156
157
158class Foundation_API AbstractTimerCallback
159 /// This is the base class for all instantiations of
160 /// the TimerCallback template.
161{
162public:
163 AbstractTimerCallback();
164 AbstractTimerCallback(const AbstractTimerCallback& callback);
165 virtual ~AbstractTimerCallback();
166
167 AbstractTimerCallback& operator = (const AbstractTimerCallback& callback);
168
169 virtual void invoke(Timer& timer) const = 0;
170 virtual AbstractTimerCallback* clone() const = 0;
171};
172
173
174template <class C>
175class TimerCallback: public AbstractTimerCallback
176 /// This template class implements an adapter that sits between
177 /// a Timer and an object's method invoked by the timer.
178 /// It is quite similar in concept to the RunnableAdapter, but provides
179 /// some Timer specific additional methods.
180 /// See the Timer class for information on how
181 /// to use this template class.
182{
183public:
184 typedef void (C::*Callback)(Timer&);
185
186 TimerCallback(C& object, Callback method): _pObject(&object), _method(method)
187 {
188 }
189
190 TimerCallback(const TimerCallback& callback):AbstractTimerCallback(), _pObject(callback._pObject), _method(callback._method)
191 {
192 }
193
194 ~TimerCallback()
195 {
196 }
197
198 TimerCallback& operator = (const TimerCallback& callback)
199 {
200 if (&callback != this)
201 {
202 _pObject = callback._pObject;
203 _method = callback._method;
204 }
205 return *this;
206 }
207
208 void invoke(Timer& timer) const
209 {
210 (_pObject->*_method)(timer);
211 }
212
213 AbstractTimerCallback* clone() const
214 {
215 return new TimerCallback(*this);
216 }
217
218private:
219 TimerCallback();
220
221 C* _pObject;
222 Callback _method;
223};
224
225
226} // namespace Poco
227
228
229#endif // Foundation_Timer_INCLUDED
230