3.3 KiB
Post-to and post-back in posting invokers
Two targets
Posting coroutines (TaggedPostingPromise / *ViralPostingInvoker / *NonViralPostingInvoker) use two different io_context targets:
| Direction | When | Target |
|---|---|---|
| Post-TO | initial_suspend |
Where the callee coroutine starts running |
| Post-BACK | final_suspend |
Where the caller resumes after co_await |
Post-back always uses callerIoContext, initialized from ComponentThread::getSelf()->getIoContext() at the co_await site. That behavior is unchanged.
Post-to defaults to the static ThreadTag::io_context() for the invoker alias (e.g. MrnttThreadTag, BodyThreadTag).
Static post-TO (default)
Existing coroutines need no signature change. TaggedPostingPromise::initial_suspend() posts the callee handle to ThreadTag::io_context().
Dynamic post-TO (ExplicitPostTarget)
Opt in by adding sscl::co::ExplicitPostTarget to the coroutine parameter list. The promise constructor extracts it into std::optional<ExplicitPostTarget> calleePostTarget; initial_suspend() posts to calleePostTarget->ioContext instead of ThreadTag::io_context().
// Viral member example: run on body thread, post back to mrntt caller
BodyViralPostingInvoker<bool> Body::initializeCReq(
sscl::co::ExplicitPostTarget postTarget)
{
co_await ...;
}
// Non-viral example
reattachKnownListCReq(
sscl::co::ExplicitPostTarget{someIoContext},
exceptionPtr,
callback);
The caller must ensure the referenced io_context outlives the callee frame.
DeviceManager attach/detach (mrntt orchestrator, library on body/world)
DeviceManager::attachStimBuffDeviceCReq and detachStimBuffDeviceCReq stay
MrnttViralPostingInvoker on the marionette thread. They co_await library
attachDeviceCReq / detachDeviceCReq (DynamicViralPostingInvoker) with
ExplicitPostTarget first:
- edev (
sensorType == 'e') → world thread - otherwise → body thread
Post-TO runs the library coroutine on that target; post-back resumes the
DeviceManager coroutine on mrntt. Attach also passes componentThread for
device/producer binding inside the library.
auto targetThread = threadForDeviceOp(*spec);
co_return co_await lib.stimBuffApiDesc.sal_mgmt_libOps.attachDeviceCReq(
sscl::co::ExplicitPostTarget{targetThread->getIoContext()},
spec,
targetThread);
Detach uses the same threadForDeviceOp rule (not producer lookup).
Constructor discrimination
PostingPromise mirrors the existing implicit-this peel:
- Member coroutines pass the object parameter first; it is discarded.
- When present,
ExplicitPostTargetis the next parameter (before non-viralexception_ptr&and completion callback). - Free non-viral dynamic:
ExplicitPostTarget, thenexception_ptr&, then callback. ExplicitPostTargetis recognized by type (is_explicit_post_target_v) and stored incalleePostTarget.ObjectArgrequires!is_explicit_post_target_vso the wrapper is never mistaken forthisptr.
Timing invariant
Post-TO and post-BACK work must run from InitialSuspendPostingInvoker::await_suspend and FinalSuspendPostingInvoker::await_suspend, not synchronously inside initial_suspend() / final_suspend() bodies. See comments in postingPromise.h.