|
morph 0.1.0
Asynchronous bridge between GUI thread and business models
|
Owned lifetime-and-stop gate for asynchronous callbacks — a data member, not a base class. More...
#include <callback_scope.hpp>
Public Member Functions | |
| CallbackScope () | |
| Constructs a live, un-stopped scope. | |
| ~CallbackScope () | |
| Refuses every outstanding token, then releases the state. | |
| CallbackScope (const CallbackScope &)=delete | |
| CallbackScope & | operator= (const CallbackScope &)=delete |
| CallbackScope (CallbackScope &&)=delete | |
| CallbackScope & | operator= (CallbackScope &&)=delete |
| void | requestStop () const noexcept |
| Marks this generation stopped: gated callbacks stop being delivered, and every call the scope owns is asked to stop. | |
| void | reset () |
| Retires every token issued so far and starts a fresh, live generation. | |
| bool | stopRequested () const noexcept |
| Whether this generation has been stopped. | |
| CallbackToken | token () const noexcept |
| Issues a weak token for the current generation. | |
| template<typename F> | |
| auto | guard (F &&fn) const |
Wraps fn so it runs only while this scope is alive and un-stopped. | |
Owned lifetime-and-stop gate for asynchronous callbacks — a data member, not a base class.
A receiver that attaches callbacks to a Completion<T>, a BridgeHandler subscription, a timer tick or any other posted closure holds one of these as an ordinary member and hands out CallbackTokens. A gated callback runs only while the scope is both alive and not stopped.
Composition is the point. Requiring every consumer to derive from a framework base class constrains hierarchies that are already QObjects, already have a base, or are aggregates — for what is an implementation detail of one screen. A member composes with all of them, and code that never opts in is unaffected.
Destruction and requestStop() are indistinguishable to a callback; they differ only in whether the owner still exists, which CallbackToken::status() reports as Expired versus Stopped.
reset() is the exception and must be externally synchronised against the others — call it from the thread that owns the scope. It replaces the _state handle itself, and reading a shared_ptr while another thread assigns it is a data race on the handle: the control block's refcount is atomic, the pointer object is not. That narrowing is a portability constraint, not taste — see _state's own comment. In the usage reset() exists for (void onNewQuery() { _callbacks.reset(); }, the supersede verb) the owning thread is the caller anyway. Within a single generation the guarantee is unconditional: reset() stops the outgoing generation before releasing it, so a token holder that pinned it still observes refusal.
Identity, not a value: neither copyable nor movable. A moved-from scope would have to either strand or silently retarget tokens already captured in flight; reset() covers the one case (regeneration) that motivates a move at all.
Definition at line 235 of file callback_scope.hpp.
|
inline |
Constructs a live, un-stopped scope.
Definition at line 238 of file callback_scope.hpp.
|
inline |
Refuses every outstanding token, then releases the state.
Equivalent, from a pending callback's point of view, to requestStop(). Does not wait for in-flight callbacks — see "Boundary of the guarantee".
Definition at line 244 of file callback_scope.hpp.
|
inlinenoexcept |
Marks this generation stopped: gated callbacks stop being delivered, and every call the scope owns is asked to stop.
A call is owned by the scope once a Completion carrying a stop source (a Bridge call whose handler returns a Task) has a callback attached through one of its tokens; its stop is requested here, on this thread, before this returns. Idempotent and safe from any thread. The owner remains alive, so tokens report CallbackStatus::Stopped rather than Expired. Undone only by reset(), which starts a new generation.
Definition at line 260 of file callback_scope.hpp.
|
inline |
Retires every token issued so far and starts a fresh, live generation.
The supersede verb: an old in-flight reply can no longer be delivered (its token reports Expired), while callbacks attached after this call are deliverable again even if requestStop() had been called before it. The outgoing generation is stopped before it is released, so a token holder that pinned it while racing this call still observes refusal.
Definition at line 275 of file callback_scope.hpp.
|
inlinenodiscardnoexcept |
Whether this generation has been stopped.
Definition at line 283 of file callback_scope.hpp.
|
inlinenodiscardnoexcept |
Issues a weak token for the current generation.
Definition at line 287 of file callback_scope.hpp.
|
inlinenodiscard |
Wraps fn so it runs only while this scope is alive and un-stopped.
Forwards to CallbackToken::guard() on a token for the current generation, so a later reset() retires the wrapper. This is the general-purpose form for the callbacks that are not Completion attachments — timer ticks, IExecutor::post closures, poller dispatch, event sinks.
| F | Callable type to wrap; must return void (see CallbackToken::guard()). |
| fn | Callable to gate. Moved into the returned wrapper. |
fn's argument list and a void return. Definition at line 301 of file callback_scope.hpp.