1use std::{
5 cell::{
6 Cell,
7 RefCell,
8 },
9 future::Future,
10 pin::Pin,
11 rc::Rc,
12 sync::{
13 Arc,
14 Mutex,
15 atomic::AtomicBool,
16 },
17 task::{
18 Context,
19 Poll,
20 Waker,
21 },
22};
23
24#[derive(Clone, Default)]
27pub struct Notify {
28 state: Rc<State>,
29}
30
31#[derive(Default)]
32struct State {
33 flag: Cell<bool>,
34 waker: Cell<Option<Waker>>,
35}
36
37impl Notify {
38 pub fn new() -> Self {
39 Self {
40 state: Rc::new(State {
41 flag: Cell::new(false),
42 waker: Cell::new(None),
43 }),
44 }
45 }
46
47 pub fn notify(&self) {
50 self.state.flag.set(true);
51
52 if let Some(w) = self.state.waker.take() {
53 w.wake();
54 }
55 }
56
57 pub fn notified(&self) -> Notified {
59 Notified {
60 state: self.state.clone(),
61 }
62 }
63}
64
65pub struct Notified {
66 state: Rc<State>,
67}
68
69impl Future for Notified {
70 type Output = ();
71
72 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
73 if self.state.flag.replace(false) {
74 Poll::Ready(())
75 } else {
76 self.state.waker.set(Some(cx.waker().clone()));
77 Poll::Pending
78 }
79 }
80}
81
82#[derive(Clone, Default)]
85pub struct ArcNotify {
86 state: Arc<StateArc>,
87}
88
89#[derive(Default)]
90struct StateArc {
91 flag: AtomicBool,
92 waker: Mutex<Option<Waker>>,
93}
94
95impl ArcNotify {
96 pub fn new() -> Self {
97 Self::default()
98 }
99
100 pub fn notify(&self) {
103 self.state
104 .flag
105 .store(true, std::sync::atomic::Ordering::SeqCst);
106
107 if let Ok(mut w) = self.state.waker.lock()
108 && let Some(waker) = w.take()
109 {
110 waker.wake();
111 }
112 }
113
114 pub fn notified(&self) -> NotifiedArc {
116 NotifiedArc {
117 state: self.state.clone(),
118 }
119 }
120}
121
122pub struct NotifiedArc {
123 state: Arc<StateArc>,
124}
125
126impl Future for NotifiedArc {
127 type Output = ();
128
129 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
130 if self
131 .state
132 .flag
133 .swap(false, std::sync::atomic::Ordering::SeqCst)
134 {
135 Poll::Ready(())
136 } else {
137 if let Ok(mut w) = self.state.waker.lock() {
138 *w = Some(cx.waker().clone());
139 }
140 Poll::Pending
141 }
142 }
143}
144
145#[derive(Clone, Default)]
148pub struct BroadcastNotify {
149 state: Rc<BroadcastState>,
150}
151
152#[derive(Default)]
153struct BroadcastState {
154 version: Cell<u64>,
155 wakers: RefCell<Vec<Waker>>,
156}
157
158impl BroadcastNotify {
159 pub fn new() -> Self {
160 Self::default()
161 }
162
163 pub fn notify(&self) {
166 self.state
167 .version
168 .set(self.state.version.get().wrapping_add(1));
169 for waker in self.state.wakers.take() {
170 waker.wake();
171 }
172 }
173
174 pub fn notified(&self) -> NotifiedBroadcast {
176 NotifiedBroadcast {
177 state: self.state.clone(),
178 version: self.state.version.get(),
179 }
180 }
181}
182
183pub struct NotifiedBroadcast {
184 state: Rc<BroadcastState>,
185 version: u64,
186}
187
188impl Future for NotifiedBroadcast {
189 type Output = ();
190
191 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
192 if self.state.version.get() != self.version {
193 Poll::Ready(())
194 } else {
195 let mut wakers = self.state.wakers.borrow_mut();
196 let waker = cx.waker();
197 if !wakers.iter().any(|registered| registered.will_wake(waker)) {
198 wakers.push(waker.clone());
199 }
200 Poll::Pending
201 }
202 }
203}
204
205#[cfg(test)]
206mod test {
207 use std::pin::pin;
208
209 use futures_lite::future::{
210 block_on,
211 poll_once,
212 };
213
214 use crate::BroadcastNotify;
215
216 #[test]
217 fn broadcast_notify() {
218 block_on(async {
219 let notify = BroadcastNotify::new();
220 let mut first = pin!(notify.notified());
221 let mut second = pin!(notify.notified());
222 assert_eq!(poll_once(&mut first).await, None);
223 assert_eq!(poll_once(&mut second).await, None);
224 notify.notify();
225 assert_eq!(poll_once(&mut first).await, Some(()));
226 assert_eq!(poll_once(&mut second).await, Some(()));
227
228 {
230 let mut cancelled = pin!(notify.notified());
231 assert_eq!(poll_once(&mut cancelled).await, None);
232 notify.notify();
233 }
234 let mut late = pin!(notify.notified());
235 assert_eq!(poll_once(&mut late).await, None);
236 notify.notify();
237 assert_eq!(poll_once(&mut late).await, Some(()));
238 });
239 }
240}