Age | Commit message (Collapse) | Author |
|
The reqid is only distinct within a particular calling script.
|
|
|
|
Since timers presents a timers.Timer Lua class supporting queries and
cancellation, make TimersListener::scheduleAfter() and scheduleEvery() respond
immediately so the newly constructed Timer object has the reqid necessary to
perform those subsequent operations.
This requires that Lua invocations of these operations avoid calling the
caller's callback with that initial response.
Reinvent leap.generate() to return a Lua object supporting next() and done()
methods. A plain Lua coroutine that (indirectly) calls fiber.wait() confuses
the fiber scheduler, so avoid implementing generate() as a Lua coroutine.
Add a bit more leap.lua diagnostic output.
|
|
|
|
leap.eventstream() is used when we expect the viewer's LLEventAPI to send an
immediate first response with the reqid from the request, followed by some
number of subsequent responses bearing the same reqid. The difference between
eventstream() and generate() is that generate() expects the caller to request
each such response, whereas eventstream calls the caller's callback with each
response.
cancelreq() is for canceling the background fiber launched by eventstream()
before the callback tells it to quit.
Make WaitFor:close() remove the object from the waitfors list; similarly, make
WaitForReqid:close() remove the object from the pending list. For this reason,
cleanup() must iterate over a copy of each of the pending and waitfors lists.
Instead of unregisterWaitFor() manually searching the waitfors list, use
table.find().
|
|
|
|
|
|
|
|
|
|
Otherwise we fall into the trap of destroying a joinable std::thread, which
calls std::terminate() and hence our crash-on-terminate() handler.
The previous ~ThreadPool() logic only joined threads if the queue wasn't
already closed, but evidently we can reach the destructor with the queue
closed but the threads not yet joined.
Fixes #1534.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(cherry picked from commit 82d713782529074b03720833038cb0df2b8bcffd)
|
|
|
|
|
|
|
|
|
|
following promotion of secondlife/viewer #705: Maintenance X
|
|
Maintenance X
|
|
|
|
Instead of making LLEventPumps an LLHandleProvider, and storing an
LLHandle<LLEventPumps> in each LLEventPump instance, just make ~LLEventPump()
query LLEventPumps::instanceExists() before calling instance().
|
|
Rename LL::Timers::scheduleRepeating() to scheduleEvery().
|
|
(cherry picked from commit dc0b3aed4782e4e4835fd6b9d59d1d70b78be4a7)
|
|
|
|
|
|
In its GitHub PR build, the nat/cleanup-timers branch hit a (rare!)
mathmisc_test failure. But since the test failure didn't report any of the
randomly generated values that led to the failure, all we can do is shrug and
rerun. Pull in the changeset from that branch that adds mathmisc_test
reporting in case of another such failure.
|
|
|
|
|
|
|
|
|
|
|
|
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.
|