-// -*- mode: C++; indent-tabs-mode: nil; -*-
-#ifndef _BLACKBOX_Timer_hh
-#define _BLACKBOX_Timer_hh
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+#ifndef __timer_hh
+#define __timer_hh
+
+/*! @file timer.hh
+ @brief Contains the Timer class, used for timed callbacks.
+*/
extern "C" {
#ifdef TIME_WITH_SYS_TIME
}
#include <queue>
-#include <algorithm>
#include <vector>
namespace otk {
-// forward declaration
-class OBTimerQueueManager;
-
-typedef void *OBTimeoutData;
-typedef void (*OBTimeoutHandler)(OBTimeoutData);
-
-class OBTimer {
-private:
- OBTimerQueueManager *manager;
- OBTimeoutHandler handler;
- OBTimeoutData data;
- bool timing, recur;
-
- timeval _start, _timeout;
-
- OBTimer(const OBTimer&);
- OBTimer& operator=(const OBTimer&);
-
+//! The Timer class implements timed callbacks.
+/*!
+ The Timer class can be used to have a callback fire after a given time
+ interval. A created Timer will fire repetitively until it is destroyed.
+*/
+class Timer {
public:
- OBTimer(OBTimerQueueManager *m, OBTimeoutHandler h, OBTimeoutData d);
- virtual ~OBTimer();
-
- void fireTimeout();
-
- inline bool isTiming() const { return timing; }
- inline bool isRecurring() const { return recur; }
-
- inline const timeval &getTimeout() const { return _timeout; }
- inline const timeval &getStartTime() const { return _start; }
-
- timeval timeRemaining(const timeval &tm) const;
- bool shouldFire(const timeval &tm) const;
- timeval endpoint() const;
-
- inline void recurring(bool b) { recur = b; }
-
- void setTimeout(long t);
- void setTimeout(const timeval &t);
-
- void start(); // manager acquires timer
- void stop(); // manager releases timer
- void halt(); // halts the timer
-
- bool operator<(const OBTimer& other) const
- { return shouldFire(other.endpoint()); }
-};
-
+ //! Data type of Timer callback
+ typedef void (*TimeoutHandler)(void *data);
-template <class _Tp, class _Sequence, class _Compare>
-class _timer_queue: protected std::priority_queue<_Tp, _Sequence, _Compare> {
-public:
- typedef std::priority_queue<_Tp, _Sequence, _Compare> _Base;
-
- _timer_queue(): _Base() {}
- ~_timer_queue() {}
-
- void release(const _Tp& value) {
- c.erase(std::remove(c.begin(), c.end(), value), c.end());
- // after removing the item we need to make the heap again
- std::make_heap(c.begin(), c.end(), comp);
- }
- bool empty() const { return _Base::empty(); }
- size_t size() const { return _Base::size(); }
- void push(const _Tp& value) { _Base::push(value); }
- void pop() { _Base::pop(); }
- const _Tp& top() const { return _Base::top(); }
private:
- // no copying!
- _timer_queue(const _timer_queue&) {}
- _timer_queue& operator=(const _timer_queue&) {}
-};
-
-struct TimerLessThan {
- bool operator()(const OBTimer* const l, const OBTimer* const r) const {
- return *r < *l;
- }
-};
+ //! Compares two timeval structs
+ struct TimerCompare {
+ //! Compares two timeval structs
+ inline bool operator()(const Timer *a, const Timer *b) const {
+ return timercmp(&a->_timeout, &b->_timeout, >);
+ }
+ };
+ friend struct TimerCompare; // give access to _timeout for shitty compilers
+
+ typedef
+ std::priority_queue<Timer*, std::vector<Timer*>, TimerCompare> TimerQ;
+
+ //! Milliseconds between timer firings
+ long _delay;
+ //! Callback for timer expiry
+ TimeoutHandler _action;
+ //! Data sent to callback
+ void *_data;
+ //! We overload the delete operator to just set this to true
+ bool _del_me;
+ //! The time the last fire should've been at
+ struct timeval _last;
+ //! When this timer will next trigger
+ struct timeval _timeout;
+
+ //! Queue of pending timers
+ static TimerQ _q;
+ //! Time next timer will expire
+ static timeval _nearest_timeout;
+ //! Time at start of current processing loop
+ static timeval _now;
+
+ //! Really delete something (not just flag for later)
+ /*!
+ @param self Timer to be deleted.
+ */
+ static void realDelete(Timer *self);
-typedef _timer_queue<OBTimer*,
- std::vector<OBTimer*>, TimerLessThan> TimerQueue;
+ //! Adds a millisecond delay to a timeval structure
+ /*!
+ @param a Amount of time to increment.
+ @param msec Number of milliseconds to increment by.
+ */
+ static void timevalAdd(timeval &a, long msec);
-//! Manages a queue of OBTimer objects
-/*!
- All OBTimer objects add themself to an OBTimerQueueManager. The manager is
- what fires the timers when their time has elapsed. This is done by having the
- application call the OBTimerQueueManager::fire class in its main event loop.
-*/
-class OBTimerQueueManager {
-private:
- //! A priority queue of all timers being managed by this class.
- TimerQueue timerList;
public:
- //! Constructs a new OBTimerQueueManager
- OBTimerQueueManager() {}
- //! Destroys the OBTimerQueueManager
- virtual ~OBTimerQueueManager() {}
+ //! Constructs a new running timer and queues it
+ /*!
+ @param delay Time in milliseconds between firings
+ @param cb The function to be called on fire.
+ @param data Data to be passed to the callback on fire.
+ */
+ Timer(long delay, TimeoutHandler cb, void *data);
- //! Will wait for and fire the next timer in the queue.
+ //! Overloaded delete so we can leave deleted objects in queue for later reap
/*!
- The function will stop waiting if an event is received from the X server.
+ @param self Pointer to current instance of Timer.
*/
- virtual void fire();
+ void operator delete(void *self);
- //! Adds a new timer to the queue
+ //! Dispatches all elligible timers, then optionally waits for X events
/*!
- @param timer An OBTimer to add to the queue
+ @param wait Whether to wait for X events after processing timers.
*/
- virtual void addTimer(OBTimer* timer);
- //! Removes a timer from the queue
+ static void dispatchTimers(bool wait = true);
+
+ //! Returns a relative timeval (to pass select) of the next timer
/*!
- @param timer An OBTimer already in the queue to remove
+ @param tm Changed to hold the time until next timer.
+ @return true if there are any timers queued, and the timeout is being
+ returned in 'tm'. false if there are no timers queued.
*/
- virtual void removeTimer(OBTimer* timer);
+ static bool nearestTimeout(struct timeval &tm);
+
+ //! Initializes internal data before use
+ static void initialize(void);
+
+ //! Deletes all waiting timers
+ static void destroy(void);
};
}
-#endif // _BLACKBOX_Timer_hh
+#endif // __timer.hh