Alexandre Lision | ddd731e | 2014-01-31 11:50:08 -0500 | [diff] [blame] | 1 | // 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 | |
| 41 | NAMESPACE_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 | */ |
| 49 | class __EXPORT Timer |
| 50 | { |
| 51 | private: |
| 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 | |
| 64 | protected: |
| 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 | |
| 77 | public: |
| 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 | */ |
| 270 | class __EXPORT TimerQueue : public OrderedIndex |
| 271 | { |
| 272 | public: |
| 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 | |
| 360 | protected: |
| 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 | |
| 376 | public: |
| 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 | */ |
| 412 | typedef TimerQueue::event TQEvent; |
| 413 | |
| 414 | /** |
| 415 | * A convenience type for timers. |
| 416 | */ |
| 417 | typedef Timer timer_t; |
| 418 | |
| 419 | END_NAMESPACE |
| 420 | |
| 421 | extern "C" { |
| 422 | #if defined(WIN32) |
| 423 | __EXPORT int gettimeofday(struct timeval *tv, void *tz); |
| 424 | #endif |
| 425 | } |
| 426 | |
| 427 | #endif |