From 76100525452f2fce80a29e1215a6189b988fc735 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Sat, 7 Dec 2019 11:00:12 +0900 Subject: [PATCH 1/4] replace async-macros with internals only Signed-off-by: Yoshua Wuyts --- Cargo.toml | 2 - src/future/future/join.rs | 2 +- src/future/future/race.rs | 2 +- src/future/future/try_join.rs | 2 +- src/future/future/try_race.rs | 2 +- src/future/maybe_done.rs | 94 +++++++++++++++++++++++++++++++++++ src/future/mod.rs | 2 + src/task/mod.rs | 2 +- 8 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 src/future/maybe_done.rs diff --git a/Cargo.toml b/Cargo.toml index 7c4613b8c..569dfb369 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,6 @@ docs = ["attributes", "unstable"] unstable = ["default", "broadcaster"] attributes = ["async-attributes"] std = [ - "async-macros", "crossbeam-utils", "futures-core", "futures-io", @@ -51,7 +50,6 @@ std = [ [dependencies] async-attributes = { version = "1.1.1", optional = true } -async-macros = { version = "2.0.0", optional = true } async-task = { version = "1.0.0", optional = true } broadcaster = { version = "0.2.6", optional = true, default-features = false, features = ["default-channels"] } crossbeam-channel = { version = "0.4.0", optional = true } diff --git a/src/future/future/join.rs b/src/future/future/join.rs index 0febcad0c..4a508ce8e 100644 --- a/src/future/future/join.rs +++ b/src/future/future/join.rs @@ -1,6 +1,6 @@ use std::pin::Pin; -use async_macros::MaybeDone; +use crate::future::MaybeDone; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; diff --git a/src/future/future/race.rs b/src/future/future/race.rs index ed034f05e..82165a0f1 100644 --- a/src/future/future/race.rs +++ b/src/future/future/race.rs @@ -1,7 +1,7 @@ use std::future::Future; use std::pin::Pin; -use async_macros::MaybeDone; +use crate::future::MaybeDone; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; diff --git a/src/future/future/try_join.rs b/src/future/future/try_join.rs index f1667240f..5277ae317 100644 --- a/src/future/future/try_join.rs +++ b/src/future/future/try_join.rs @@ -1,6 +1,6 @@ use std::pin::Pin; -use async_macros::MaybeDone; +use crate::future::MaybeDone; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; diff --git a/src/future/future/try_race.rs b/src/future/future/try_race.rs index d0ca4a90f..45199570f 100644 --- a/src/future/future/try_race.rs +++ b/src/future/future/try_race.rs @@ -1,6 +1,6 @@ use std::pin::Pin; -use async_macros::MaybeDone; +use crate::future::MaybeDone; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; diff --git a/src/future/maybe_done.rs b/src/future/maybe_done.rs new file mode 100644 index 000000000..8c3827360 --- /dev/null +++ b/src/future/maybe_done.rs @@ -0,0 +1,94 @@ +//! A type that wraps a future to keep track of its completion status. +//! +//! This implementation was taken from the original `macro_rules` `join/try_join` +//! macros in the `futures-preview` crate. + +use std::future::Future; +use std::mem; +use std::pin::Pin; +use std::task::{Context, Poll}; + +use futures_core::ready; + +/// A future that may have completed. +#[derive(Debug)] +pub(crate) enum MaybeDone { + /// A not-yet-completed future + Future(Fut), + /// The output of the completed future + Done(Fut::Output), + /// The empty variant after the result of a [`MaybeDone`] has been + /// taken using the [`take`](MaybeDone::take) method. + Gone, +} + +impl MaybeDone { + /// Create a new instance of `MaybeDone`. + pub(crate) fn new(future: Fut) -> MaybeDone { + Self::Future(future) + } + + /// Returns an [`Option`] containing a reference to the output of the future. + /// The output of this method will be [`Some`] if and only if the inner + /// future has been completed and [`take`](MaybeDone::take) + /// has not yet been called. + #[inline] + pub(crate) fn output(self: Pin<&Self>) -> Option<&Fut::Output> { + let this = self.get_ref(); + match this { + MaybeDone::Done(res) => Some(res), + _ => None, + } + } + + /// Returns an [`Option`] containing a mutable reference to the output of the future. + /// The output of this method will be [`Some`] if and only if the inner + /// future has been completed and [`take`](MaybeDone::take) + /// has not yet been called. + #[inline] + pub(crate) fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Output> { + unsafe { + let this = self.get_unchecked_mut(); + match this { + MaybeDone::Done(res) => Some(res), + _ => None, + } + } + } + + /// Attempt to take the output of a `MaybeDone` without driving it + /// towards completion. + #[inline] + pub(crate) fn take(self: Pin<&mut Self>) -> Option { + unsafe { + let this = self.get_unchecked_mut(); + match this { + MaybeDone::Done(_) => {} + MaybeDone::Future(_) | MaybeDone::Gone => return None, + }; + if let MaybeDone::Done(output) = mem::replace(this, MaybeDone::Gone) { + Some(output) + } else { + unreachable!() + } + } + } + + // fn ok(self) -> Option {} +} + +impl Future for MaybeDone { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let res = unsafe { + match Pin::as_mut(&mut self).get_unchecked_mut() { + MaybeDone::Future(a) => ready!(Pin::new_unchecked(a).poll(cx)), + MaybeDone::Done(_) => return Poll::Ready(()), + MaybeDone::Gone => panic!("MaybeDone polled after value taken"), + } + }; + self.set(MaybeDone::Done(res)); + Poll::Ready(()) + } +} diff --git a/src/future/mod.rs b/src/future/mod.rs index 8b51a6a5f..a8bedfa58 100644 --- a/src/future/mod.rs +++ b/src/future/mod.rs @@ -47,11 +47,13 @@ //! [`Future::try_race`]: trait.Future.html#method.try_race pub use future::Future; +pub(crate) use maybe_done::MaybeDone; pub use pending::pending; pub use poll_fn::poll_fn; pub use ready::ready; pub(crate) mod future; +mod maybe_done; mod pending; mod poll_fn; mod ready; diff --git a/src/task/mod.rs b/src/task/mod.rs index 8e181d135..b08721a0c 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -123,7 +123,7 @@ cfg_std! { pub use std::task::{Context, Poll, Waker}; #[doc(inline)] - pub use async_macros::ready; + pub use futures_core::ready; pub use yield_now::yield_now; mod yield_now; From 250d4faeb9eff3b56ffa560765dc1ddcb40831ba Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Sat, 7 Dec 2019 11:02:44 +0900 Subject: [PATCH 2/4] clean up MaybeDone Signed-off-by: Yoshua Wuyts --- src/future/maybe_done.rs | 32 ++++++++++++++++---------------- src/future/mod.rs | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/future/maybe_done.rs b/src/future/maybe_done.rs index 8c3827360..afc1d1938 100644 --- a/src/future/maybe_done.rs +++ b/src/future/maybe_done.rs @@ -15,8 +15,10 @@ use futures_core::ready; pub(crate) enum MaybeDone { /// A not-yet-completed future Future(Fut), + /// The output of the completed future Done(Fut::Output), + /// The empty variant after the result of a [`MaybeDone`] has been /// taken using the [`take`](MaybeDone::take) method. Gone, @@ -41,20 +43,20 @@ impl MaybeDone { } } - /// Returns an [`Option`] containing a mutable reference to the output of the future. - /// The output of this method will be [`Some`] if and only if the inner - /// future has been completed and [`take`](MaybeDone::take) - /// has not yet been called. - #[inline] - pub(crate) fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Output> { - unsafe { - let this = self.get_unchecked_mut(); - match this { - MaybeDone::Done(res) => Some(res), - _ => None, - } - } - } +// /// Returns an [`Option`] containing a mutable reference to the output of the future. +// /// The output of this method will be [`Some`] if and only if the inner +// /// future has been completed and [`take`](MaybeDone::take) +// /// has not yet been called. +// #[inline] +// pub(crate) fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Output> { +// unsafe { +// let this = self.get_unchecked_mut(); +// match this { +// MaybeDone::Done(res) => Some(res), +// _ => None, +// } +// } +// } /// Attempt to take the output of a `MaybeDone` without driving it /// towards completion. @@ -73,8 +75,6 @@ impl MaybeDone { } } } - - // fn ok(self) -> Option {} } impl Future for MaybeDone { diff --git a/src/future/mod.rs b/src/future/mod.rs index a8bedfa58..993627652 100644 --- a/src/future/mod.rs +++ b/src/future/mod.rs @@ -47,13 +47,11 @@ //! [`Future::try_race`]: trait.Future.html#method.try_race pub use future::Future; -pub(crate) use maybe_done::MaybeDone; pub use pending::pending; pub use poll_fn::poll_fn; pub use ready::ready; pub(crate) mod future; -mod maybe_done; mod pending; mod poll_fn; mod ready; @@ -65,5 +63,7 @@ cfg_default! { cfg_unstable! { pub use into_future::IntoFuture; + pub(crate) use maybe_done::MaybeDone; mod into_future; + mod maybe_done; } From 58121e80b0a999febe055cc205d4dc4028af9fff Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Sat, 7 Dec 2019 11:04:54 +0900 Subject: [PATCH 3/4] inline futures_core::ready Signed-off-by: Yoshua Wuyts --- src/task/mod.rs | 5 ++--- src/task/ready.rs | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 src/task/ready.rs diff --git a/src/task/mod.rs b/src/task/mod.rs index b08721a0c..89655d9fa 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -122,10 +122,9 @@ cfg_std! { #[doc(inline)] pub use std::task::{Context, Poll, Waker}; - #[doc(inline)] - pub use futures_core::ready; - + pub use ready::ready; pub use yield_now::yield_now; + mod ready; mod yield_now; } diff --git a/src/task/ready.rs b/src/task/ready.rs new file mode 100644 index 000000000..aca04aa7b --- /dev/null +++ b/src/task/ready.rs @@ -0,0 +1,4 @@ +/// Extracts the successful type of a `Poll`. +/// +/// This macro bakes in propagation of `Pending` signals by returning early. +pub use futures_core::ready; From 4f483df8b5ae4e28d0f1a58faa909f84cb46cd4c Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Sat, 7 Dec 2019 11:11:39 +0900 Subject: [PATCH 4/4] remove big commented blob Signed-off-by: Yoshua Wuyts --- src/future/maybe_done.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/future/maybe_done.rs b/src/future/maybe_done.rs index afc1d1938..7a3a7fa33 100644 --- a/src/future/maybe_done.rs +++ b/src/future/maybe_done.rs @@ -43,21 +43,6 @@ impl MaybeDone { } } -// /// Returns an [`Option`] containing a mutable reference to the output of the future. -// /// The output of this method will be [`Some`] if and only if the inner -// /// future has been completed and [`take`](MaybeDone::take) -// /// has not yet been called. -// #[inline] -// pub(crate) fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Output> { -// unsafe { -// let this = self.get_unchecked_mut(); -// match this { -// MaybeDone::Done(res) => Some(res), -// _ => None, -// } -// } -// } - /// Attempt to take the output of a `MaybeDone` without driving it /// towards completion. #[inline]