Skip to main content

Stop

Trait Stop 

Source
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§

Source

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§

Source

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.

Source

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.

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());
Source§

impl<T> Stop for &T
where T: Stop + ?Sized,

Source§

impl<T> Stop for &mut T
where T: Stop + ?Sized,

Implementors§