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; /// /// 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(()) }) } /// ``` 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, "I/O operation has timed out", ))), Poll::Pending => Poll::Pending, }, } } }