diff options
author | Chris Wilson <chris+github@qwirx.com> | 2006-11-06 20:43:12 +0000 |
---|---|---|
committer | Chris Wilson <chris+github@qwirx.com> | 2006-11-06 20:43:12 +0000 |
commit | 3a590d43ce5e108e42483993b3ce7bfaaa20d74d (patch) | |
tree | 56aeb826bce234eb3f2fe5e747fe8194a84d9c42 /lib | |
parent | ee4dc408e4ce8364322ea19a4fabbb5e8edf4d46 (diff) |
Added generic timer support class
Diffstat (limited to 'lib')
-rw-r--r-- | lib/common/BoxTime.h | 5 | ||||
-rw-r--r-- | lib/common/Timer.cpp | 252 | ||||
-rw-r--r-- | lib/common/Timer.h | 65 |
3 files changed, 321 insertions, 1 deletions
diff --git a/lib/common/BoxTime.h b/lib/common/BoxTime.h index 398e6b1c..e62a77ab 100644 --- a/lib/common/BoxTime.h +++ b/lib/common/BoxTime.h @@ -35,6 +35,9 @@ inline uint64_t BoxTimeToMilliSeconds(box_time_t Time) { return Time / MILLI_SEC_IN_NANO_SEC_LL; } +inline uint64_t BoxTimeToMicroSeconds(box_time_t Time) +{ + return Time; +} #endif // BOXTIME__H - diff --git a/lib/common/Timer.cpp b/lib/common/Timer.cpp new file mode 100644 index 00000000..e05affb2 --- /dev/null +++ b/lib/common/Timer.cpp @@ -0,0 +1,252 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: Timer.cpp +// Purpose: Generic timers which execute arbitrary code when +// they expire. +// Created: 5/11/2006 +// +// -------------------------------------------------------------------------- + +#include "Box.h" + +#include <signal.h> + +#include "Timer.h" + +#include "MemLeakFindOn.h" + +std::vector<Timer*> Timers::sTimers; +bool Timers::sInitialised = false; + +// -------------------------------------------------------------------------- +// +// Function +// Name: static void TimerSigHandler(int) +// Purpose: Signal handler, notifies Timers class +// Created: 19/3/04 +// +// -------------------------------------------------------------------------- +static void TimerSigHandler(int iUnused) +{ + Timers::Signal(); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: static void Timers::Init() +// Purpose: Initialise timers, prepare signal handler +// Created: 5/11/2006 +// +// -------------------------------------------------------------------------- +void Timers::Init() +{ + ASSERT(!sInitialised); + + #ifdef PLATFORM_CYGWIN + ASSERT(::signal(SIGALRM, TimerSigHandler) == 0); + #elif defined WIN32 + // no support for signals at all + InitTimer(); + SetTimerHandler(TimerSigHandler); + #else + ASSERT(::signal(SIGALRM, TimerSigHandler) == 0); + #endif // PLATFORM_CYGWIN + + sInitialised = true; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: static void Timers::Cleanup() +// Purpose: Clean up timers, stop signal handler +// Created: 6/11/2006 +// +// -------------------------------------------------------------------------- +void Timers::Cleanup() +{ + ASSERT(sInitialised); + + #ifdef PLATFORM_CYGWIN + ASSERT(::signal(SIGALRM, NULL) == TimerSigHandler); + #elif defined WIN32 + // no support for signals at all + SetTimerHandler(NULL); + FiniTimer(); + #else + ASSERT(::signal(SIGALRM, NULL) == TimerSigHandler); + #endif // PLATFORM_CYGWIN + + sTimers.clear(); + + sInitialised = false; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: static void Timers::Add(Timer&) +// Purpose: Add a new timer to the set, and reschedule next wakeup +// Created: 5/11/2006 +// +// -------------------------------------------------------------------------- +void Timers::Add(Timer& rTimer) +{ + ASSERT(sInitialised); + sTimers.push_back(&rTimer); + Reschedule(); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: static void Timers::Remove(Timer&) +// Purpose: Removes the timer from the set (preventing it from +// being called) and reschedule next wakeup +// Created: 5/11/2006 +// +// -------------------------------------------------------------------------- +void Timers::Remove(Timer& rTimer) +{ + ASSERT(sInitialised); + + bool restart = true; + while (restart) + { + restart = false; + for (std::vector<Timer*>::iterator i = sTimers.begin(); + i != sTimers.end(); i++) + { + if (&rTimer == *i) + { + sTimers.erase(i); + restart = true; + break; + } + } + } + + Reschedule(); +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: static void Timers::Reschedule() +// Purpose: Recalculate when the next wakeup is due +// Created: 5/11/2006 +// +// -------------------------------------------------------------------------- +void Timers::Reschedule() +{ + ASSERT(sInitialised); + + box_time_t timeNow = GetCurrentBoxTime(); + box_time_t timeToNextEvent = 0; + + for (std::vector<Timer*>::iterator i = sTimers.begin(); + i != sTimers.end(); i++) + { + Timer& rTimer = **i; + ASSERT(!rTimer.HasExpired()); + + box_time_t timeToExpiry = rTimer.GetExpiryTime() - timeNow; + + if (timeToNextEvent == 0 || timeToNextEvent > timeToExpiry) + { + timeToNextEvent = timeToExpiry; + } + } + + ASSERT(timeToNextEvent >= 0); + + struct itimerval timeout; + memset(&timeout, 0, sizeof(timeout)); + + timeout.it_value.tv_sec = BoxTimeToSeconds(timeToNextEvent); + timeout.it_value.tv_usec = (int) + (BoxTimeToMicroSeconds(timeToNextEvent) % MICRO_SEC_IN_SEC); + +#ifdef PLATFORM_CYGWIN + if(::setitimer(ITIMER_REAL, &timeout, NULL) != 0) +#else + if(::setitimer(ITIMER_REAL, &timeout, NULL) != 0) +#endif // PLATFORM_CYGWIN + { + TRACE0("WARNING: couldn't initialise timer\n"); + THROW_EXCEPTION(CommonException, Internal) + } +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: static void Timers::Signal() +// Purpose: Called by signal handler. Signals any timers which +// are due or overdue, removes them from the set, +// and reschedules next wakeup. +// Created: 5/11/2006 +// +// -------------------------------------------------------------------------- +void Timers::Signal() +{ + ASSERT(sInitialised); + + box_time_t timeNow = GetCurrentBoxTime(); + + std::vector<Timer*> timersCopy = sTimers; + + for (std::vector<Timer*>::iterator i = timersCopy.begin(); + i != timersCopy.end(); i++) + { + Timer& rTimer = **i; + ASSERT(!rTimer.HasExpired()); + + box_time_t timeToExpiry = rTimer.GetExpiryTime() - timeNow; + + if (timeToExpiry <= 0) + { + rTimer.OnExpire(); + } + } + + Reschedule(); +} + +Timer::Timer(size_t timeoutSecs) +: mExpires(GetCurrentBoxTime() + SecondsToBoxTime(timeoutSecs)), + mExpired(false) +{ + Timers::Add(*this); +} + +Timer::~Timer() +{ + Timers::Remove(*this); +} + +Timer::Timer(const Timer& rToCopy) +: mExpires(rToCopy.mExpires), + mExpired(rToCopy.mExpired) +{ + Timers::Add(*this); +} + +Timer& Timer::operator=(const Timer& rToCopy) +{ + Timers::Remove(*this); + mExpires = rToCopy.mExpires; + mExpired = rToCopy.mExpired; + if (!mExpired) + { + Timers::Add(*this); + } +} + +void Timer::OnExpire() +{ + mExpired = true; + Timers::Remove(*this); +} diff --git a/lib/common/Timer.h b/lib/common/Timer.h new file mode 100644 index 00000000..6e4a5952 --- /dev/null +++ b/lib/common/Timer.h @@ -0,0 +1,65 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: Timer.h +// Purpose: Generic timers which execute arbitrary code when +// they expire. +// Created: 5/11/2006 +// +// -------------------------------------------------------------------------- + +#ifndef TIMER__H +#define TIMER__H + +#include <sys/time.h> + +#include <vector> + +#include "MemLeakFindOn.h" +#include "BoxTime.h" + +class Timer +{ +public: + Timer(size_t timeoutSecs); + virtual ~Timer(); + Timer(const Timer &); + Timer &operator=(const Timer &); + +public: + box_time_t GetExpiryTime() { return mExpires; } + bool HasExpired () { return mExpired; } + virtual void OnExpire (); + +private: + box_time_t mExpires; + bool mExpired; +}; + +// -------------------------------------------------------------------------- +// +// Class +// Name: Timers +// Purpose: Static class to manage all timers and arrange +// efficient delivery of wakeup signals +// Created: 19/3/04 +// +// -------------------------------------------------------------------------- +class Timers +{ + private: + static std::vector<Timer*> sTimers; + static bool sInitialised; + static void Reschedule(); + + public: + static void Init(); + static void Cleanup(); + static void Add (Timer& rTimer); + static void Remove(Timer& rTimer); + static void Signal(); +}; + +#include "MemLeakFindOff.h" + +#endif // TIMER__H |