mirror of
https://github.com/latentPrion/libspinscale.git
synced 2026-06-23 11:38:33 +00:00
Nursery: document syncAwaitAll's caller io_context requirement for LLMs
This commit is contained in:
@@ -204,7 +204,8 @@ nursery.launch(
|
||||
|
||||
nursery.requestCancelOnAll();
|
||||
nursery.closeAdmission();
|
||||
nursery.syncAwaitAllSettlements(ioContext);
|
||||
nursery.syncAwaitAllSettlements(
|
||||
sscl::ComponentThread::getSelf()->getIoContext());
|
||||
```
|
||||
|
||||
Each slot owns a `SyncCancelerForAsyncWork`. `requestCancelOnAll()` only signals
|
||||
@@ -213,6 +214,14 @@ completion callbacks run. Call `closeAdmission()` explicitly before
|
||||
`asyncAwaitAllSettlements()` or `syncAwaitAllSettlements()`; those APIs wait until
|
||||
all slots have retired naturally and throw if admission is still open.
|
||||
|
||||
`syncAwaitAllSettlements()` runs a nested `io_context` loop on the **calling
|
||||
thread** (it blocks in `run_one()` until every slot has retired). Pass the
|
||||
caller thread's `io_context` — usually `ComponentThread::getSelf()->getIoContext()`
|
||||
— not some other thread's context. While the caller is blocked pumping another
|
||||
thread's queue, handlers posted to the caller's own `io_context` are abandoned
|
||||
and the drain can deadlock even when in-flight work has already completed on a
|
||||
different thread.
|
||||
|
||||
`launch(factory, onSettledHook)` registers a non-null hook before `fillSlot()`.
|
||||
Omit the hook (default `nullptr`) when no settlement callback is needed.
|
||||
`Slot::Lease` is commit-required: an uncommitted lease removes its
|
||||
|
||||
@@ -45,9 +45,15 @@ struct MemberInvoker : MemberInvokerBase
|
||||
* SyncCancelerForAsyncWork, and provides drain APIs.
|
||||
*
|
||||
* Call closeAdmission() explicitly before asyncAwaitAllSettlements() or
|
||||
* syncAwaitAllSettlements(). syncAwaitAllSettlements() caller must pass the
|
||||
* io_context where non-viral posting completions will land, and must ensure
|
||||
* that io_context is prepared to run (e.g. not left stopped without restart).
|
||||
* syncAwaitAllSettlements().
|
||||
*
|
||||
* syncAwaitAllSettlements() runs a nested io_context loop on the calling
|
||||
* thread (AsynchronousBridge). Pass the calling thread's io_context —
|
||||
* typically
|
||||
* ComponentThread::getSelf()->getIoContext() — not another thread's
|
||||
* io_context. If the caller pumps a different thread's queue while blocked,
|
||||
* completions posted back to the caller's own io_context are never executed
|
||||
* and the drain can deadlock even after cooperative cancel.
|
||||
*/
|
||||
class NonViralTaskNursery
|
||||
{
|
||||
@@ -307,6 +313,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/** Nested drain: blocks the calling thread in run_one() on @p ioContext until
|
||||
* all slots retire. @p ioContext must be the caller thread's io_context.
|
||||
*/
|
||||
void syncAwaitAllSettlements(boost::asio::io_context &ioContext)
|
||||
{
|
||||
if (admissionIsOpen())
|
||||
|
||||
@@ -25,6 +25,10 @@ public:
|
||||
boost::asio::post(io_context, []{});
|
||||
}
|
||||
|
||||
/** Blocks the calling thread in run_one() on the bridge's io_context.
|
||||
* Used by syncAwaitAllSettlements(); that io_context must be the caller
|
||||
* thread's own queue so posted completions on the caller are not starved.
|
||||
*/
|
||||
void waitForAsyncOperationCompleteOrIoContextStopped(void)
|
||||
{
|
||||
for (;;)
|
||||
|
||||
Reference in New Issue
Block a user