• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Allows a future to execute for a maximum amount of time.
2 //!
3 //! See [`Timeout`] documentation for more details.
4 //!
5 //! [`Timeout`]: struct@Timeout
6 
7 use crate::time::{error::Elapsed, sleep_until, Duration, Instant, Sleep};
8 
9 use pin_project_lite::pin_project;
10 use std::future::Future;
11 use std::pin::Pin;
12 use std::task::{self, Poll};
13 
14 /// Require a `Future` to complete before the specified duration has elapsed.
15 ///
16 /// If the future completes before the duration has elapsed, then the completed
17 /// value is returned. Otherwise, an error is returned and the future is
18 /// canceled.
19 ///
20 /// # Cancelation
21 ///
22 /// Cancelling a timeout is done by dropping the future. No additional cleanup
23 /// or other work is required.
24 ///
25 /// The original future may be obtained by calling [`Timeout::into_inner`]. This
26 /// consumes the `Timeout`.
27 ///
28 /// # Examples
29 ///
30 /// Create a new `Timeout` set to expire in 10 milliseconds.
31 ///
32 /// ```rust
33 /// use tokio::time::timeout;
34 /// use tokio::sync::oneshot;
35 ///
36 /// use std::time::Duration;
37 ///
38 /// # async fn dox() {
39 /// let (tx, rx) = oneshot::channel();
40 /// # tx.send(()).unwrap();
41 ///
42 /// // Wrap the future with a `Timeout` set to expire in 10 milliseconds.
43 /// if let Err(_) = timeout(Duration::from_millis(10), rx).await {
44 ///     println!("did not receive value within 10 ms");
45 /// }
46 /// # }
47 /// ```
timeout<T>(duration: Duration, future: T) -> Timeout<T> where T: Future,48 pub fn timeout<T>(duration: Duration, future: T) -> Timeout<T>
49 where
50     T: Future,
51 {
52     let deadline = Instant::now().checked_add(duration);
53     let delay = match deadline {
54         Some(deadline) => Sleep::new_timeout(deadline),
55         None => Sleep::far_future(),
56     };
57     Timeout::new_with_delay(future, delay)
58 }
59 
60 /// Require a `Future` to complete before the specified instant in time.
61 ///
62 /// If the future completes before the instant is reached, then the completed
63 /// value is returned. Otherwise, an error is returned.
64 ///
65 /// # Cancelation
66 ///
67 /// Cancelling a timeout is done by dropping the future. No additional cleanup
68 /// or other work is required.
69 ///
70 /// The original future may be obtained by calling [`Timeout::into_inner`]. This
71 /// consumes the `Timeout`.
72 ///
73 /// # Examples
74 ///
75 /// Create a new `Timeout` set to expire in 10 milliseconds.
76 ///
77 /// ```rust
78 /// use tokio::time::{Instant, timeout_at};
79 /// use tokio::sync::oneshot;
80 ///
81 /// use std::time::Duration;
82 ///
83 /// # async fn dox() {
84 /// let (tx, rx) = oneshot::channel();
85 /// # tx.send(()).unwrap();
86 ///
87 /// // Wrap the future with a `Timeout` set to expire 10 milliseconds into the
88 /// // future.
89 /// if let Err(_) = timeout_at(Instant::now() + Duration::from_millis(10), rx).await {
90 ///     println!("did not receive value within 10 ms");
91 /// }
92 /// # }
93 /// ```
timeout_at<T>(deadline: Instant, future: T) -> Timeout<T> where T: Future,94 pub fn timeout_at<T>(deadline: Instant, future: T) -> Timeout<T>
95 where
96     T: Future,
97 {
98     let delay = sleep_until(deadline);
99 
100     Timeout {
101         value: future,
102         delay,
103     }
104 }
105 
106 pin_project! {
107     /// Future returned by [`timeout`](timeout) and [`timeout_at`](timeout_at).
108     #[must_use = "futures do nothing unless you `.await` or poll them"]
109     #[derive(Debug)]
110     pub struct Timeout<T> {
111         #[pin]
112         value: T,
113         #[pin]
114         delay: Sleep,
115     }
116 }
117 
118 impl<T> Timeout<T> {
new_with_delay(value: T, delay: Sleep) -> Timeout<T>119     pub(crate) fn new_with_delay(value: T, delay: Sleep) -> Timeout<T> {
120         Timeout { value, delay }
121     }
122 
123     /// Gets a reference to the underlying value in this timeout.
get_ref(&self) -> &T124     pub fn get_ref(&self) -> &T {
125         &self.value
126     }
127 
128     /// Gets a mutable reference to the underlying value in this timeout.
get_mut(&mut self) -> &mut T129     pub fn get_mut(&mut self) -> &mut T {
130         &mut self.value
131     }
132 
133     /// Consumes this timeout, returning the underlying value.
into_inner(self) -> T134     pub fn into_inner(self) -> T {
135         self.value
136     }
137 }
138 
139 impl<T> Future for Timeout<T>
140 where
141     T: Future,
142 {
143     type Output = Result<T::Output, Elapsed>;
144 
poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output>145     fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
146         let me = self.project();
147 
148         // First, try polling the future
149         if let Poll::Ready(v) = me.value.poll(cx) {
150             return Poll::Ready(Ok(v));
151         }
152 
153         // Now check the timer
154         match me.delay.poll(cx) {
155             Poll::Ready(()) => Poll::Ready(Err(Elapsed::new())),
156             Poll::Pending => Poll::Pending,
157         }
158     }
159 }
160