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.
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).
Use this with impl Stop for Option<T> to skip checks in hot loops
behind dyn Stop:
use enough::{Stop, StopReason, Unstoppable};
fn process(stop: &dyn Stop) -> Result<(), StopReason> {
let stop = stop.may_stop().then_some(stop);
// stop is Option<&dyn Stop>, which impl Stop:
// None → check() always returns Ok(()), Some → delegates
for i in 0..100 {
stop.check()?;
}
Ok(())
}
// Unstoppable: may_stop() returns false, so stop is None
assert!(process(&Unstoppable).is_ok());In generic code (impl Stop), this is unnecessary — the compiler
already optimizes Unstoppable::check() to nothing via inlining.
Use may_stop() only when accepting &dyn Stop.
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 enables the may_stop() pattern for hot loops:
use enough::{Stop, StopReason, Unstoppable};
fn hot_loop(stop: &dyn Stop) -> Result<(), StopReason> {
let stop = stop.may_stop().then_some(stop);
for i in 0..1000 {
stop.check()?; // None → Ok(()), Some → delegates
}
Ok(())
}
assert!(hot_loop(&Unstoppable).is_ok());