Skip to main content

molframe_core/execution/
cancellation.rs

1//! Cooperative cancellation shared by all stages of an execution.
2
3use std::fmt;
4use std::sync::Arc;
5use std::sync::atomic::{AtomicBool, Ordering};
6
7/// A cheap, thread-safe cooperative cancellation handle.
8#[derive(Clone, Debug, Default)]
9pub struct CancellationToken {
10    cancelled: Arc<AtomicBool>,
11}
12
13impl CancellationToken {
14    /// Creates an active token.
15    #[must_use]
16    pub fn new() -> Self {
17        Self::default()
18    }
19
20    /// Requests cancellation for this token and all of its clones.
21    pub fn cancel(&self) {
22        self.cancelled.store(true, Ordering::Release);
23    }
24
25    /// Reports whether cancellation has been requested.
26    #[must_use]
27    pub fn is_cancelled(&self) -> bool {
28        self.cancelled.load(Ordering::Acquire)
29    }
30
31    /// Converts the current state into a branch-friendly result.
32    ///
33    /// # Errors
34    ///
35    /// Returns [`Cancelled`] after this token or one of its clones is cancelled.
36    pub fn check(&self) -> Result<(), Cancelled> {
37        if self.is_cancelled() {
38            return Err(Cancelled);
39        }
40        Ok(())
41    }
42}
43
44/// An execution stopped after cooperative cancellation was requested.
45#[derive(Clone, Copy, Debug, PartialEq, Eq)]
46pub struct Cancelled;
47
48impl fmt::Display for Cancelled {
49    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
50        formatter.write_str("execution cancelled")
51    }
52}
53
54impl std::error::Error for Cancelled {}
55
56#[cfg(test)]
57#[path = "cancellation_tests.rs"]
58mod tests;