summaryrefslogtreecommitdiff
path: root/lib/common
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2006-11-06 20:43:12 +0000
committerChris Wilson <chris+github@qwirx.com>2006-11-06 20:43:12 +0000
commit3a590d43ce5e108e42483993b3ce7bfaaa20d74d (patch)
tree56aeb826bce234eb3f2fe5e747fe8194a84d9c42 /lib/common
parentee4dc408e4ce8364322ea19a4fabbb5e8edf4d46 (diff)
Added generic timer support class
Diffstat (limited to 'lib/common')
-rw-r--r--lib/common/BoxTime.h5
-rw-r--r--lib/common/Timer.cpp252
-rw-r--r--lib/common/Timer.h65
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