blob: 82084606b8b58f28fabffc175fc292112c6fdd8f [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Realtime timers and timer queues.
20 * This offers ucommon support for realtime high-resolution threadsafe
21 * timers and timer queues. Threads may be scheduled by timers and timer
22 * queues may be used to inject timer events into callback objects or through
23 * virtuals.
24 * @file ucommon/timers.h
25 */
26
27#ifndef _UCOMMON_TIMERS_H_
28#define _UCOMMON_TIMERS_H_
29
30#ifndef _UCOMMON_LINKED_H_
31#include <ucommon/linked.h>
32#endif
33
34#ifndef _MSWINDOWS_
35#include <unistd.h>
36#include <sys/time.h>
37#endif
38
39#include <time.h>
40
41NAMESPACE_UCOMMON
42
43/**
44 * Timer class to use when scheduling realtime events. The timer generally
45 * uses millisecond values but has a microsecond accuracy. On platforms that
46 * support it, the timer uses posix realtime monotonic clock extensions,
47 * otherwise lower accuracy timer systems might be used.
48 */
49class __EXPORT Timer
50{
51private:
52 friend class Conditional;
53 friend class Semaphore;
54 friend class Event;
55
56#if _POSIX_TIMERS > 0 && defined(POSIX_TIMERS)
57 timespec timer;
58#else
59#undef POSIX_TIMERS // make sure not used if no support
60 timeval timer;
61#endif
62 bool updated;
63
64protected:
65 /**
66 * Check if timer has been updated since last check.
67 * @return true if updated.
68 */
69 bool update(void);
70
71 /**
72 * Check if timer active.
73 * @return true if active.
74 */
75 bool is_active(void);
76
77public:
78#if _MSC_VER > 1400 // windows broken dll linkage issue...
79 static const timeout_t inf = ((timeout_t)(-1));
80 static const time_t reset = ((time_t)(0));
81#else
82 static const timeout_t inf; /**< A value to use for infinite time */
83 static const time_t reset; /**< A value to use when resetting */
84#endif
85
86#ifdef _MSWINDOWS_
87 typedef unsigned __int64 tick_t;
88#else
89 typedef uint64_t tick_t;
90#endif
91
92 /**
93 * Construct an untriggered timer set to the time of creation.
94 */
95 Timer();
96
97 /**
98 * Construct a triggered timer that expires at specified offset.
99 * @param offset to expire in milliseconds.
100 */
101 Timer(timeout_t offset);
102
103 /**
104 * Construct a triggered timer that expires at specified offset.
105 * @param offset to expire in seconds.
106 */
107 Timer(time_t offset);
108
109 /**
110 * Construct a timer from a copy of another timer.
111 * @param copy of timer to construct from.
112 */
113 Timer(const Timer& copy);
114
115 /**
116 * Set the timer to expire.
117 * @param expire time in milliseconds.
118 */
119 void set(timeout_t expire);
120
121 /**
122 * Set the timer to expire.
123 * @param expire time in seconds.
124 */
125 void set(time_t expire);
126
127 /**
128 * Set (update) the timer with current time.
129 */
130 void set(void);
131
132 /**
133 * Clear pending timer, has no value.
134 */
135 void clear(void);
136
137 /**
138 * Get remaining time until the timer expires.
139 * @return 0 if expired or milliseconds still waiting.
140 */
141 timeout_t get(void) const;
142
143 /**
144 * Get remaining time until timer expires by reference.
145 * @return 0 if expired or milliseconds still waiting.
146 */
147 inline timeout_t operator*() const
148 {return get();};
149
150 /**
151 * Check if timer has expired.
152 * @return true if timer still pending.
153 */
154 bool operator!() const;
155
156 /**
157 * Check if timer expired for is() expression.
158 * @return true if timer expired.
159 */
160 operator bool() const;
161
162 /**
163 * Set timer expiration.
164 * @param expire timer in specified seconds.
165 */
166 Timer& operator=(time_t expire);
167
168 /**
169 * Set timer expiration.
170 * @param expire timer in milliseconds.
171 */
172 Timer& operator=(timeout_t expire);
173
174 /**
175 * Adjust timer expiration.
176 * @param expire time to add in seconds.
177 */
178 Timer& operator+=(time_t expire);
179
180 /**
181 * Adjust timer expiration.
182 * @param expire time to add in milliseconds.
183 */
184 Timer& operator+=(timeout_t expire);
185
186 /**
187 * Adjust timer expiration.
188 * @param expire time to subtract in seconds.
189 */
190 Timer& operator-=(time_t expire);
191
192 /**
193 * Adjust timer expiration.
194 * @param expire time to subtract in milliseconds.
195 */
196 Timer& operator-=(timeout_t expire);
197
198 /**
199 * Compute difference between two timers.
200 * @param timer to use for difference.
201 * @return difference in milliseconds.
202 */
203 timeout_t operator-(const Timer& timer);
204
205 /**
206 * Compare timers if same timeout.
207 * @param timer to compare with.
208 * @return true if same.
209 */
210 bool operator==(const Timer& timer) const;
211
212 /**
213 * Compare timers if not same timeout.
214 * @param timer to compare with.
215 * @return true if not same.
216 */
217 bool operator!=(const Timer& timer) const;
218
219 /**
220 * Compare timers if earlier timeout than another timer.
221 * @param timer to compare with.
222 * @return true if earlier.
223 */
224 bool operator<(const Timer& timer) const;
225
226 /**
227 * Compare timers if earlier than or equal to another timer.
228 * @param timer to compare with.
229 * @return true if earlier or same.
230 */
231 bool operator<=(const Timer& timer) const;
232
233 /**
234 * Compare timers if later timeout than another timer.
235 * @param timer to compare with.
236 * @return true if later.
237 */
238 bool operator>(const Timer& timer) const;
239
240 /**
241 * Compare timers if later than or equal to another timer.
242 * @param timer to compare with.
243 * @return true if later or same.
244 */
245 bool operator>=(const Timer& timer) const;
246
247 /**
248 * Sleep current thread until the specified timer expires.
249 * @param timer to reference for sleep.
250 */
251 static void sync(Timer &timer);
252
253 /**
254 * Get timer ticks since uuid epoch.
255 * @return timer ticks in 100ns resolution.
256 */
257 static tick_t ticks(void);
258};
259
260/**
261 * A timer queue for timer events. The timer queue is used to hold a
262 * linked list of timers that must be processed together. The timer
263 * queue processes the timer event list and calls an expired function
264 * on events that have expired. The timer queue also determines the
265 * wait time until the next timer will expire. When timer events are
266 * modified, they can retrigger the queue to re-examine the list to
267 * find when the next timer will now expire.
268 * @author David Sugar <dyfet@gnutelephony.org>
269 */
270class __EXPORT TimerQueue : public OrderedIndex
271{
272public:
273 /**
274 * A timer event object that lives on a timer queue. Timer events are
275 * triggered through the timer queue's expire method. Timer events
276 * also modify the queue when they are changed, particularly to force
277 * re-evaluation of the expiration period. This class is not used by
278 * itself but rather as a base class for a timer event object.
279 * @author David Sugar <dyfet@gnutelephony.org>
280 */
281 class __EXPORT event : protected Timer, public LinkedList
282 {
283 protected:
284 friend class TimerQueue;
285
286 /**
287 * Construct a timer event object and initially arm.
288 * @param expire timer in specified milliseconds.
289 */
290 event(timeout_t expire);
291
292 /**
293 * Construct an armed timer event object and attach to queue.
294 * @param queue to add event to.
295 * @param expire timer in specified milliseconds.
296 */
297 event(TimerQueue *queue, timeout_t expire);
298
299 /**
300 * Event method to call in derived class when timer expires.
301 */
302 virtual void expired(void) = 0;
303
304 /**
305 * Expected next timeout for the timer. This may be overriden
306 * for strategy purposes when evaluted by timer queue's expire.
307 * @return milliseconds until timer next triggers.
308 */
309 virtual timeout_t timeout(void);
310
311 public:
312 /**
313 * Detaches from queue when destroyed.
314 */
315 virtual ~event();
316
317 /**
318 * Attach event to a timer queue. Detaches from previous list if
319 * already attached elsewhere.
320 * @param queue to attach to.
321 */
322 void attach(TimerQueue *queue);
323
324 /**
325 * Detach event from a timer queue.
326 */
327 void detach(void);
328
329 /**
330 * Arm event to trigger at specified timeout.
331 * @param timeout to expire and trigger.
332 */
333 void arm(timeout_t timeout);
334
335 /**
336 * Disarm event.
337 */
338 void disarm(void);
339
340 /**
341 * Time remaining until expired.
342 * @return milliseconds until timer expires.
343 */
344 inline timeout_t get(void) const
345 {return Timer::get();};
346
347 /**
348 * Notify timer queue that the timer has been updated.
349 */
350 void update(void);
351
352 /**
353 * Get the timer queue we are attached to.
354 * @return timer queue or NULL if not attached.
355 */
356 inline TimerQueue *list(void)
357 {return static_cast<TimerQueue*>(Root);};
358 };
359
360protected:
361 friend class event;
362
363 /**
364 * Called in derived class when the queue is being modified.
365 * This is often used to lock the list.
366 */
367 virtual void modify(void) = 0;
368
369 /**
370 * Called in derived class after the queue has been modified. This often
371 * releases a lock that modify set and to wakeup a timer thread to
372 * evaluate when the next timer will now expire.
373 */
374 virtual void update(void) = 0;
375
376public:
377 /**
378 * Create an empty timer queue.
379 */
380 TimerQueue();
381
382 /**
383 * Destroy queue, does not remove event objects.
384 */
385 virtual ~TimerQueue();
386
387 /**
388 * Add a timer event to the timer queue.
389 * @param timer event to add.
390 */
391 void operator+=(event &timer);
392
393 /**
394 * Remove a timer event from the timer queue.
395 * @param timer event to remove.
396 */
397 void operator-=(event &timer);
398
399 /**
400 * Process timer queue and find when next event triggers. This function
401 * will call the expired methods on expired timers. Normally this function
402 * will be called in the context of a timer thread which sleeps for the
403 * timeout returned unless it is awoken on an update event.
404 * @return timeout until next timer expires in milliseconds.
405 */
406 timeout_t expire();
407};
408
409/**
410 * A convenience type for timer queue timer events.
411 */
412typedef TimerQueue::event TQEvent;
413
414/**
415 * A convenience type for timers.
416 */
417typedef Timer timer_t;
418
419END_NAMESPACE
420
421extern "C" {
422#if defined(WIN32)
423 __EXPORT int gettimeofday(struct timeval *tv, void *tz);
424#endif
425}
426
427#endif