1use futures::{FutureExt, StreamExt};
2use std::{
3 future::Future,
4 ops::Deref,
5 pin::Pin,
6 sync::{
7 Arc,
8 atomic::{self, AtomicBool},
9 },
10 time::Duration,
11};
12
13#[derive(Debug, Clone)]
14pub struct WaitTokenRepeat<Tk> {
15 tk: Tk,
16 frq: Duration,
17}
18impl WaitTokenRepeat<WaitToken> {
19 pub async fn next(&mut self) -> bool {
20 let result = tokio::select! {
21 _ = tokio::time::sleep(self.frq) => {true}
22 _ = self.tk.cancelled() => {false}
23 };
24 result
25 }
26}
27
28#[derive(Debug, Default)]
29pub struct WaitTokenGuard {
30 tk: WaitToken,
31}
32impl Drop for WaitTokenGuard {
33 fn drop(&mut self) {
34 self.tk.cancel();
35 }
36}
37impl Deref for WaitTokenGuard {
38 type Target = WaitToken;
39
40 fn deref(&self) -> &Self::Target {
41 &self.tk
42 }
43}
44impl WaitTokenGuard {
45 pub fn new() -> Self {
46 Self {
47 tk: WaitToken::new(),
48 }
49 }
50 pub fn clone_tk(&self) -> WaitToken {
51 self.deref().clone()
52 }
53}
54
55#[derive(Debug, Clone)]
96pub struct WaitToken {
97 inner: Arc<WaitTokenRaw>,
98}
99
100pub type CancellationToken = WaitToken;
101
102#[derive(Debug)]
103struct WaitTokenRaw {
104 state: AtomicBool,
105 parent: Option<WaitToken>,
106 future: Option<tokio::sync::Notify>,
107}
108
109impl WaitTokenRaw {
110 pub fn is_cancelled(&self) -> bool {
111 if let Some(parent) = &self.parent {
112 if parent.is_cancelled() {
113 return true;
114 }
115 }
116 self.state.load(atomic::Ordering::Acquire)
117 }
118
119 fn notified<'a: 'b, 'b>(&'a self) -> tokio::sync::futures::Notified<'b> {
120 if let Some(parent) = &self.parent {
121 return parent.inner.notified();
122 }
123 self.future.as_ref().unwrap().notified()
124 }
125}
126
127#[derive(Debug, Clone, Copy, PartialEq, Eq)]
128pub enum CancelState {
129 AlreadyCancelled,
130 Cancelled,
131}
132impl CancelState {
133 pub fn already_cancelled(self) -> bool {
134 self == CancelState::AlreadyCancelled
135 }
136 pub fn just_cancelled(self) -> bool {
137 self == CancelState::Cancelled
138 }
139}
140
141impl WaitToken {
142 pub fn new() -> Self {
144 Self {
145 inner: Arc::new(WaitTokenRaw {
146 state: false.into(),
147 parent: None,
148 future: Some(tokio::sync::Notify::new()),
149 }),
150 }
151 }
152
153 pub fn spawn_terminator(&self) -> std::thread::JoinHandle<Result<(), std::io::Error>> {
155 let this = self.clone();
156 std::thread::spawn(move || {
157 let mut signals = signal_hook::iterator::Signals::new([
158 signal_hook::consts::SIGTERM,
159 signal_hook::consts::SIGINT,
160 ])
161 .inspect_err(|_| {
162 this.cancel();
163 })?;
164
165 for _ in &mut signals {
166 this.cancel();
167 }
168
169 Ok(())
170 })
171 }
172
173 pub fn ready() -> Self {
175 Self {
176 inner: Arc::new(WaitTokenRaw {
177 state: true.into(),
178 parent: None,
179 future: Some(tokio::sync::Notify::new()),
180 }),
181 }
182 }
183
184 fn wake(&self) {
185 if let Some(parent) = &self.inner.parent {
186 parent.wake();
187 return;
188 }
189 if let Some(future) = &self.inner.future {
190 future.notify_waiters();
191 }
192 }
193
194 fn notified(&self) -> tokio::sync::futures::Notified<'_> {
195 self.inner.notified()
196 }
197
198 pub fn cancel(&self) -> CancelState {
200 if self.inner.state.swap(true, atomic::Ordering::Release) {
201 return CancelState::AlreadyCancelled;
202 }
203 self.wake();
204 CancelState::Cancelled
205 }
206
207 pub fn reset(&self) {
209 self.inner.state.store(false, atomic::Ordering::Release);
210 }
211
212 pub fn is_cancelled(&self) -> bool {
213 self.inner.is_cancelled()
214 }
215
216 pub fn cancelled(&self) -> WaitTokenCancelled {
217 WaitTokenCancelled {
218 token: self.clone(),
219 future: Box::pin(unsafe {
220 std::mem::transmute::<
221 tokio::sync::futures::Notified<'_>,
222 tokio::sync::futures::Notified<'_>,
223 >(self.notified())
224 }),
225 }
226 }
227
228 pub fn until_cancel(
230 &self,
231 ) -> futures::stream::TakeUntil<futures::stream::Repeat<()>, WaitTokenCancelled> {
232 futures::stream::repeat(()).take_until(self.cancelled())
233 }
234
235 pub fn on_cancel(&self) -> futures::stream::Once<WaitTokenCancelled> {
236 futures::stream::once(self.cancelled())
237 }
238 pub async fn on_cancel_then<Fut: Future + Send>(self, fut: Fut) -> Fut::Output {
239 self.cancelled().then(|_| fut).await
240 }
241 pub fn repeat_until_cancel(&self, frq: Duration) -> WaitTokenRepeat<Self> {
252 WaitTokenRepeat {
253 tk: self.clone(),
254 frq,
255 }
256 }
257
258 pub async fn run_fn<Fut: Future>(&self, fut: Fut) -> Option<Fut::Output> {
260 tokio::select! {
261 a = fut => Some(a),
262 _ = self.cancelled() => None,
263 }
264 }
265
266 pub fn make_child_token(&self) -> Self {
269 Self {
270 inner: Arc::new(WaitTokenRaw {
271 state: false.into(),
272 parent: Some(self.clone()),
273 future: None,
274 }),
275 }
276 }
277
278 pub fn guard(&self) -> WaitTokenGuard {
280 WaitTokenGuard { tk: self.clone() }
281 }
282}
283
284impl Default for WaitToken {
285 fn default() -> Self {
286 Self::new()
287 }
288}
289
290pub struct WaitTokenCancelled {
291 token: WaitToken,
292 future: Pin<Box<tokio::sync::futures::Notified<'static>>>,
293}
294
295impl Future for WaitTokenCancelled {
296 type Output = ();
297
298 fn poll(
299 mut self: std::pin::Pin<&mut Self>,
300 cx: &mut std::task::Context<'_>,
301 ) -> std::task::Poll<Self::Output> {
302 loop {
303 if self.token.is_cancelled() {
304 return std::task::Poll::Ready(());
305 }
306
307 if self.future.poll_unpin(cx).is_pending() {
308 return std::task::Poll::Pending;
309 }
310
311 if self.token.is_cancelled() {
312 return std::task::Poll::Ready(());
313 }
314
315 let future = unsafe {
316 std::mem::transmute::<
317 tokio::sync::futures::Notified<'_>,
318 tokio::sync::futures::Notified<'_>,
319 >(self.token.notified())
320 };
321 self.future.set(future);
322 }
323 }
324}