Skip to content

Commit 487811e

Browse files
author
Stjepan Glavina
authored
Merge pull request #19 from async-rs/io-timeout
Add io::timeout()
2 parents 62be014 + 2e3bc63 commit 487811e

File tree

3 files changed

+78
-14
lines changed

3 files changed

+78
-14
lines changed

examples/stdin-timeout.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,13 @@ use async_std::prelude::*;
99
use async_std::task;
1010

1111
fn main() -> io::Result<()> {
12-
task::block_on(async {
12+
task::block_on(io::timeout(Duration::from_secs(5), async {
1313
let stdin = io::stdin();
14-
let mut line = String::new();
1514

16-
match stdin
17-
.read_line(&mut line)
18-
.timeout(Duration::from_secs(5))
19-
.await
20-
{
21-
Ok(res) => {
22-
res?;
23-
print!("Got line: {}", line);
24-
}
25-
Err(_) => println!("You have only 5 seconds to enter a line. Try again :)"),
26-
}
15+
let mut line = String::new();
16+
stdin.read_line(&mut line).await?;
2717

18+
print!("Got line: {}", line);
2819
Ok(())
29-
})
20+
}))
3021
}

src/io/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub use sink::{sink, Sink};
3434
pub use stderr::{stderr, Stderr};
3535
pub use stdin::{stdin, Stdin};
3636
pub use stdout::{stdout, Stdout};
37+
pub use timeout::timeout;
3738
pub use write::Write;
3839

3940
mod buf_read;
@@ -46,4 +47,5 @@ mod sink;
4647
mod stderr;
4748
mod stdin;
4849
mod stdout;
50+
mod timeout;
4951
mod write;

src/io/timeout.rs

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use std::pin::Pin;
2+
use std::time::Duration;
3+
4+
use futures_timer::Delay;
5+
use pin_utils::unsafe_pinned;
6+
7+
use crate::future::Future;
8+
use crate::io;
9+
use crate::task::{Context, Poll};
10+
11+
/// Awaits an I/O future or times out after a duration of time.
12+
///
13+
/// # Examples
14+
///
15+
/// ```no_run
16+
/// # #![feature(async_await)]
17+
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
18+
/// #
19+
/// use std::time::Duration;
20+
///
21+
/// use async_std::io;
22+
///
23+
/// io::timeout(Duration::from_secs(5), async {
24+
/// let stdin = io::stdin();
25+
/// let mut line = String::new();
26+
/// let n = stdin.read_line(&mut line).await?;
27+
/// })
28+
/// .await?;
29+
/// #
30+
/// # Ok(()) }) }
31+
/// ```
32+
pub async fn timeout<F, T>(dur: Duration, f: F) -> io::Result<T>
33+
where
34+
F: Future<Output = io::Result<T>>,
35+
{
36+
let f = TimeoutFuture {
37+
future: f,
38+
delay: Delay::new(dur),
39+
};
40+
f.await
41+
}
42+
43+
struct TimeoutFuture<F> {
44+
future: F,
45+
delay: Delay,
46+
}
47+
48+
impl<F> TimeoutFuture<F> {
49+
unsafe_pinned!(future: F);
50+
unsafe_pinned!(delay: Delay);
51+
}
52+
53+
impl<F, T> Future for TimeoutFuture<F>
54+
where
55+
F: Future<Output = io::Result<T>>,
56+
{
57+
type Output = F::Output;
58+
59+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
60+
match self.as_mut().future().poll(cx) {
61+
Poll::Ready(v) => Poll::Ready(v),
62+
Poll::Pending => match self.delay().poll(cx) {
63+
Poll::Ready(_) => Poll::Ready(Err(io::Error::new(
64+
io::ErrorKind::TimedOut,
65+
"I/O operation has timed out",
66+
))),
67+
Poll::Pending => Poll::Pending,
68+
},
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)