From 72605a65e7022752141111e387228eabdffe9631 Mon Sep 17 00:00:00 2001 From: matt961 Date: Wed, 23 Oct 2019 17:47:30 -0700 Subject: [PATCH] adds Future#delay --- src/future/delay.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ src/future/future.rs | 9 +++++++++ src/future/mod.rs | 1 + src/prelude.rs | 2 ++ tests/delay.rs | 19 +++++++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 src/future/delay.rs create mode 100644 tests/delay.rs diff --git a/src/future/delay.rs b/src/future/delay.rs new file mode 100644 index 000000000..e96c09b73 --- /dev/null +++ b/src/future/delay.rs @@ -0,0 +1,43 @@ +use crate::future::Future; +use std::pin::Pin; +use std::time::Duration; + +use crate::task::{Context, Poll}; + +#[doc(hidden)] +#[allow(missing_debug_implementations)] +pub struct Delay { + fut: F, + delay: futures_timer::Delay, + delay_done: bool, +} + +impl Delay { + pin_utils::unsafe_pinned!(fut: F); + pin_utils::unsafe_pinned!(delay: futures_timer::Delay); + pin_utils::unsafe_unpinned!(delay_done: bool); + + pub(super) fn new(fut: F, dur: Duration) -> Self { + Delay { + fut, + delay: futures_timer::Delay::new(dur), + delay_done: false, + } + } +} + +impl Future for Delay +where + F: Future +{ + type Output = F::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if !self.delay_done { + futures_core::ready!(self.as_mut().delay().poll(cx)); + *self.as_mut().delay_done() = true; + } + + self.as_mut().fut().poll(cx) + } +} diff --git a/src/future/future.rs b/src/future/future.rs index 8c9c12a23..a42959c47 100644 --- a/src/future/future.rs +++ b/src/future/future.rs @@ -1,3 +1,5 @@ +use crate::future::delay::Delay; + extension_trait! { use std::pin::Pin; use std::ops::{Deref, DerefMut}; @@ -99,6 +101,13 @@ extension_trait! { } pub trait FutureExt: std::future::Future { + #[doc = r#" + "#] + fn delay(self, dur: std::time::Duration) -> Delay + where Self: Sized + { + Delay::new(self, dur) + } } impl Future for Box { diff --git a/src/future/mod.rs b/src/future/mod.rs index a45bf96cd..8392968bd 100644 --- a/src/future/mod.rs +++ b/src/future/mod.rs @@ -55,6 +55,7 @@ mod pending; mod poll_fn; mod ready; mod timeout; +mod delay; cfg_unstable! { #[doc(inline)] diff --git a/src/prelude.rs b/src/prelude.rs index 91432e0bb..70ff3a0dd 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -38,6 +38,8 @@ pub use crate::io::seek::SeekExt as _; pub use crate::io::write::WriteExt as _; #[doc(hidden)] pub use crate::stream::stream::StreamExt as _; +#[doc(hidden)] +pub use crate::future::future::FutureExt as _; cfg_unstable! { #[doc(no_inline)] diff --git a/tests/delay.rs b/tests/delay.rs new file mode 100644 index 000000000..94124a9a8 --- /dev/null +++ b/tests/delay.rs @@ -0,0 +1,19 @@ +use async_std::future; +use async_std::task; +use async_std::prelude::*; + +use std::time::Duration; +use std::time::Instant; + +#[test] +fn delay() { + task::block_on( async { + let start = Instant::now(); + let a = future::ready("a"); + let b = future::ready("b"); + let c = future::ready("c").delay(Duration::from_secs(1)); + dbg!(future::join!(a, b, c).await); + let elapsed = start.elapsed().as_secs(); + assert_eq!(elapsed, 1); + }) +}