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}