async_timeouts/timeout.rs
1use std::{future::Future, time::Duration};
2use tokio::{
3 sync::mpsc::{Sender, channel},
4 time,
5};
6
7#[derive(Debug)]
8enum Msg {
9 UpdateTerm(Duration),
10 Stop,
11}
12
13/// See more information about `reset` and `stop` methods
14#[derive(Debug, Clone)]
15pub struct Timeout {
16 tx: Sender<Msg>,
17}
18
19impl Timeout {
20 /// Schedule the task inside closure after timeout
21 pub async fn set(mut timeout: Duration, f: impl Future<Output = ()> + Send + 'static) -> Self
22 {
23 let (tx, mut rx) = channel(1);
24 tokio::spawn(async move {
25 loop {
26 tokio::select! {
27 _ = time::sleep(timeout) => {
28 f.await;
29 break;
30 },
31 Some(msg) = rx.recv() => {
32 match msg {
33 Msg::UpdateTerm(duration) => {
34 timeout = duration;
35 continue;
36 },
37 Msg::Stop => break,
38 }
39 },
40 else => break,
41 }
42 }
43 });
44 Timeout {
45 tx,
46 }
47 }
48
49 /// Reset timeout with a new value, i.e. to delay execution of your task
50 /// ## Example
51 /// ```rust
52 /// use std::time::Duration;
53 /// use async_timeouts::Timeout;
54 /// use tokio::sync::Notify;
55 /// use std::sync::Arc;
56 ///
57 /// #[tokio::main]
58 /// async fn main() {
59 /// let event = Arc::new(Notify::new());
60 /// let event_cloned = event.clone();
61 /// let x = Timeout::set(Duration::from_secs(3), async move {
62 /// println!("This message will be printed after 6 seconds");
63 /// event_cloned.notify_one();
64 /// }).await;
65 /// x.reset(Duration::from_secs(6)).await;
66 /// event.notified().await;
67 /// }
68 /// ```
69 pub async fn reset(&self, timeout: Duration) {
70 let _ = self.tx.send(Msg::UpdateTerm(timeout)).await;
71 }
72
73 /// Stop timer before your task will be executed
74 /// ## Example
75 /// ```rust,no_run
76 /// use std::time::Duration;
77 /// use async_timeouts::Timeout;
78 /// use tokio::sync::Notify;
79 /// use std::sync::Arc;
80 ///
81 /// #[tokio::main]
82 /// async fn main() {
83 /// let event = Arc::new(Notify::new());
84 ///
85 /// let event_cloned = event.clone();
86 /// let x = Timeout::set(Duration::from_secs(3), async move {
87 /// println!("This message will never be printed and event will never be notified.");
88 /// event_cloned.notify_one();
89 /// }).await;
90 ///
91 /// x.stop().await;
92 /// event.notified().await;
93 /// }
94 /// ```
95 pub async fn stop(&self) {
96 let _ = self.tx.send(Msg::Stop).await;
97 }
98
99}