Hack around race condition in timers.

This commit is contained in:
Christian Speckner 2018-12-17 00:30:42 +01:00
parent 9b22c6afa7
commit 8cb235bf19
3 changed files with 14 additions and 5 deletions

View File

@ -67,6 +67,7 @@
"unordered_map": "cpp", "unordered_map": "cpp",
"istream": "cpp", "istream": "cpp",
"thread": "cpp", "thread": "cpp",
"utility": "cpp" "utility": "cpp",
"streambuf": "cpp"
} }
} }

View File

@ -43,7 +43,8 @@ StaggeredLogger::StaggeredLogger(const string& message, Logger logger)
myMaxIntervalFactor(9), myMaxIntervalFactor(9),
myCurrentIntervalFactor(1), myCurrentIntervalFactor(1),
myCooldownTime(1000), myCooldownTime(1000),
myTimer(new TimerManager()) myTimer(new TimerManager()),
myTimerCallbackId(0)
{ {
if (logger) myLogger = logger; if (logger) myLogger = logger;
} }
@ -148,14 +149,16 @@ void StaggeredLogger::startInterval()
myLastIntervalStartTimestamp = now; myLastIntervalStartTimestamp = now;
myTimer->clear(myTimerId); myTimer->clear(myTimerId);
myTimerId = myTimer->setTimeout(std::bind(&StaggeredLogger::onTimerExpired, this), myCurrentIntervalSize); myTimerId = myTimer->setTimeout(std::bind(&StaggeredLogger::onTimerExpired, this, ++myTimerCallbackId), myCurrentIntervalSize);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StaggeredLogger::onTimerExpired() void StaggeredLogger::onTimerExpired(uInt32 timerCallbackId)
{ {
std::lock_guard<std::mutex> lock(myMutex); std::lock_guard<std::mutex> lock(myMutex);
if (timerCallbackId != myTimerCallbackId) return;
logLine(); logLine();
myIsCurrentlyCollecting = false; myIsCurrentlyCollecting = false;

View File

@ -52,7 +52,7 @@ class StaggeredLogger {
void _setLogger(Logger logger); void _setLogger(Logger logger);
void onTimerExpired(); void onTimerExpired(uInt32 timerId);
void startInterval(); void startInterval();
@ -83,6 +83,11 @@ class StaggeredLogger {
// our destructor. // our destructor.
TimerManager *myTimer; TimerManager *myTimer;
TimerManager::TimerId myTimerId; TimerManager::TimerId myTimerId;
// It is possible that the timer callback is running even after TimerManager::clear
// returns. This id is unique per timer and is used to return from the callback
// early in case the time is stale.
uInt32 myTimerCallbackId;
}; };
#endif // STAGGERED_LOGGER #endif // STAGGERED_LOGGER