Docs: add these prompts, I guess

This commit is contained in:
2026-06-06 19:20:43 -04:00
parent d4905f53df
commit 986e1833d0
2 changed files with 84 additions and 0 deletions
@@ -0,0 +1,7 @@
# Caller post-back uses getSelf io_context
Viral posting invokers resume the caller on the thread that issued `co_await`, using `callerIoContext` captured from `ComponentThread::getSelf()` at promise construction time.
Dynamic `ExplicitPostTarget` only affects post-TO (`initial_suspend`), not post-back.
See [post-to-and-back-in-invokables.md](post-to-and-back-in-invokables.md).
@@ -0,0 +1,77 @@
# 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()`.
```cpp
// 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.
```cpp
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, `ExplicitPostTarget` is the next parameter (before non-viral `exception_ptr&` and completion callback).
- Free non-viral dynamic: `ExplicitPostTarget`, then `exception_ptr&`, then callback.
- `ExplicitPostTarget` is recognized by type (`is_explicit_post_target_v`) and stored in `calleePostTarget`.
- `ObjectArg` requires `!is_explicit_post_target_v` so the wrapper is never mistaken for `thisptr`.
## 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`.