diff options
Diffstat (limited to 'lib/common/Timer.cpp')
-rw-r--r-- | lib/common/Timer.cpp | 227 |
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 |