diff --git a/Subtrees/beast/modules/beast_basics/events/beast_DeadlineTimer.cpp b/Subtrees/beast/modules/beast_basics/events/beast_DeadlineTimer.cpp index 8475610e5e..ca5ab93f60 100644 --- a/Subtrees/beast/modules/beast_basics/events/beast_DeadlineTimer.cpp +++ b/Subtrees/beast/modules/beast_basics/events/beast_DeadlineTimer.cpp @@ -43,11 +43,24 @@ public: bassert (m_items.empty ()); } - void activate (DeadlineTimer* timer) + // Okay to call on an active timer. + // However, an extra notification may still happen due to concurrency. + // + void activate (DeadlineTimer* timer, double secondsRecurring, Time const& when) { + bassert (secondsRecurring >= 0); + LockType::ScopedLockType lock (m_mutex); - bassert (! timer->m_isActive); + if (timer->m_isActive) + { + m_items.erase (m_items.iterator_to (*timer)); + + timer->m_isActive = false; + } + + timer->m_secondsRecurring = secondsRecurring; + timer->m_notificationTime = when; insertSorted (*timer); timer->m_isActive = true; @@ -219,26 +232,25 @@ DeadlineTimer::~DeadlineTimer () void DeadlineTimer::setExpiration (double secondsUntilDeadline) { - m_secondsRecurring = 0; - m_notificationTime = Time::getCurrentTime () + RelativeTime (secondsUntilDeadline); + bassert (secondsUntilDeadline > 0); - m_manager->activate (this); + Time const when = Time::getCurrentTime () + RelativeTime (secondsUntilDeadline); + + m_manager->activate (this, 0, when); } void DeadlineTimer::setRecurringExpiration (double secondsUntilDeadline) { - m_secondsRecurring = secondsUntilDeadline; - m_notificationTime = Time::getCurrentTime () + RelativeTime (secondsUntilDeadline); + bassert (secondsUntilDeadline > 0); - m_manager->activate (this); + Time const when = Time::getCurrentTime () + RelativeTime (secondsUntilDeadline); + + m_manager->activate (this, secondsUntilDeadline, when); } -void DeadlineTimer::setExpirationTime (Time absoluteDeadline) +void DeadlineTimer::setExpirationTime (Time const& when) { - m_secondsRecurring = 0; - m_notificationTime = absoluteDeadline; - - m_manager->activate (this); + m_manager->activate (this, 0, when); } void DeadlineTimer::reset () diff --git a/Subtrees/beast/modules/beast_basics/events/beast_DeadlineTimer.h b/Subtrees/beast/modules/beast_basics/events/beast_DeadlineTimer.h index 5af0a236aa..671ab27d06 100644 --- a/Subtrees/beast/modules/beast_basics/events/beast_DeadlineTimer.h +++ b/Subtrees/beast/modules/beast_basics/events/beast_DeadlineTimer.h @@ -46,21 +46,49 @@ public: ~DeadlineTimer (); /** Set the timer to go off once in the future. + + If the timer is already active, this will reset it. + + @note If the timer is already active, a notification may still + occur due to concurrency. + + @param secondsUntilDeadline The number of seconds until the timer + will send a notification. This must be + greater than zero. */ void setExpiration (double secondsUntilDeadline); /** Set the timer to go off repeatedly with the specified frequency. + + If the timer is already active, this will reset it. + + @note If the timer is already active, a notification may still + occur due to concurrency. + + @param secondsUntilDeadline The number of seconds until the timer + will send a notification. This must be + greater than zero. */ void setRecurringExpiration (double secondsUntilDeadline); /** Set the timer to go off at a specific time. + If the timer is already active, this will reset it. + + @note If the timer is already active, a notification may still + occur due to concurrency. + @note If the time is in the past, the timer will go off immediately. */ - void setExpirationTime (Time absoluteDeadline); + void setExpirationTime (Time const& when); /** Reset the timer so that no more notifications are sent. + + It is okay to call this on an inactive timer. + + @note If the timer is already active, a notification may still + occur due to concurrency. */ void reset ();