summaryrefslogtreecommitdiff
path: root/lib/common/Timer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common/Timer.cpp')
-rw-r--r--lib/common/Timer.cpp227
1 files changed, 227 insertions, 0 deletions
diff --git a/lib/common/Timer.cpp b/lib/common/Timer.cpp
index 137ad45f..390ddf8e 100644
--- a/lib/common/Timer.cpp
+++ b/lib/common/Timer.cpp
@@ -8,12 +8,25 @@
//
// --------------------------------------------------------------------------
+<<<<<<< HEAD
#ifdef WIN32
#define _WIN32_WINNT 0x0500
#endif
#include "Box.h"
+=======
+#include "Box.h"
+
+#ifdef WIN32
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0500
+# elif _WIN32_WINNT < 0x0500
+# error Timers require at least Windows 2000 headers
+# endif
+#endif
+
+>>>>>>> 0.12
#include <signal.h>
#include <cstring>
@@ -26,7 +39,11 @@ std::vector<Timer*>* Timers::spTimers = NULL;
bool Timers::sRescheduleNeeded = false;
#define TIMER_ID "timer " << mName << " (" << this << ") "
+<<<<<<< HEAD
#define TIMER_ID_OF(t) "timer " << (t).GetName() << " (" << &(t) << ") "
+=======
+#define TIMER_ID_OF(t) "timer " << (t).GetName() << " (" << &(t) << ")"
+>>>>>>> 0.12
typedef void (*sighandler_t)(int);
@@ -115,6 +132,10 @@ void Timers::Add(Timer& rTimer)
{
ASSERT(spTimers);
ASSERT(&rTimer);
+<<<<<<< HEAD
+=======
+ BOX_TRACE(TIMER_ID_OF(rTimer) " added to global queue, rescheduling");
+>>>>>>> 0.12
spTimers->push_back(&rTimer);
Reschedule();
}
@@ -132,6 +153,10 @@ void Timers::Remove(Timer& rTimer)
{
ASSERT(spTimers);
ASSERT(&rTimer);
+<<<<<<< HEAD
+=======
+ BOX_TRACE(TIMER_ID_OF(rTimer) " removed from global queue, rescheduling");
+>>>>>>> 0.12
bool restart = true;
while (restart)
@@ -166,10 +191,13 @@ void Timers::RescheduleIfNeeded()
}
}
+<<<<<<< HEAD
#define FORMAT_MICROSECONDS(t) \
(int)(t / 1000000) << "." << \
(int)(t % 1000000) << " seconds"
+=======
+>>>>>>> 0.12
// --------------------------------------------------------------------------
//
// Function
@@ -232,6 +260,7 @@ void Timers::Reschedule()
if (timeToExpiry <= 0)
{
+<<<<<<< HEAD
/*
BOX_TRACE("timer " << *i << " has expired, "
"triggering it");
@@ -239,6 +268,11 @@ void Timers::Reschedule()
BOX_TRACE(TIMER_ID_OF(**i) "has expired, "
"triggering " <<
FORMAT_MICROSECONDS(-timeToExpiry) <<
+=======
+ BOX_TRACE(TIMER_ID_OF(**i) " has expired, "
+ "triggering " <<
+ BOX_FORMAT_MICROSECONDS(-timeToExpiry) <<
+>>>>>>> 0.12
" late");
rTimer.OnExpire();
spTimers->erase(i);
@@ -248,8 +282,13 @@ void Timers::Reschedule()
else
{
/*
+<<<<<<< HEAD
BOX_TRACE("timer " << *i << " has not "
"expired, triggering in " <<
+=======
+ BOX_TRACE(TIMER_ID_OF(**i) " has not expired, "
+ "triggering in " <<
+>>>>>>> 0.12
FORMAT_MICROSECONDS(timeToExpiry) <<
" seconds");
*/
@@ -290,8 +329,13 @@ void Timers::Reschedule()
}
else
{
+<<<<<<< HEAD
BOX_TRACE("timer: next event: " << nameOfNextEvent <<
" expires in " << FORMAT_MICROSECONDS(timeToNextEvent));
+=======
+ BOX_TRACE("timer: next event: " << nameOfNextEvent << " at " <<
+ FormatTime(timeNow + timeToNextEvent, false, true));
+>>>>>>> 0.12
}
struct itimerval timeout;
@@ -331,7 +375,11 @@ void Timers::SignalHandler(int unused)
// --------------------------------------------------------------------------
//
// Function
+<<<<<<< HEAD
// Name: Timer::Timer(size_t timeoutSecs,
+=======
+// Name: Timer::Timer(size_t timeoutMillis,
+>>>>>>> 0.12
// const std::string& rName)
// Purpose: Standard timer constructor, takes a timeout in
// seconds from now, and an optional name for
@@ -340,14 +388,20 @@ void Timers::SignalHandler(int unused)
//
// --------------------------------------------------------------------------
+<<<<<<< HEAD
Timer::Timer(size_t timeoutSecs, const std::string& rName)
: mExpires(GetCurrentBoxTime() + SecondsToBoxTime(timeoutSecs)),
+=======
+Timer::Timer(size_t timeoutMillis, const std::string& rName)
+: mExpires(0),
+>>>>>>> 0.12
mExpired(false),
mName(rName)
#ifdef WIN32
, mTimerHandle(INVALID_HANDLE_VALUE)
#endif
{
+<<<<<<< HEAD
#ifndef BOX_RELEASE_BUILD
if (timeoutSecs == 0)
{
@@ -370,72 +424,125 @@ Timer::Timer(size_t timeoutSecs, const std::string& rName)
Timers::Add(*this);
Start(timeoutSecs * MICRO_SEC_IN_SEC_LL);
}
+=======
+ Set(timeoutMillis, true /* isInit */);
+>>>>>>> 0.12
}
// --------------------------------------------------------------------------
//
// Function
// Name: Timer::Start()
+<<<<<<< HEAD
// Purpose: This internal function initialises an OS TimerQueue
// timer on Windows, while on Unixes there is only a
// single global timer, managed by the Timers class,
// so this method does nothing.
+=======
+// Purpose: This internal function recalculates the remaining
+// time (timeout) from the expiry time, and then calls
+// Start(timeoutMillis).
+>>>>>>> 0.12
// Created: 27/07/2008
//
// --------------------------------------------------------------------------
void Timer::Start()
{
+<<<<<<< HEAD
#ifdef WIN32
+=======
+>>>>>>> 0.12
box_time_t timeNow = GetCurrentBoxTime();
int64_t timeToExpiry = mExpires - timeNow;
if (timeToExpiry <= 0)
{
BOX_WARNING(TIMER_ID << "fudging expiry from -" <<
+<<<<<<< HEAD
FORMAT_MICROSECONDS(-timeToExpiry))
timeToExpiry = 1;
}
Start(timeToExpiry);
#endif
+=======
+ BOX_FORMAT_MICROSECONDS(-timeToExpiry))
+ timeToExpiry = 1;
+ }
+
+ Start(timeToExpiry / MICRO_SEC_IN_MILLI_SEC);
+>>>>>>> 0.12
}
// --------------------------------------------------------------------------
//
// Function
+<<<<<<< HEAD
// Name: Timer::Start(int64_t delayInMicros)
// Purpose: This internal function initialises an OS TimerQueue
// timer on Windows, with a specified delay already
// calculated to save us doing it again. Like
// Timer::Start(), on Unixes it does nothing.
+=======
+// Name: Timer::Start(int64_t timeoutMillis)
+// Purpose: This internal function adds this timer to the global
+// timer list, and on Windows it initialises an OS
+// TimerQueue timer for it.
+>>>>>>> 0.12
// Created: 27/07/2008
//
// --------------------------------------------------------------------------
+<<<<<<< HEAD
void Timer::Start(int64_t delayInMicros)
{
+=======
+void Timer::Start(int64_t timeoutMillis)
+{
+ ASSERT(mExpires != 0);
+ Timers::Add(*this);
+
+>>>>>>> 0.12
#ifdef WIN32
// only call me once!
ASSERT(mTimerHandle == INVALID_HANDLE_VALUE);
+<<<<<<< HEAD
int64_t delayInMillis = delayInMicros / 1000;
+=======
+>>>>>>> 0.12
// Windows XP always seems to fire timers up to 20 ms late,
// at least on my test laptop. Not critical in practice, but our
// tests are precise enough that they will fail if we don't
// correct for it.
+<<<<<<< HEAD
delayInMillis -= 20;
// Set a system timer to call our timer routine
if (CreateTimerQueueTimer(&mTimerHandle, NULL, TimerRoutine,
(PVOID)this, delayInMillis, 0, WT_EXECUTEINTIMERTHREAD)
+=======
+ timeoutMillis -= 20;
+
+ // Set a system timer to call our timer routine
+ if (CreateTimerQueueTimer(&mTimerHandle, NULL, TimerRoutine,
+ (PVOID)this, timeoutMillis, 0, WT_EXECUTEINTIMERTHREAD)
+>>>>>>> 0.12
== FALSE)
{
BOX_ERROR(TIMER_ID "failed to create timer: " <<
GetErrorMessage(GetLastError()));
mTimerHandle = INVALID_HANDLE_VALUE;
}
+<<<<<<< HEAD
+=======
+ else
+ {
+ BOX_INFO(TIMER_ID << "set for " << timeoutMillis << " ms");
+ }
+>>>>>>> 0.12
#endif
}
@@ -443,15 +550,29 @@ void Timer::Start(int64_t delayInMicros)
//
// Function
// Name: Timer::Stop()
+<<<<<<< HEAD
// Purpose: This internal function deletes the associated OS
// TimerQueue timer on Windows, and on Unixes does
// nothing.
+=======
+// Purpose: This internal function removes us from the global
+// list of timers, resets our expiry time, and on
+// Windows it deletes the associated OS TimerQueue timer.
+>>>>>>> 0.12
// Created: 27/07/2008
//
// --------------------------------------------------------------------------
void Timer::Stop()
{
+<<<<<<< HEAD
+=======
+ if (mExpires != 0)
+ {
+ Timers::Remove(*this);
+ }
+
+>>>>>>> 0.12
#ifdef WIN32
if (mTimerHandle != INVALID_HANDLE_VALUE)
{
@@ -481,10 +602,37 @@ Timer::~Timer()
BOX_TRACE(TIMER_ID "destroyed");
#endif
+<<<<<<< HEAD
Timers::Remove(*this);
Stop();
}
+=======
+ Stop();
+}
+
+void Timer::LogAssignment(const Timer &From)
+{
+ #ifndef BOX_RELEASE_BUILD
+ BOX_TRACE(TIMER_ID "initialised from " << TIMER_ID_OF(From));
+
+ if (From.mExpired)
+ {
+ BOX_TRACE(TIMER_ID "already expired, will not fire");
+ }
+ else if (From.mExpires == 0)
+ {
+ BOX_TRACE(TIMER_ID "has no expiry time, will not fire");
+ }
+ else
+ {
+ BOX_TRACE(TIMER_ID "will fire at " <<
+ FormatTime(From.mExpires, false, true));
+ }
+ #endif
+}
+
+>>>>>>> 0.12
// --------------------------------------------------------------------------
//
// Function
@@ -504,6 +652,7 @@ Timer::Timer(const Timer& rToCopy)
, mTimerHandle(INVALID_HANDLE_VALUE)
#endif
{
+<<<<<<< HEAD
#ifndef BOX_RELEASE_BUILD
if (mExpired)
{
@@ -527,6 +676,12 @@ Timer::Timer(const Timer& rToCopy)
if (!mExpired && mExpires != 0)
{
Timers::Add(*this);
+=======
+ LogAssignment(rToCopy);
+
+ if (!mExpired && mExpires != 0)
+ {
+>>>>>>> 0.12
Start();
}
}
@@ -545,6 +700,7 @@ Timer::Timer(const Timer& rToCopy)
Timer& Timer::operator=(const Timer& rToCopy)
{
+<<<<<<< HEAD
#ifndef BOX_RELEASE_BUILD
if (rToCopy.mExpired)
{
@@ -566,6 +722,10 @@ Timer& Timer::operator=(const Timer& rToCopy)
#endif
Timers::Remove(*this);
+=======
+ LogAssignment(rToCopy);
+
+>>>>>>> 0.12
Stop();
mExpires = rToCopy.mExpires;
@@ -574,7 +734,10 @@ Timer& Timer::operator=(const Timer& rToCopy)
if (!mExpired && mExpires != 0)
{
+<<<<<<< HEAD
Timers::Add(*this);
+=======
+>>>>>>> 0.12
Start();
}
@@ -584,6 +747,70 @@ Timer& Timer::operator=(const Timer& rToCopy)
// --------------------------------------------------------------------------
//
// Function
+<<<<<<< HEAD
+=======
+// Name: Timer::Reset(size_t timeoutMillis)
+// Purpose: Simple reset operation for an existing Timer. Avoids
+// the need to create a temporary timer just to modify
+// an existing one.
+// Created: 17/11/2012
+//
+// --------------------------------------------------------------------------
+
+void Timer::Reset(size_t timeoutMillis)
+{
+ Set(timeoutMillis, false /* isInit */);
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: Timer::Reset(size_t timeoutMillis)
+// Purpose: Internal set/reset operation for an existing Timer.
+// Shared by constructor and Reset().
+// Created: 17/11/2012
+//
+// --------------------------------------------------------------------------
+
+void Timer::Set(size_t timeoutMillis, bool isInit)
+{
+ Stop();
+ mExpired = false;
+
+ if (timeoutMillis == 0)
+ {
+ mExpires = 0;
+ }
+ else
+ {
+ mExpires = GetCurrentBoxTime() +
+ MilliSecondsToBoxTime(timeoutMillis);
+ }
+
+ #ifndef BOX_RELEASE_BUILD
+ if (timeoutMillis == 0)
+ {
+ BOX_TRACE(TIMER_ID << (isInit ? "initialised" : "reset") <<
+ " for " << timeoutMillis << " ms, will not fire");
+ }
+ else
+ {
+ BOX_TRACE(TIMER_ID << (isInit ? "initialised" : "reset") <<
+ " for " << timeoutMillis << " ms, to fire at " <<
+ FormatTime(mExpires, false, true));
+ }
+ #endif
+
+ if (mExpires != 0)
+ {
+ Start(timeoutMillis);
+ }
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+>>>>>>> 0.12
// Name: Timer::OnExpire()
// Purpose: Method called by Timers::Reschedule (on Unixes)
// on next poll after timer expires, or from