* Functions for measuring time in a friendly unit.
*/
-#include <map>
-
#include <boost/bind.hpp>
#include <boost/function.hpp>
+#include <moof/hash.hh>
#include <moof/math.hh>
namespace moof {
+/**
+ * A class to represent a timer for scheduled events. The timer events
+ * will be executed on or sometime after their schedculed time. The
+ * runloop associated with the current running view will make an attempt to
+ * fire any expired timers as close to their scheduled times as possible.
+ */
class timer
{
public:
+ /**
+ * A type for the state of a timer.
+ */
enum mode
{
- invalid = -1,
- normal = 0,
- absolute = 1,
- repeat = 2
+ invalid = -1, /// Timer is not scheduled.
+ relative = 0, /// Timer is scheduled by a relative time.
+ absolute = 1, /// Timer is scheduled by an absolute time.
+ repeat = 2 /// Timer is scheduled by a periodic time.
};
+ /**
+ * Function protocol for a timer event handler. A function matching
+ * this protocol will be called when the timer expires. The function
+ * takes two parameters: the timer object that just expired, and the
+ * absolute time.
+ */
typedef boost::function<void(timer&,scalar)> function;
+ /**
+ * Construct an invalid (uninitialized) timer.
+ */
timer() :
- mode_(invalid) {}
+ mode_(invalid),
+ absolute_(SCALAR(0.0)) {}
- timer(const function& function, scalar seconds, mode mode = normal)
+ /**
+ * Construct a scheduled timer.
+ * \param function The event handler.
+ * \param seconds The number of seconds; the meaning of this depends on
+ * the mode of the timer.
+ * \param mode The timer mode. If the mode is relative (default), the
+ * seconds parameter is the number of seconds from the current time to
+ * wait before expiring the timer. If the mode is absolute, the
+ * seconds parameter is the number of seconds from some arbitrary,
+ * fixed time in the past. If the mode is repeat, the seconds
+ * parameter is the number of seconds from now to wait before expiring
+ * the timer, at which time the timer will be rescheduled to expired
+ * again at that many seconds from the expiration time. A repeating
+ * timer can be invalidated manually using invalidate().
+ */
+ timer(const function& function, scalar seconds, mode mode = relative)
{
init(function, seconds, mode);
}
+ /**
+ * Deconstruct a timer. This will automagically invalidate the timer,
+ * so it will not expire or fire an event.
+ */
~timer()
{
invalidate();
}
- void init(const function& function, scalar seconds, mode mode = normal);
+ /**
+ * Initialize a timer with a scheduled time. If the timer is already
+ * scheduled, its prior schedule will be invalidated and replaced by
+ * this new schedule.
+ * \param function The event handler.
+ * \param seconds The number of seconds; the meaning of this depends on
+ * the mode of the timer.
+ * \param mode The timer mode. If the mode is relative (default), the
+ * seconds parameter is the number of seconds from the current time to
+ * wait before expiring the timer. If the mode is absolute, the
+ * seconds parameter is the number of seconds from some arbitrary,
+ * fixed time in the past. If the mode is repeat, the seconds
+ * parameter is the number of seconds from now to wait before expiring
+ * the timer, at which time the timer will be rescheduled to expired
+ * again at that many seconds from the expiration time. A repeating
+ * timer can be invalidated manually using invalidate().
+ */
+ void init(const function& function,
+ scalar seconds,
+ mode mode = relative);
+
+
+ /**
+ * Get whether or not the timer is valid. If a timer is valid, it is
+ * still scheduled to expired. You can get the time remaining from
+ * seconds_remaining().
+ */
bool is_valid() const;
+
+ /**
+ * Manually invalidated the timer, removing any schedule such that the
+ * timer will not expired and no event will be fired.
+ */
void invalidate();
+
+ /**
+ * Manually fire the timer event. Usually, the timer event will be
+ * fired when the timer expires, but this can be used to fire it
+ * prematurely. If the timer is scheduled, it will be invalidated. If
+ * the timer is already invalid (but is initialized with an event
+ * handler), the event will be fired and the timer will remain invalid.
+ */
void fire();
+
+ /**
+ * Get the number of seconds remaining before the timer is scheduled to
+ * expired. If the timer is invalid, the retured value will be
+ * negative.
+ * \return Seconds.
+ */
scalar seconds_remaining() const;
+
+ /**
+ * Get whether or not the timer is expired. A timer on a repeating
+ * schedule will never be expired since it will always have a scheduled
+ * expiration time in the future. If the timer is expired but not
+ * invalid, the timer event has not yet fired; the timer will be
+ * invalidated when it does fire.
+ * \return True if the timer is expired, false otherwise.
+ */
bool is_expired() const;
+
+ /**
+ * Get whether or not the timer is on a repeating schedule.
+ * \return True if the timer is repeating, false otherwise.
+ */
bool is_repeating() const;
* \param seconds Number of seconds.
* \param mode The timer mode.
*/
- static void sleep(scalar seconds, mode mode = normal);
+ static void sleep(scalar seconds, mode mode = relative);
+ /**
+ * Get the absolute time when the next timer is scheduled to expire.
+ * \return Absolute time, in seconds.
+ */
static scalar next_expiration()
{
- return gNextFire;
+ return next_expiration_;
}
+
+ /**
+ * Fire any timers which are not yet invalidated but have an expiration
+ * time in the past.
+ */
static void fire_expired_timers();
+
+ /**
+ * Fire any timers which are not yet invalidated but have an expiration
+ * time before a given absolute time.
+ */
static void fire_expired_timers(scalar t);
scalar interval_;
unsigned id_;
- static scalar gNextFire;
- static std::map<unsigned,timer*> gTimers;
+ static scalar next_expiration_;
+ static hash<unsigned,timer*,hash_function> timers_;
};