From 572afe708b32d9c92a9a262053a2af17728f2f43 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 15 Jun 2019 16:18:20 +0900 Subject: [PATCH] Change ArcWake::into_waker to a free function --- futures-test/src/task/wake_counter.rs | 6 +-- futures-util/src/compat/compat03as01.rs | 14 +++---- futures-util/src/task/arc_wake.rs | 50 ----------------------- futures-util/src/task/mod.rs | 5 +++ futures-util/src/task/waker.rs | 53 +++++++++++++++++++++++++ futures-util/src/task/waker_ref.rs | 13 +++--- futures/src/lib.rs | 2 +- futures/tests/arc_wake.rs | 4 +- 8 files changed, 76 insertions(+), 71 deletions(-) create mode 100644 futures-util/src/task/waker.rs diff --git a/futures-test/src/task/wake_counter.rs b/futures-test/src/task/wake_counter.rs index 9fb2dbdbf8..cf496c2ddb 100644 --- a/futures-test/src/task/wake_counter.rs +++ b/futures-test/src/task/wake_counter.rs @@ -1,7 +1,7 @@ -use futures_core::task::{Waker}; +use futures_core::task::Waker; +use futures_util::task::{self, ArcWake}; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; -use futures_util::task::ArcWake; /// Number of times the waker was awoken. /// @@ -55,5 +55,5 @@ impl ArcWake for WakerInner { /// ``` pub fn new_count_waker() -> (Waker, AwokenCount) { let inner = Arc::new(WakerInner { count: AtomicUsize::new(0) }); - (ArcWake::into_waker(inner.clone()), AwokenCount { inner }) + (task::waker(inner.clone()), AwokenCount { inner }) } diff --git a/futures-util/src/compat/compat03as01.rs b/futures-util/src/compat/compat03as01.rs index cdc3cf9fd6..930c7129c0 100644 --- a/futures-util/src/compat/compat03as01.rs +++ b/futures-util/src/compat/compat03as01.rs @@ -4,16 +4,16 @@ use futures_01::{ StartSend as StartSend01, Stream as Stream01, }; use futures_core::{ - task::{ - self as task03, - RawWaker, - RawWakerVTable, - }, + task::{RawWaker, RawWakerVTable}, TryFuture as TryFuture03, TryStream as TryStream03, }; use futures_sink::Sink as Sink03; -use crate::task::{ArcWake as ArcWake03, WakerRef}; +use crate::task::{ + self as task03, + ArcWake as ArcWake03, + WakerRef, +}; use std::{ marker::PhantomData, mem, @@ -168,7 +168,7 @@ impl Current { // FIXME: remove `transmute` when a `Waker` -> `RawWaker` conversion // function is landed in `core`. mem::transmute::( - Arc::new(ptr_to_current(ptr).clone()).into_waker() + task03::waker(Arc::new(ptr_to_current(ptr).clone())) ) } unsafe fn drop(_: *const ()) {} diff --git a/futures-util/src/task/arc_wake.rs b/futures-util/src/task/arc_wake.rs index c95b19019f..8c09037e0b 100644 --- a/futures-util/src/task/arc_wake.rs +++ b/futures-util/src/task/arc_wake.rs @@ -1,5 +1,3 @@ -use core::mem; -use core::task::{Waker, RawWaker, RawWakerVTable}; use alloc::sync::Arc; /// A way of waking up a specific task. @@ -35,52 +33,4 @@ pub trait ArcWake: Send + Sync { /// This function is similar to `wake`, but must not consume the provided data /// pointer. fn wake_by_ref(arc_self: &Arc); - - /// Creates a `Waker` from an Arc, if T implements `ArcWake`. - /// - /// If `wake()` is called on the returned `Waker`, - /// the `wake()` function that is defined inside this trait will get called. - fn into_waker(self: Arc) -> Waker where Self: Sized - { - let ptr = Arc::into_raw(self) as *const (); - - unsafe { - Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self))) - } - } -} - -// FIXME: panics on Arc::clone / refcount changes could wreak havoc on the -// code here. We should guard against this by aborting. - -unsafe fn increase_refcount(data: *const ()) { - // Retain Arc by creating a copy - let arc: Arc = Arc::from_raw(data as *const T); - let arc_clone = arc.clone(); - // Forget the Arcs again, so that the refcount isn't decrased - mem::forget(arc); - mem::forget(arc_clone); -} - -// used by `waker_ref` -pub(super) unsafe fn clone_arc_raw(data: *const ()) -> RawWaker { - increase_refcount::(data); - RawWaker::new(data, waker_vtable!(T)) -} - -unsafe fn drop_arc_raw(data: *const ()) { - drop(Arc::::from_raw(data as *const T)) -} - -// used by `waker_ref` -pub(super) unsafe fn wake_arc_raw(data: *const ()) { - let arc: Arc = Arc::from_raw(data as *const T); - ArcWake::wake(arc); -} - -// used by `waker_ref` -pub(super) unsafe fn wake_by_ref_arc_raw(data: *const ()) { - let arc: Arc = Arc::from_raw(data as *const T); - ArcWake::wake_by_ref(&arc); - mem::forget(arc); } diff --git a/futures-util/src/task/mod.rs b/futures-util/src/task/mod.rs index f8069386d0..3a24265a70 100644 --- a/futures-util/src/task/mod.rs +++ b/futures-util/src/task/mod.rs @@ -20,6 +20,11 @@ cfg_target_has_atomic! { #[cfg(feature = "alloc")] pub use self::arc_wake::ArcWake; + #[cfg(feature = "alloc")] + mod waker; + #[cfg(feature = "alloc")] + pub use self::waker::waker; + #[cfg(feature = "alloc")] mod waker_ref; #[cfg(feature = "alloc")] diff --git a/futures-util/src/task/waker.rs b/futures-util/src/task/waker.rs new file mode 100644 index 0000000000..5fb2f9210a --- /dev/null +++ b/futures-util/src/task/waker.rs @@ -0,0 +1,53 @@ +use super::arc_wake::ArcWake; +use core::mem; +use core::task::{Waker, RawWaker, RawWakerVTable}; +use alloc::sync::Arc; + +/// Creates a [`Waker`] from an `Arc`. +/// +/// The returned [`Waker`] will call +/// [`ArcWake.wake()`](ArcWake::wake) if awoken. +pub fn waker(wake: Arc) -> Waker +where + W: ArcWake, +{ + let ptr = Arc::into_raw(wake) as *const (); + + unsafe { + Waker::from_raw(RawWaker::new(ptr, waker_vtable!(W))) + } +} + +// FIXME: panics on Arc::clone / refcount changes could wreak havoc on the +// code here. We should guard against this by aborting. + +unsafe fn increase_refcount(data: *const ()) { + // Retain Arc by creating a copy + let arc: Arc = Arc::from_raw(data as *const T); + let arc_clone = arc.clone(); + // Forget the Arcs again, so that the refcount isn't decrased + mem::forget(arc); + mem::forget(arc_clone); +} + +// used by `waker_ref` +pub(super) unsafe fn clone_arc_raw(data: *const ()) -> RawWaker { + increase_refcount::(data); + RawWaker::new(data, waker_vtable!(T)) +} + +unsafe fn wake_arc_raw(data: *const ()) { + let arc: Arc = Arc::from_raw(data as *const T); + ArcWake::wake(arc); +} + +// used by `waker_ref` +pub(super) unsafe fn wake_by_ref_arc_raw(data: *const ()) { + let arc: Arc = Arc::from_raw(data as *const T); + ArcWake::wake_by_ref(&arc); + mem::forget(arc); +} + +unsafe fn drop_arc_raw(data: *const ()) { + drop(Arc::::from_raw(data as *const T)) +} diff --git a/futures-util/src/task/waker_ref.rs b/futures-util/src/task/waker_ref.rs index f7ad0b6dbd..f9ff559e0f 100644 --- a/futures-util/src/task/waker_ref.rs +++ b/futures-util/src/task/waker_ref.rs @@ -1,15 +1,13 @@ #![allow(clippy::cast_ptr_alignment)] // clippy is too strict here -use super::arc_wake::{ArcWake, clone_arc_raw, wake_by_ref_arc_raw}; +use super::arc_wake::ArcWake; +use super::waker::{clone_arc_raw, wake_by_ref_arc_raw}; use alloc::sync::Arc; use core::marker::PhantomData; use core::ops::Deref; use core::task::{Waker, RawWaker, RawWakerVTable}; -// TODO: The link to Waker below points to futures::task::Waker and not to std. Is that a -// bug in rustdoc? -// -/// A [`Waker`](::std::task::Waker) that is only valid for a given lifetime. +/// A [`Waker`] that is only valid for a given lifetime. /// /// Note: this type implements [`Deref`](::std::ops::Deref), /// so it can be used to get a `&Waker`. @@ -56,10 +54,9 @@ unsafe fn wake_unreachable(_data: *const ()) { unreachable!("WakerRef::wake"); } -/// Creates a reference to a [`Waker`](::std::task::Waker) -/// from a local [`ArcWake`]. +/// Creates a reference to a [`Waker`] from a reference to `Arc`. /// -/// The resulting [`Waker`](::std::task::Waker) will call +/// The resulting [`Waker`] will call /// [`ArcWake.wake()`](ArcWake::wake) if awoken. #[inline] pub fn waker_ref(wake: &Arc) -> WakerRef<'_> diff --git a/futures/src/lib.rs b/futures/src/lib.rs index e691304f46..08445e3e1a 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -491,7 +491,7 @@ pub mod task { cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) )] #[cfg(feature = "alloc")] - pub use futures_util::task::{WakerRef, waker_ref, ArcWake}; + pub use futures_util::task::{waker, waker_ref, WakerRef, ArcWake}; #[cfg_attr( feature = "cfg-target-has-atomic", diff --git a/futures/tests/arc_wake.rs b/futures/tests/arc_wake.rs index 5fc27adcad..ff07ab9469 100644 --- a/futures/tests/arc_wake.rs +++ b/futures/tests/arc_wake.rs @@ -1,4 +1,4 @@ -use futures::task::{ArcWake, Waker}; +use futures::task::{self, ArcWake, Waker}; use std::sync::{Arc, Mutex}; struct CountingWaker { @@ -28,7 +28,7 @@ impl ArcWake for CountingWaker { fn create_waker_from_arc() { let some_w = Arc::new(CountingWaker::new()); - let w1: Waker = ArcWake::into_waker(some_w.clone()); + let w1: Waker = task::waker(some_w.clone()); assert_eq!(2, Arc::strong_count(&some_w)); w1.wake_by_ref(); assert_eq!(1, some_w.wakes());