Skip to content

Commit 38a8676

Browse files
Stjepan Glavinayoshuawuyts
Stjepan Glavina
authored andcommitted
Add future::timeout() (#20)
* Add future::timeout() * Update src/future/timeout.rs Co-Authored-By: Yoshua Wuyts <yoshuawuyts+github@gmail.com> * Update src/future/timeout.rs Co-Authored-By: Yoshua Wuyts <yoshuawuyts+github@gmail.com> * Put futues::timeout behind unstable feature
1 parent 374f0c9 commit 38a8676

File tree

4 files changed

+92
-2
lines changed

4 files changed

+92
-2
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ before_script:
1919
- if [[ -n "$BUILD_BOOK" ]]; then (test -x $HOME/.cargo/bin/mdbook || ./ci/install-mdbook.sh); fi
2020

2121
script:
22-
- if ! [[ -n "$BUILD_BOOK" ]]; then cargo check --all --benches --bins --examples --tests && cargo test --all; fi
23-
- if [[ -n "$BUILD_BOOK" ]]; then cargo test --all --benches --bins --examples --tests; fi
22+
- if ! [[ -n "$BUILD_BOOK" ]]; then cargo check --features unstable --all --benches --bins --examples --tests && cargo test --features unstable --all; fi
23+
- if [[ -n "$BUILD_BOOK" ]]; then cargo test --features unstable --all --benches --bins --examples --tests; fi
2424
- cargo fmt --all -- --check
2525
- if [[ -n "$BUILD_DOCS" ]]; then cargo doc --features docs; fi
2626
- if [[ -n "$BUILD_BOOK" ]]; then mdbook build docs && mdbook test -L ./target/debug/deps docs; fi

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ rustdoc-args = ["--cfg", "feature=\"docs\""]
2121

2222
[features]
2323
docs = []
24+
unstable = []
2425

2526
[dependencies]
2627
async-task = "1.0.0"

src/future/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,17 @@
33
#[doc(inline)]
44
pub use std::future::Future;
55

6+
use cfg_if::cfg_if;
7+
68
pub use pending::pending;
79
pub use ready::ready;
810

911
mod pending;
1012
mod ready;
13+
14+
cfg_if! {
15+
if #[cfg(any(feature = "unstable", feature = "docs"))] {
16+
mod timeout;
17+
pub use timeout::{timeout, TimeoutError};
18+
}
19+
}

src/future/timeout.rs

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

0 commit comments

Comments
 (0)