Skip to content

Commit 5aa0e24

Browse files
author
Stjepan Glavina
committed
Add future::timeout()
1 parent 13835b0 commit 5aa0e24

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/future/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ pub use std::future::Future;
55

66
pub use pending::pending;
77
pub use ready::ready;
8+
pub use timeout::{timeout, TimeoutError};
89

910
mod pending;
1011
mod ready;
12+
mod timeout;

src/future/timeout.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use std::error::Error;
2+
use std::fmt;
3+
use std::pin::Pin;
4+
use std::time::Duration;
5+
6+
use futures_timer::Delay;
7+
use pin_utils::unsafe_pinned;
8+
9+
use crate::future::Future;
10+
use crate::task::{Context, Poll};
11+
12+
/// Awaits a future or times out after a duration of time.
13+
///
14+
/// # Examples
15+
///
16+
/// ```no_run
17+
/// # #![feature(async_await)]
18+
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
19+
/// #
20+
/// use std::time::Duration;
21+
///
22+
/// use async_std::future;
23+
///
24+
/// let never = future::pending::<()>();
25+
/// let dur = Duration::from_secs(5);
26+
/// assert!(future::timeout(dur, never).await.is_err());
27+
/// #
28+
/// # Ok(()) }) }
29+
/// ```
30+
pub async fn timeout<F, T>(dur: Duration, f: F) -> Result<T, TimeoutError>
31+
where
32+
F: Future<Output = T>,
33+
{
34+
let f = TimeoutFuture {
35+
future: f,
36+
delay: Delay::new(dur),
37+
};
38+
f.await
39+
}
40+
41+
/// A future that times out after a duration of time.
42+
#[doc(hidden)]
43+
#[allow(missing_debug_implementations)]
44+
struct TimeoutFuture<F> {
45+
future: F,
46+
delay: Delay,
47+
}
48+
49+
impl<F> TimeoutFuture<F> {
50+
unsafe_pinned!(future: F);
51+
unsafe_pinned!(delay: Delay);
52+
}
53+
54+
impl<F: Future> Future for TimeoutFuture<F> {
55+
type Output = Result<F::Output, TimeoutError>;
56+
57+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
58+
match self.as_mut().future().poll(cx) {
59+
Poll::Ready(v) => Poll::Ready(Ok(v)),
60+
Poll::Pending => match self.delay().poll(cx) {
61+
Poll::Ready(_) => Poll::Ready(Err(TimeoutError)),
62+
Poll::Pending => Poll::Pending,
63+
},
64+
}
65+
}
66+
}
67+
68+
/// An error returned when a future times out.
69+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
70+
pub struct TimeoutError;
71+
72+
impl Error for TimeoutError {}
73+
74+
impl fmt::Display for TimeoutError {
75+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76+
"future has timed out".fmt(f)
77+
}
78+
}

0 commit comments

Comments
 (0)