async_std/future/
timeout.rs

1use std::error::Error;
2use std::fmt;
3use std::pin::Pin;
4use std::time::Duration;
5use std::future::Future;
6
7use futures_timer::Delay;
8use pin_project_lite::pin_project;
9
10use crate::task::{Context, Poll};
11
12/// Awaits a future or times out after a duration of time.
13///
14/// If you want to await an I/O future consider using
15/// [`io::timeout`](../io/fn.timeout.html) instead.
16///
17/// # Examples
18///
19/// ```
20/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
21/// #
22/// use std::time::Duration;
23///
24/// use async_std::future;
25///
26/// let never = future::pending::<()>();
27/// let dur = Duration::from_millis(5);
28/// assert!(future::timeout(dur, never).await.is_err());
29/// #
30/// # Ok(()) }) }
31/// ```
32pub async fn timeout<F, T>(dur: Duration, f: F) -> Result<T, TimeoutError>
33where
34    F: Future<Output = T>,
35{
36    let f = TimeoutFuture {
37        future: f,
38        delay: Delay::new(dur),
39    };
40    f.await
41}
42
43pin_project! {
44    /// A future that times out after a duration of time.
45    pub struct TimeoutFuture<F> {
46        #[pin]
47        future: F,
48        #[pin]
49        delay: Delay,
50    }
51}
52
53impl<F> TimeoutFuture<F> {
54    #[allow(dead_code)]
55    pub(super) fn new(future: F, dur: Duration) -> TimeoutFuture<F> {
56        TimeoutFuture { future: future, delay: Delay::new(dur) }
57    }
58}
59
60impl<F: Future> Future for TimeoutFuture<F> {
61    type Output = Result<F::Output, TimeoutError>;
62
63    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
64        let this = self.project();
65        match this.future.poll(cx) {
66            Poll::Ready(v) => Poll::Ready(Ok(v)),
67            Poll::Pending => match this.delay.poll(cx) {
68                Poll::Ready(_) => Poll::Ready(Err(TimeoutError { _private: () })),
69                Poll::Pending => Poll::Pending,
70            },
71        }
72    }
73}
74
75/// An error returned when a future times out.
76#[derive(Clone, Copy, Debug, Eq, PartialEq)]
77pub struct TimeoutError {
78    _private: (),
79}
80
81impl Error for TimeoutError {}
82
83impl fmt::Display for TimeoutError {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        "future has timed out".fmt(f)
86    }
87}