casus/lib.rs
1//! Casus is a simple library containing a handful of useful generic async primitives. At present, it contains `Event` and `Waiter` primitives.
2//!
3//! ## Event
4//!
5//! The Event primitive allows a future to await the completion of an event. Once the event is completed, all futures trying to await it will immediately return and continue until the event is reset.
6//!
7//! ```rs
8//! use casus::Event;
9//!
10//! let event = Event::new();
11//!
12//! // this will block until Event::set is called elsewhere
13//! event.wait().await;
14//! ```
15//!
16//! ## Waiter
17//!
18//! The Waiter primitive simply waits to be woken up with it's return value.
19//!
20//! ```rs
21//! use casus::Waiter;
22//!
23//! let waiter = Waiter::new();
24//!
25//! // this will block until Event::wake is called elsewhere
26//! waiter.await;
27//! ```
28
29use std::{
30 future::Future,
31 sync::{Arc, Mutex, RwLock},
32 task::{Poll, Waker},
33};
34/// The Event primitive allows a future to await the completion of an event. Once the event is completed, all futures trying to await it will immediately return and continue until the event is reset.
35///
36/// # Example
37///
38/// ```rs
39/// use casus::Event;
40///
41/// let event = Event::new();
42///
43/// // this will block until Event::set is called elsewhere
44/// event.wait().await;
45/// ```
46
47#[derive(Debug)]
48pub struct Event {
49 state: RwLock<bool>,
50 waiters: Mutex<Vec<Waiter<()>>>,
51}
52
53impl Event {
54 /// Creates a new `Event`
55 ///
56 /// # Example
57 /// ```rs
58 /// use casus::Event;
59 ///
60 /// let event = Event::new();
61 /// ```
62 pub fn new() -> Self {
63 Self {
64 state: RwLock::new(false),
65 waiters: Mutex::new(vec![]),
66 }
67 }
68
69 /// Waits for an event to be set
70 ///
71 /// # Example
72 /// ```rs
73 /// // will return when `Event::set` is called
74 /// event.wait().await;
75 /// ```
76 pub async fn wait(&self) -> bool {
77 let state = *self.state.read().unwrap();
78 if !state {
79 let fut = Waiter::new();
80 {
81 let mut waiters = self.waiters.lock().unwrap();
82 waiters.push(fut.clone());
83 }
84 fut.await;
85 }
86 true
87 }
88
89 /// Sets the event and returns all current and future waiters until the event is reset
90 ///
91 /// # Example
92 /// ```rs
93 /// event.set();
94 /// ```
95 pub fn set(&self) {
96 {
97 let mut state = self.state.write().unwrap();
98 *state = true;
99 }
100 for i in self.waiters.lock().unwrap().iter() {
101 i.wake(());
102 }
103 }
104
105 /// Clears the event, allowing waiters to start waiting again until the event is set
106 ///
107 /// # Example
108 /// ```rs
109 /// event.clear();
110 /// ```
111 pub fn clear(&self) {
112 *self.state.write().unwrap() = false;
113 }
114
115 /// Checks if the event is set
116 ///
117 /// # Example
118 /// ```rs
119 /// if !event.is_set() {
120 /// event.wait().await;
121 /// }
122 pub fn is_set(&self) -> bool {
123 *self.state.read().unwrap()
124 }
125}
126
127impl Default for Event {
128 fn default() -> Self {
129 Self::new()
130 }
131}
132/// The Waiter primitive simply waits to be woken up with it's return value.
133///
134/// # Example
135///
136/// ```rs
137/// use casus::Waiter;
138///
139/// let waiter = Waiter::new();
140///
141/// // this will block until Event::wake is called elsewhere
142/// waiter.await;
143/// ```
144
145#[derive(Clone, Debug)]
146pub struct Waiter<T>(
147 #[allow(clippy::type_complexity)] Arc<Mutex<(bool, Option<Waker>, Option<T>)>>,
148);
149
150impl<T> Waiter<T> {
151 /// Creates a new `Waiter`
152 ///
153 /// # Example
154 /// ```rs
155 /// use casus::Waiter;
156 ///
157 /// let waiter = Waiter::new();
158 /// ```
159 pub fn new() -> Self {
160 Self(Arc::new(Mutex::new((false, None, None))))
161 }
162
163 /// Wakes up the waiter with `T` as the return value, meaning anything awaiting the waiter will return the value T
164 ///
165 /// # Example
166 /// ```
167 /// waiter.wake(T)
168 /// ```
169 pub fn wake(&self, v: T) {
170 let mut state = self.0.lock().unwrap();
171 state.0 = true;
172 state.2 = Some(v);
173 if let Some(waker) = state.1.take() {
174 waker.wake();
175 }
176 }
177}
178
179impl<T> Default for Waiter<T> {
180 fn default() -> Self {
181 Self::new()
182 }
183}
184
185impl<T> Future for Waiter<T> {
186 type Output = T;
187
188 fn poll(
189 self: std::pin::Pin<&mut Self>,
190 cx: &mut std::task::Context<'_>,
191 ) -> std::task::Poll<Self::Output> {
192 let mut state = self.0.lock().unwrap();
193 if state.0 {
194 Poll::Ready(state.2.take().unwrap())
195 } else {
196 state.1 = Some(cx.waker().clone());
197 Poll::Pending
198 }
199 }
200}