diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2024-05-07 16:13:03 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2024-05-07 16:13:03 -0400 |
commit | d4f384b4ec55758a7f2ca4338894ea6cacc98eec (patch) | |
tree | 0d9f42611023e7289af64415f0e1580e76692303 /indra/llcommon/lleventfilter.cpp | |
parent | c89d51c60a6f42a5e279e2c9e06adcf1f13822c0 (diff) |
Refactor LLLater -> LL::Timers to accommodate nonpositive repeats.
In the previous design, the tick() method ran each task exactly once.
doPeriodically() was implemented by posting a functor that would, after
calling the specified callable, repost itself at (timestamp + interval).
The trouble with that design is that it required (interval > 0). A nonpositive
interval would result in looping over any timers with nonpositive repetition
intervals without ever returning from the tick() method.
To avoid that, doPeriodically() contained an llassert(interval > 0).
Unfortunately the viewer failed that constraint immediately at login, leading
to the suspicion that eliminating every such usage might require a protracted
search.
Lifting that restriction required a redesign. Now the priority queue stores a
callable returning bool, and the tick() method itself contains the logic to
repost a recurring task -- but defers doing so until after it stops looping
over ready tasks, ensuring that a task with a nonpositive interval will at
least wait until the following tick() call.
This simplifies not only doPeriodically(), but also doAtTime(). The previous
split of doAtTime() into doAtTime1() and doAtTime2() was only to accommodate
the needs of the Periodic functor class. Ditch Periodic.
Per feedback from NickyD, rename doAtTime() to scheduleAt(), which wraps its
passed nullary callable into a callable that unconditionally returns true (so
tick() will run it only once).
Rename the doAfterInterval() method to scheduleAfter(), which similarly wraps
its nullary callable. However, the legacy doAfterInterval() free function
remains. scheduleAfter() also loses its llassert(seconds > 0).
Rename the doPeriodically() method to scheduleRepeating(). However, the legacy
doPeriodically() free function remains.
Add internal scheduleAtRepeating(), whose role is to accept both a specific
timestamp and a repetition interval (which might be ignored, depending on the
callable). scheduleAtRepeating() now contains the real logic to add a task.
Rename getRemaining() to timeUntilCall(), hopefully resolving the question of
"remaining what?"
Expand the std::pair metadata stored in Timers's auxiliary unordered_map to a
Metadata struct containing the repetition interval plus two bools to mediate
deferred cancel() processing. Rename HandleMap to MetaMap, mHandles to mMeta.
Defend against the case when cancel(handle) is reached during the call to that
handle's callable. Meta::mRunning is set for the duration of that call. When
cancel() sees mRunning, instead of immediately deleting map entries, it sets
mCancel. Upon return from a task's callable, tick() notices mCancel and
behaves as if the callable returned true to stop the series of calls.
To guarantee that mRunning doesn't inadvertently remain set even in the case
of an exception, introduce local RAII class TempSet whose constructor accepts
a non-const variable reference and a desired value. The constructor captures
the current value and sets the desired value; the destructor restores the
previous value.
Defend against exception in a task's callable, and stop calling that task. Use
LOG_UNHANDLED_EXCEPTION() to report it.
Diffstat (limited to 'indra/llcommon/lleventfilter.cpp')
-rw-r--r-- | indra/llcommon/lleventfilter.cpp | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/indra/llcommon/lleventfilter.cpp b/indra/llcommon/lleventfilter.cpp index e72ae7ad33..ad61e9298a 100644 --- a/indra/llcommon/lleventfilter.cpp +++ b/indra/llcommon/lleventfilter.cpp @@ -87,7 +87,7 @@ LLEventTimeout::LLEventTimeout(LLEventPump& source): void LLEventTimeout::actionAfter(F32 seconds, const Action& action) { - mTimer = LLLater::instance().doAfterInterval(action, seconds); + mTimer = LL::Timers::instance().scheduleAfter(action, seconds); } void LLEventTimeout::errorAfter(F32 seconds, const std::string& message) @@ -118,7 +118,7 @@ void LLEventTimeout::cancel() bool LLEventTimeout::running() const { - return LLLater::instance().isRunning(mTimer); + return LL::Timers::instance().isRunning(mTimer); } /***************************************************************************** @@ -277,17 +277,17 @@ F32 LLEventThrottle::getDelay() const void LLEventThrottle::alarmActionAfter(F32 interval, const LLEventTimeout::Action& action) { - mAlarm = LLLater::instance().doAfterInterval(action, interval); + mAlarm = LL::Timers::instance().scheduleAfter(action, interval); } bool LLEventThrottle::alarmRunning() const { - return LLLater::instance().isRunning(mAlarm); + return LL::Timers::instance().isRunning(mAlarm); } void LLEventThrottle::alarmCancel() { - LLLater::instance().cancel(mAlarm); + LL::Timers::instance().cancel(mAlarm); } void LLEventThrottle::timerSet(F32 interval) |