From d512e7c45cd23a3290413e32d6fdf69f794d2ff7 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Wed, 14 Aug 2019 16:14:44 +0200 Subject: [PATCH 1/3] Add io::timeout() --- src/io/mod.rs | 2 ++ src/io/timeout.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/io/timeout.rs diff --git a/src/io/mod.rs b/src/io/mod.rs index daf70b8e..aae9cb56 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -32,6 +32,7 @@ pub use seek::Seek; pub use stderr::{stderr, Stderr}; pub use stdin::{stdin, Stdin}; pub use stdout::{stdout, Stdout}; +pub use timeout::timeout; pub use write::Write; mod buf_read; @@ -42,4 +43,5 @@ mod seek; mod stderr; mod stdin; mod stdout; +mod timeout; mod write; diff --git a/src/io/timeout.rs b/src/io/timeout.rs new file mode 100644 index 00000000..5902989e --- /dev/null +++ b/src/io/timeout.rs @@ -0,0 +1,70 @@ +use std::pin::Pin; +use std::time::Duration; + +use futures_timer::Delay; +use pin_utils::unsafe_pinned; + +use crate::future::Future; +use crate::io; +use crate::task::{Context, Poll}; + +/// Awaits an I/O future or times out after a duration of time. +/// +/// # Examples +/// +/// ```no_run +/// # #![feature(async_await)] +/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { +/// # +/// use std::time::Duration; +/// +/// use async_std::io; +/// +/// let stdin = io::stdin(); +/// let mut line = String::new(); +/// +/// let dur = Duration::from_secs(5); +/// let n = io::timeout(dur, stdin.read_line(&mut line)).await?; +/// # +/// # Ok(()) }) } +/// ``` +pub async fn timeout(dur: Duration, f: F) -> io::Result +where + F: Future>, +{ + let f = TimeoutFuture { + future: f, + delay: Delay::new(dur), + }; + f.await +} + +struct TimeoutFuture { + future: F, + delay: Delay, +} + +impl TimeoutFuture { + unsafe_pinned!(future: F); + unsafe_pinned!(delay: Delay); +} + +impl Future for TimeoutFuture +where + F: Future>, +{ + type Output = F::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.as_mut().future().poll(cx) { + Poll::Ready(v) => Poll::Ready(v), + Poll::Pending => match self.delay().poll(cx) { + Poll::Ready(_) => Poll::Ready(Err(io::Error::new( + io::ErrorKind::TimedOut, + "future has timed out", + ))), + Poll::Pending => Poll::Pending, + }, + } + } +} From 79bfd92154cd89feb640d6336ea70c3d80a9073f Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Thu, 15 Aug 2019 02:55:37 +0200 Subject: [PATCH 2/3] Update src/io/timeout.rs Co-Authored-By: Florian Gilcher --- src/io/timeout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io/timeout.rs b/src/io/timeout.rs index 5902989e..a989b2df 100644 --- a/src/io/timeout.rs +++ b/src/io/timeout.rs @@ -61,7 +61,7 @@ where Poll::Pending => match self.delay().poll(cx) { Poll::Ready(_) => Poll::Ready(Err(io::Error::new( io::ErrorKind::TimedOut, - "future has timed out", + "IO operation has timed out", ))), Poll::Pending => Poll::Pending, }, From e3fc67c1cbfd56244d6bc9e0649e218c7741510b Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 15 Aug 2019 17:59:48 +0200 Subject: [PATCH 3/3] Address comments --- examples/stdin-timeout.rs | 19 +++++-------------- src/io/timeout.rs | 13 +++++++------ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/examples/stdin-timeout.rs b/examples/stdin-timeout.rs index dde49e5b..04b860a2 100644 --- a/examples/stdin-timeout.rs +++ b/examples/stdin-timeout.rs @@ -9,22 +9,13 @@ use async_std::prelude::*; use async_std::task; fn main() -> io::Result<()> { - task::block_on(async { + task::block_on(io::timeout(Duration::from_secs(5), async { let stdin = io::stdin(); - let mut line = String::new(); - match stdin - .read_line(&mut line) - .timeout(Duration::from_secs(5)) - .await - { - Ok(res) => { - res?; - print!("Got line: {}", line); - } - Err(_) => println!("You have only 5 seconds to enter a line. Try again :)"), - } + let mut line = String::new(); + stdin.read_line(&mut line).await?; + print!("Got line: {}", line); Ok(()) - }) + })) } diff --git a/src/io/timeout.rs b/src/io/timeout.rs index 5902989e..b35a8030 100644 --- a/src/io/timeout.rs +++ b/src/io/timeout.rs @@ -20,11 +20,12 @@ use crate::task::{Context, Poll}; /// /// use async_std::io; /// -/// let stdin = io::stdin(); -/// let mut line = String::new(); -/// -/// let dur = Duration::from_secs(5); -/// let n = io::timeout(dur, stdin.read_line(&mut line)).await?; +/// io::timeout(Duration::from_secs(5), async { +/// let stdin = io::stdin(); +/// let mut line = String::new(); +/// let n = stdin.read_line(&mut line).await?; +/// }) +/// .await?; /// # /// # Ok(()) }) } /// ``` @@ -61,7 +62,7 @@ where Poll::Pending => match self.delay().poll(cx) { Poll::Ready(_) => Poll::Ready(Err(io::Error::new( io::ErrorKind::TimedOut, - "future has timed out", + "I/O operation has timed out", ))), Poll::Pending => Poll::Pending, },