From 796085fc537e6bac7999e4b6624f02196eeaf4ad Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 12 Sep 2023 09:32:32 -0400 Subject: DRTVWR-588: Reimplement LLMainThreadTask based on WorkQueue instead of on LLEventTimer. LLEventTimer takes cycles from the main loop to run through the collection of pending LLEventTimers, checking each to see if we've reached its timestamp. But LLMainThreadTask does not require delay timing; it wants the main loop to service it ASAP. That's what the "mainloop" WorkQueue is for. But WorkQueue::waitForResult() forbids calls from a thread's default coroutine. While that restriction may still make sense in general, we specifically want to be able to pause LLMainThreadTask's caller, no matter what coroutine it's running on. Introduce WorkQueue::waitForResult_() that bypasses the check. --- indra/llcommon/workqueue.h | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'indra/llcommon/workqueue.h') diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 70fd65bd0c..20fd15d0d5 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -12,7 +12,6 @@ #if ! defined(LL_WORKQUEUE_H) #define LL_WORKQUEUE_H -#include "llcoros.h" #include "llexception.h" #include "llinstancetracker.h" #include "threadsafeschedule.h" @@ -200,31 +199,51 @@ namespace LL } /** - * Post work to another WorkQueue to be run at a specified time, - * blocking the calling coroutine until then, returning the result to - * caller on completion. + * Post work, blocking the calling coroutine until then, returning the + * result to caller on completion. * * In general, we assume that each thread's default coroutine is busy * servicing its WorkQueue or whatever. To try to prevent mistakes, we * forbid calling waitForResult() from a thread's default coroutine. */ template - auto waitForResult(const TimePoint& time, CALLABLE&& callable); + auto waitForResult(CALLABLE&& callable) + { + return waitForResult(TimePoint::clock::now(), std::forward(callable)); + } /** - * Post work to another WorkQueue, blocking the calling coroutine - * until then, returning the result to caller on completion. + * Post work to be run at a specified time, blocking the calling + * coroutine until then, returning the result to caller on completion. * * In general, we assume that each thread's default coroutine is busy * servicing its WorkQueue or whatever. To try to prevent mistakes, we * forbid calling waitForResult() from a thread's default coroutine. */ template - auto waitForResult(CALLABLE&& callable) + auto waitForResult(const TimePoint& time, CALLABLE&& callable) { - return waitForResult(TimePoint::clock::now(), std::move(callable)); + checkCoroutine("waitForResult()"); + return waitForResult_(time, std::forward(callable)); } + /** + * Post work, blocking the calling coroutine until then, returning the + * result to caller on completion. + */ + template + auto waitForResult_(CALLABLE&& callable) + { + return waitForResult_(TimePoint::clock::now(), std::forward(callable)); + } + + /** + * Post work to be run at a specified time, blocking the calling + * coroutine until then, returning the result to caller on completion. + */ + template + auto waitForResult_(const TimePoint& time, CALLABLE&& callable); + /*--------------------------- worker API ---------------------------*/ /** @@ -561,9 +580,8 @@ namespace LL }; template - auto WorkQueue::waitForResult(const TimePoint& time, CALLABLE&& callable) + auto WorkQueue::waitForResult_(const TimePoint& time, CALLABLE&& callable) { - checkCoroutine("waitForResult()"); // derive callable's return type so we can specialize for void return WaitForResult(callable)())>() (this, time, std::forward(callable)); -- cgit v1.2.3 From c78be38a6a4211f06876bc80b3f19f89a5f936e0 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Apr 2024 16:39:37 -0400 Subject: Reintroduce LLCoros::killreq() to request killing a named coroutine. Make LLCoros constructor echo "LLApp" status-change events on new "LLCoros" event pump. Rename LLCoros::kill() to killreq() because this operation only registers a request for the named coroutine to terminate next time it calls checkStop(). Add a new CoroData member to record the name of the coroutine requesting termination. killreq() sets that and also posts "killreq" to "LLCoros". Add an optional final-cleanup callback to LLCoros::checkStop(). Make checkStop() check for a pending killreq() request as well as viewer termination. Introduce new LLCoros::Killed exception for that case. Introduce LLCoros::getStopListener(), with two overloads, to encapsulate some of the messy logic to listen (perhaps temporarily) for viewer shutdown. Both overloads are for use by code at the source end of a queue or promise or other resource for which coroutines might still be waiting at viewer shutdown time. One overload is specifically for when the caller knows the name of the one and only coroutine that will wait on the resource (e.g. because the caller IS that coroutine). That overload honors killreq(). Use getStopListener() to simplify the four existing places where we set up such a listener. Add a fifth: also make WorkQueue listen for viewer shutdown (resolving a TODO comment). Remove LLLUAmanager::terminateScript(), getTerminationList() and the static sTerminationList. In the Lua interrupt callback, instead of checking sTerminationList, call LLCoros::checkStop(). Change LLFloaterLUAScripts terminate-script logic to call LLCoros::killreq() instead of posting on "LLLua" and calling LLLUAmanager::terminateScript(). Drop LLApp::setStatus() posting to "LLLua" LLEventPump: the above makes that moot. --- indra/llcommon/workqueue.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/llcommon/workqueue.h') diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index ec0700a718..4c46290f2a 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -13,6 +13,7 @@ #define LL_WORKQUEUE_H #include "llcoros.h" +#include "llevents.h" #include "llexception.h" #include "llinstancetracker.h" #include "llinstancetrackersubclass.h" @@ -194,6 +195,8 @@ namespace LL static std::string makeName(const std::string& name); void callWork(const Work& work); + LLTempBoundListener mStopListener; + private: virtual Work pop_() = 0; virtual bool tryPop_(Work&) = 0; -- cgit v1.2.3 From 0bcbe6f850580306d3f665e459873adf736c37a2 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 25 Apr 2024 14:01:50 -0400 Subject: Resolve WorkQueue::waitForResult() merge glitch. --- indra/llcommon/workqueue.h | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'indra/llcommon/workqueue.h') diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 03c0494c1f..c4435cec40 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -115,33 +115,29 @@ namespace LL ARGS&&... args); /** - * Post work to be run at a specified time, blocking the calling - * coroutine until then, returning the result to caller on completion. - * Optional final argument is TimePoint for WorkSchedule. + * Post work, blocking the calling coroutine, returning the result to + * caller on completion. Optional final argument is TimePoint for + * WorkSchedule. * * In general, we assume that each thread's default coroutine is busy * servicing its WorkQueue or whatever. To try to prevent mistakes, we * forbid calling waitForResult() from a thread's default coroutine. */ template - auto waitForResult(CALLABLE&& callable, ARGS&&... args); - - /** - * Post work, blocking the calling coroutine until then, returning the - * result to caller on completion. - */ - template - auto waitForResult_(CALLABLE&& callable) + auto waitForResult(CALLABLE&& callable, ARGS&&... args) { - return waitForResult_(TimePoint::clock::now(), std::forward(callable)); + checkCoroutine("waitForResult()"); + return waitForResult_(std::forward(callable), + std::forward(args)...); } /** - * Post work to be run at a specified time, blocking the calling - * coroutine until then, returning the result to caller on completion. + * Post work, blocking the calling coroutine, returning the result to + * caller on completion. Optional final argument is TimePoint for + * WorkSchedule. */ - template - auto waitForResult_(const TimePoint& time, CALLABLE&& callable); + template + auto waitForResult_(CALLABLE&& callable, ARGS&&... args); /*--------------------------- worker API ---------------------------*/ @@ -634,7 +630,7 @@ namespace LL }; template - auto WorkQueueBase::waitForResult(CALLABLE&& callable, ARGS&&... args) + auto WorkQueueBase::waitForResult_(CALLABLE&& callable, ARGS&&... args) { // derive callable's return type so we can specialize for void return WaitForResult(callable)())>() -- cgit v1.2.3 From bd8e1dd8d2340636521200d15a045321ea07b986 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 8 May 2024 16:58:34 -0400 Subject: Tweak a couple things --- indra/llcommon/workqueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/workqueue.h') diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index b658966f63..ecc6f27223 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -541,7 +541,7 @@ namespace LL reply, // Bind the current exception to transport back to the // originating WorkQueue. Once there, rethrow it. - [exc = std::current_exception()](){ std::rethrow_exception(exc); }); + [exc = std::current_exception()]{ std::rethrow_exception(exc); }); } }, // if caller passed a TimePoint, pass it along to post() -- cgit v1.2.3 From 86110fd186be29f313d781945ba6cdc500f25b32 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 31 May 2024 11:14:41 -0400 Subject: Explain the name of the LL::WorkQueue::BackJack class. --- indra/llcommon/workqueue.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llcommon/workqueue.h') diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index ecc6f27223..1f8cebd336 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -375,6 +375,10 @@ namespace LL * CALLABLE that returns bool, a TimePoint and an interval at which to * relaunch it. As long as the callable continues returning true, BackJack * keeps resubmitting it to the target WorkQueue. + * + * "You go back, Jack, and do it again -- wheel turning' round and round..." + * --Steely Dan, from "Can't Buy a Thrill" (1972) + * https://www.youtube.com/watch?v=yCgHTmv4YU8 */ // Why is BackJack a class and not a lambda? Because, unlike a lambda, a // class method gets its own 'this' pointer -- which we need to resubmit -- cgit v1.2.3 From c3ccf00e91ff61bd3ea6c6f7ffb3709442e2270a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 3 Jun 2024 17:02:19 -0400 Subject: Fix a small typo --- indra/llcommon/workqueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/workqueue.h') diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 1f8cebd336..0581f85bfa 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -376,7 +376,7 @@ namespace LL * relaunch it. As long as the callable continues returning true, BackJack * keeps resubmitting it to the target WorkQueue. * - * "You go back, Jack, and do it again -- wheel turning' round and round..." + * "You go back, Jack, and do it again -- wheel turnin' round and round..." * --Steely Dan, from "Can't Buy a Thrill" (1972) * https://www.youtube.com/watch?v=yCgHTmv4YU8 */ -- cgit v1.2.3 From 03d7f2b84daf9ab991de6cad7d6149abda1ef716 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 28 Aug 2024 21:16:56 -0400 Subject: Ditch trailing spaces. --- indra/llcommon/workqueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/workqueue.h') diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 0581f85bfa..eb6923df0b 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -3,7 +3,7 @@ * @author Nat Goodspeed * @date 2021-09-30 * @brief Queue used for inter-thread work passing. - * + * * $LicenseInfo:firstyear=2021&license=viewerlgpl$ * Copyright (c) 2021, Linden Research, Inc. * $/LicenseInfo$ -- cgit v1.2.3