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}