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