async_std/future/
timeout.rs1use std::error::Error;
2use std::fmt;
3use std::future::Future;
4use std::pin::Pin;
5use std::time::Duration;
6
7use pin_project_lite::pin_project;
8
9use crate::task::{Context, Poll};
10use crate::utils::{timer_after, Timer};
11
12pub async fn timeout<F, T>(dur: Duration, f: F) -> Result<T, TimeoutError>
33where
34 F: Future<Output = T>,
35{
36 TimeoutFuture::new(f, dur).await
37}
38
39pin_project! {
40 pub struct TimeoutFuture<F> {
42 #[pin]
43 future: F,
44 #[pin]
45 delay: Timer,
46 }
47}
48
49impl<F> TimeoutFuture<F> {
50 #[allow(dead_code)]
51 pub(super) fn new(future: F, dur: Duration) -> TimeoutFuture<F> {
52 TimeoutFuture {
53 future,
54 delay: timer_after(dur),
55 }
56 }
57}
58
59impl<F: Future> Future for TimeoutFuture<F> {
60 type Output = Result<F::Output, TimeoutError>;
61
62 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
63 let this = self.project();
64 match this.future.poll(cx) {
65 Poll::Ready(v) => Poll::Ready(Ok(v)),
66 Poll::Pending => match this.delay.poll(cx) {
67 Poll::Ready(_) => Poll::Ready(Err(TimeoutError { _private: () })),
68 Poll::Pending => Poll::Pending,
69 },
70 }
71 }
72}
73
74#[derive(Clone, Copy, Debug, Eq, PartialEq)]
76pub struct TimeoutError {
77 _private: (),
78}
79
80impl Error for TimeoutError {}
81
82impl fmt::Display for TimeoutError {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 "future has timed out".fmt(f)
85 }
86}