X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fmoof%2Ftimer.hh;h=a429ba955e0206158814ce120661ef54974b6e09;hp=90c53ceb034452208b6262aeb039938ea650369f;hb=44b3014bce798789e795242d1556cb7449e6386a;hpb=d6990468d297a6cbee98e4d0d33ab37e1b2352c9 diff --git a/src/moof/timer.hh b/src/moof/timer.hh index 90c53ce..a429ba9 100644 --- a/src/moof/timer.hh +++ b/src/moof/timer.hh @@ -1,34 +1,68 @@ -/*] Copyright (c) 2009-2010, Charles McGarvey [************************** +/*] Copyright (c) 2009-2011, Charles McGarvey [***************************** **] All rights reserved. * -* vi:ts=4 sw=4 tw=75 -* * Distributable under the terms and conditions of the 2-clause BSD license; * see the file COPYING for a complete text of the license. * -**************************************************************************/ +*****************************************************************************/ #ifndef _MOOF_TIMER_HH_ #define _MOOF_TIMER_HH_ -/** - * \file timer.hh - * Functions for measuring time in a friendly unit. - */ - #include #include #include #include #include -#include +/** + * \file timer.hh + * Functions for measuring time in a friendly unit. + */ + namespace moof { +// forward declarations +class runloop; + +/** + * A timer source is an object that keeps track of increasing time in units + * of seconds. A timer source does not necessarily have to increment at + * the same rate or in the same way as the real time. The time source must + * begin at zero and always remain the same or increase each time the time + * is queried. + */ +class timer_source +{ +public: + + /** + * Deconstruct a timer source. + */ + virtual ~timer_source() {} + + /** + * Get the number seconds since the timer source was created or reset. + */ + virtual scalar ticks() const = 0; + + /** + * Reset the timer such that the current time will become zero. + */ + virtual void reset() = 0; + + /** + * Scale the time. After calling this, the timer source should either + * increment faster or slower, depending on the scale factor. + */ + virtual void scale(scalar factor) = 0; +}; + + /** * A class to represent a timer for scheduled events. The timer events * will be executed on or sometime after their schedculed time. The @@ -44,27 +78,27 @@ public: */ enum mode { - 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. + invalid = 0, /// Timer is not scheduled. + relative = 1, /// Timer is scheduled by a relative time. + absolute = 2, /// Timer is scheduled by an absolute time. + repeat = 3 /// 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. + * absolute time of the time source which caused the timer to expire. */ typedef boost::function function; - /** * Construct an invalid (uninitialized) timer. */ timer() : mode_(invalid), - absolute_(SCALAR(0.0)) {} + absolute_(SCALAR(0.0)), + runloop_(0) {} /** * Construct a scheduled timer. @@ -84,20 +118,17 @@ public: timer(const function& function, scalar seconds, mode mode = relative, - runloop* runloop = runloop::current()) + timer_source& source = default_source()) : + runloop_(0) { - init(function, seconds, mode, runloop); + init(function, seconds, mode, source); } /** * Deconstruct a timer. This will automagically invalidate the timer, * so it will not expire or fire an event. */ - ~timer() - { - invalidate(); - } - + ~timer(); /** * Initialize a timer with a scheduled time. If the timer is already @@ -118,19 +149,8 @@ public: */ void init(const function& function, scalar seconds, - mode mode = relative, - runloop* runloop = runloop::current()); - - - /** - * 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 - { - return mode_ != invalid; - } + enum mode mode = relative, + timer_source& source = default_source()); /** * Manually invalidated the timer, removing any schedule such that the @@ -138,6 +158,10 @@ public: */ void invalidate(); + enum mode mode() const + { + return mode_; + } /** * Manually fire the timer event. Usually, the timer event will be @@ -147,8 +171,11 @@ public: * handler), the event will be fired and the timer will remain invalid. * \param t The absolute time passed to the timer event function. */ - void fire(scalar t = ticks()); - + void fire(scalar t); + void fire() + { + fire(source_->ticks()); + } /** * Fire the timer event if it is expired. @@ -157,12 +184,28 @@ public: * \return The absolute time of the next expiration (if repeating), or * 0.0 otherwise. */ - scalar fire_if_expired(scalar t = ticks()) + bool fire_if_expired(scalar t) { - if (is_expired()) fire(); - return absolute_; + if (is_expired(t)) + { + fire(t); + return true; + } + return false; + } + bool fire_if_expired() + { + return fire_if_expired(source_->ticks()); } + /** + * Get the absolute time of the next expiration of this timer. + * \return Seconds. + */ + scalar expiration() const + { + return absolute_; + } /** * Get the number of seconds remaining before the timer is scheduled to @@ -172,21 +215,15 @@ public: * amount of time left; defaults to the current time. * \return Seconds. */ - scalar seconds_remaining(scalar t = ticks()) const + scalar remaining(scalar t) const { - return next_expiration() - t; + return expiration() - t; } - - /** - * Get the absolute time of the next expiration of this timer. - * \return Seconds. - */ - scalar next_expiration() const + scalar remaining() const { - return absolute_; + return remaining(source_->ticks()); } - /** * 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 @@ -197,53 +234,103 @@ public: * timer is expired; defaults to the current time. * \return True if the timer is expired, false otherwise. */ - bool is_expired(scalar t = ticks()) const + bool is_expired(scalar t) const { - return seconds_remaining(t) < SCALAR(0.0); + return remaining(t) < SCALAR(0.0); } - - /** - * Get whether or not the timer is on a repeating schedule. - * \return True if the timer is repeating, false otherwise. - */ - bool is_repeating() const + bool is_expired() const { - return mode_ == repeat; + return is_expired(source_->ticks()); } + static timer_source& default_source(); /** - * Get the number of seconds since a fixed, arbitrary point in the - * past. + * Get the number of real seconds since the default timer was first + * created or last reset. * \return Seconds. */ static scalar ticks(); - /** * Put the thread to sleep for a certain period of time. If absolute - * is true, then it will sleep until seconds after the fixed time in - * the past. If absolute is false, it will sleep for seconds starting - * now. Unlike system sleep functions, this one automatically resumes - * sleep if sleep was interrupted by a signal. Therefore, calling this - * function is guaranteed to sleep for the requested amount of time - * (and maybe longer). + * is true, then it will sleep until the default timer reaches the + * specified number of seconds. If the mode is relative, the thread + * will sleep for that many seconds. Unlike system sleep functions, + * this one automatically resumes sleep if sleep was interrupted by a + * signal. Therefore, calling this function is guaranteed to sleep for + * at least the requested amount of time. * \param seconds Number of seconds. * \param mode The timer mode. */ - static void sleep(scalar seconds, mode mode = relative); - + static void sleep(scalar seconds, enum mode mode = relative); private: + void added_to_runloop(runloop& runloop); + void detach_from_runloop(); + function function_; - mode mode_; + enum mode mode_; scalar absolute_; scalar interval_; + timer_source* source_; runloop* runloop_; }; +class game_time : public timer_source +{ +public: + + game_time(scalar timestep = SCALAR(1.0)) : + scale_(timestep), + scalefactor_(SCALAR(1.0)) + { + reset(timestep); + } + + scalar ticks() const + { + return reference_ + scalar(ticks_) * scale_; + } + + void reset() + { + reference_ = SCALAR(0.0); + ticks_ = 0; + } + void reset(scalar timestep) + { + reset(); + timestep_ = timestep; + scale_ = timestep_ * scalefactor_; + } + + void scale(scalar factor) + { + reference_ = ticks(); + ticks_ = 0; + scale_ = timestep_ * factor; + scalefactor_ = factor; + } + + scalar step(unsigned step = 1) + { + ticks_ += step; + return scale_; + } + +private: + + scalar reference_; + unsigned ticks_; + scalar timestep_; + scalar scale_; + scalar scalefactor_; +}; + + } // namespace moof #endif // _MOOF_TIMER_HH_