pub trait Stop: Send + Sync {
// Required method
fn check(&self) -> Result<(), StopReason>;
// Provided methods
fn should_stop(&self) -> bool { ... }
fn may_stop(&self) -> bool { ... }
}Expand description
Cooperative cancellation check.
Implement this trait for custom cancellation sources. The implementation
must be thread-safe (Send + Sync) to support parallel processing and
async runtimes.
§Example Implementation
use enough::{Stop, StopReason};
use core::sync::atomic::{AtomicBool, Ordering};
pub struct MyStop<'a> {
cancelled: &'a AtomicBool,
}
impl Stop for MyStop<'_> {
fn check(&self) -> Result<(), StopReason> {
if self.cancelled.load(Ordering::Relaxed) {
Err(StopReason::Cancelled)
} else {
Ok(())
}
}
}Required Methods§
Sourcefn check(&self) -> Result<(), StopReason>
fn check(&self) -> Result<(), StopReason>
Check if the operation should stop.
Returns Ok(()) to continue, Err(StopReason) to stop.
Call this periodically in long-running loops. The frequency depends on your workload - typically every 16-1000 iterations is reasonable.
#[track_caller] lets instrumented implementations (e.g.
almost_enough::PollMeter) attribute a poll to this call site.
Implementations that don’t need it are unaffected.
Provided Methods§
Sourcefn should_stop(&self) -> bool
fn should_stop(&self) -> bool
Returns true if the operation should stop.
Convenience method for when you want to handle stopping yourself
rather than using the ? operator.
Sourcefn may_stop(&self) -> bool
fn may_stop(&self) -> bool
Returns true if this stop can ever signal a stop.
Unstoppable returns false. Wrapper types delegate to their
inner stop. The default is true (conservative — always check).
Behind &dyn Stop, live uses this to skip checks
in hot loops: it returns None for a stop that can never stop.
In generic code (impl Stop), this is unnecessary — the compiler
already optimizes Unstoppable::check() to nothing via inlining.
Implementations§
Source§impl<'a> dyn Stop + 'a
impl<'a> dyn Stop + 'a
Sourcepub fn live(&self) -> Option<&(dyn Stop + 'a)>
pub fn live(&self) -> Option<&(dyn Stop + 'a)>
This stop, or None if it can never stop.
For a loop that checks a &dyn Stop often: a stop whose
may_stop returns false, such as Unstoppable,
becomes None. Option<&dyn Stop> implements Stop (None never
stops), so each check costs a branch the compiler can hoist out of the
loop instead of a call. Call it once, before the loop.
“Live” means the stop can fire, not that it hasn’t: a stop that was cancelled is still live, and checking it returns the stop.
use enough::{Stop, StopReason, Unstoppable};
fn decode(rows: &[u8], stop: &dyn Stop) -> Result<usize, StopReason> {
let stop = stop.live();
for _ in rows {
stop.check()?; // a branch, not a call, for Unstoppable
}
Ok(rows.len())
}
assert!((&Unstoppable as &dyn Stop).live().is_none());
assert_eq!(decode(&[1, 2, 3], &Unstoppable), Ok(3));Generic code (impl Stop) doesn’t need it: there Unstoppable’s
checks inline to nothing.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementations on Foreign Types§
Source§impl<T> Stop for Option<T>where
T: Stop,
Option<T> implements Stop: None is a no-op (always Ok(())),
Some(inner) delegates to the inner stop.
impl<T> Stop for Option<T>where
T: Stop,
Option<T> implements Stop: None is a no-op (always Ok(())),
Some(inner) delegates to the inner stop.
This is what live returns: a hot loop checks the
Option and pays a branch instead of a call when the stop can never stop.