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