From 01aac213866d1edcfa33cd5bc33a34c6e4b08eac Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Mon, 12 Aug 2019 20:28:50 +0200 Subject: [PATCH] Modularize time module --- src/time/mod.rs | 106 +------------------------------------------- src/time/timeout.rs | 105 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 104 deletions(-) create mode 100644 src/time/timeout.rs diff --git a/src/time/mod.rs b/src/time/mod.rs index b19e7ea..78a554a 100644 --- a/src/time/mod.rs +++ b/src/time/mod.rs @@ -26,108 +26,6 @@ //! # Ok(()) }) } //! ``` -use std::error::Error; -use std::fmt; -use std::pin::Pin; -use std::time::Duration; +pub use timeout::{Timeout, TimeoutError}; -use cfg_if::cfg_if; -use futures_timer::Delay; -use pin_utils::unsafe_pinned; - -use crate::future::Future; -use crate::io; -use crate::task::{Context, Poll}; - -cfg_if! { - if #[cfg(feature = "docs")] { - #[doc(hidden)] - pub struct ImplFuture(std::marker::PhantomData); - - macro_rules! ret { - ($f:tt, $o:ty) => (ImplFuture<$o>); - } - } else { - macro_rules! ret { - ($f:tt, $o:ty) => ($f); - } - } -} - -/// An error returned when a future times out. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct TimeoutError; - -impl Error for TimeoutError {} - -impl fmt::Display for TimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "future has timed out".fmt(f) - } -} - -impl From for io::Error { - fn from(_: TimeoutError) -> io::Error { - io::Error::new(io::ErrorKind::TimedOut, "future has timed out") - } -} - -/// An extension trait that configures timeouts for futures. -pub trait Timeout: Future + Sized { - /// Awaits a future to completion 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 async_std::{io, prelude::*}; - /// use std::time::Duration; - /// - /// let stdin = io::stdin(); - /// let mut line = String::new(); - /// - /// let n = stdin - /// .read_line(&mut line) - /// .timeout(Duration::from_secs(5)) - /// .await??; - /// # - /// # Ok(()) }) } - /// ``` - fn timeout(self, dur: Duration) -> ret!(TimeoutFuture, Result) { - TimeoutFuture { - future: self, - delay: Delay::new(dur), - } - } -} - -/// A future that times out after a duration of time. -#[doc(hidden)] -#[allow(missing_debug_implementations)] -pub struct TimeoutFuture { - future: F, - delay: Delay, -} - -impl TimeoutFuture { - unsafe_pinned!(future: F); - unsafe_pinned!(delay: Delay); -} - -impl Future for TimeoutFuture { - type Output = Result; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - match self.as_mut().future().poll(cx) { - Poll::Ready(v) => Poll::Ready(Ok(v)), - Poll::Pending => match self.delay().poll(cx) { - Poll::Ready(_) => Poll::Ready(Err(TimeoutError)), - Poll::Pending => Poll::Pending, - }, - } - } -} - -impl Timeout for F {} +mod timeout; diff --git a/src/time/timeout.rs b/src/time/timeout.rs new file mode 100644 index 0000000..ef60f0f --- /dev/null +++ b/src/time/timeout.rs @@ -0,0 +1,105 @@ +use std::error::Error; +use std::fmt; +use std::pin::Pin; +use std::time::Duration; + +use cfg_if::cfg_if; +use futures_timer::Delay; +use pin_utils::unsafe_pinned; + +use crate::future::Future; +use crate::io; +use crate::task::{Context, Poll}; + +cfg_if! { + if #[cfg(feature = "docs")] { + #[doc(hidden)] + pub struct ImplFuture(std::marker::PhantomData); + + macro_rules! ret { + ($f:tt, $o:ty) => (ImplFuture<$o>); + } + } else { + macro_rules! ret { + ($f:tt, $o:ty) => ($f); + } + } +} + +/// An error returned when a future times out. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct TimeoutError; + +impl Error for TimeoutError {} + +impl fmt::Display for TimeoutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "future has timed out".fmt(f) + } +} + +impl From for io::Error { + fn from(_: TimeoutError) -> io::Error { + io::Error::new(io::ErrorKind::TimedOut, "future has timed out") + } +} + +/// An extension trait that configures timeouts for futures. +pub trait Timeout: Future + Sized { + /// Awaits a future to completion 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 async_std::{io, prelude::*}; + /// use std::time::Duration; + /// + /// let stdin = io::stdin(); + /// let mut line = String::new(); + /// + /// let n = stdin + /// .read_line(&mut line) + /// .timeout(Duration::from_secs(5)) + /// .await??; + /// # + /// # Ok(()) }) } + /// ``` + fn timeout(self, dur: Duration) -> ret!(TimeoutFuture, Result) { + TimeoutFuture { + future: self, + delay: Delay::new(dur), + } + } +} + +/// A future that times out after a duration of time. +#[doc(hidden)] +#[allow(missing_debug_implementations)] +pub struct TimeoutFuture { + future: F, + delay: Delay, +} + +impl TimeoutFuture { + unsafe_pinned!(future: F); + unsafe_pinned!(delay: Delay); +} + +impl Future for TimeoutFuture { + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.as_mut().future().poll(cx) { + Poll::Ready(v) => Poll::Ready(Ok(v)), + Poll::Pending => match self.delay().poll(cx) { + Poll::Ready(_) => Poll::Ready(Err(TimeoutError)), + Poll::Pending => Poll::Pending, + }, + } + } +} + +impl Timeout for F {}