Skip to main content

tea_control/
lib.rs

1#![forbid(unsafe_code)]
2#![deny(missing_docs)]
3
4//! Shared operation control primitives for `tea-rs`.
5//!
6//! # Example
7//!
8//! ```
9//! use tea_control::CancellationScope;
10//!
11//! let root = CancellationScope::new();
12//! let child = root.child();
13//! root.cancel();
14//! assert!(child.is_cancelled());
15//! ```
16
17use tokio_util::sync::CancellationToken;
18
19/// Cooperative cancellation scope for an owned operation and its children.
20///
21/// The implementation wraps Tokio internally, while the public contract does
22/// not expose Tokio tokens, runtime handles, channels, or tasks. Cancellation
23/// is idempotent and propagates from parent scopes to children.
24#[derive(Debug, Clone)]
25pub struct CancellationScope {
26    inner: CancellationToken,
27}
28
29impl CancellationScope {
30    /// Creates a pending root cancellation scope.
31    #[must_use]
32    pub fn new() -> Self {
33        Self {
34            inner: CancellationToken::new(),
35        }
36    }
37
38    /// Creates a child cancelled when this parent is cancelled.
39    ///
40    /// Cancelling the child does not cancel this parent.
41    #[must_use]
42    pub fn child(&self) -> Self {
43        Self {
44            inner: self.inner.child_token(),
45        }
46    }
47
48    /// Requests cooperative cancellation for this scope and its children.
49    pub fn cancel(&self) {
50        self.inner.cancel();
51    }
52
53    /// Returns whether cancellation has been requested.
54    #[must_use]
55    pub fn is_cancelled(&self) -> bool {
56        self.inner.is_cancelled()
57    }
58
59    /// Waits until cancellation is requested.
60    pub async fn cancelled(&self) {
61        self.inner.cancelled().await;
62    }
63}
64
65impl Default for CancellationScope {
66    fn default() -> Self {
67        Self::new()
68    }
69}