feat(cancel): cooperative cancellation via sentinel unwind
request_stop(pid) sets a per-actor flag and wakes a parked target. The actor realizes the stop as a controlled unwind at its next observation point (check!()/alloc via maybe_preempt, or the wakeup side of any blocking park): a StopSentinel panic tears the stack down via the trampoline's existing catch_unwind, running Drop, and is reported as the new Outcome::Stopped (distinct from a user Panic). Death surface kept distinct from Exit: Signal::Stopped(pid) + DownReason::Stopped, so the supervisor await logic to come can tell a requested stop apart from a self-termination. Flag lives on Actor behind Arc<AtomicBool>; the scheduler resume path takes a raw pointer into it (no per-resume refcount traffic), keeping yield throughput at baseline.
This commit is contained in:
@@ -16,6 +16,10 @@ pub enum Signal {
|
||||
Exit(Pid),
|
||||
/// The child panicked. Payload is whatever `panic!` was called with.
|
||||
Panic(Pid, Box<dyn Any + Send>),
|
||||
/// The child was cooperatively cancelled via `request_stop`. Carries no
|
||||
/// payload — there is nothing to propagate. Kept distinct from `Exit` so a
|
||||
/// supervisor can distinguish a stop it requested from a self-termination.
|
||||
Stopped(Pid),
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Signal {
|
||||
@@ -23,6 +27,7 @@ impl std::fmt::Debug for Signal {
|
||||
match self {
|
||||
Signal::Exit(pid) => write!(f, "Signal::Exit({:?})", pid),
|
||||
Signal::Panic(pid, _) => write!(f, "Signal::Panic({:?}, ..)", pid),
|
||||
Signal::Stopped(pid) => write!(f, "Signal::Stopped({:?})", pid),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +37,7 @@ impl Signal {
|
||||
match self {
|
||||
Signal::Exit(p) => *p,
|
||||
Signal::Panic(p, _) => *p,
|
||||
Signal::Stopped(p) => *p,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user