Skip to content

Commit

Permalink
Change ArcWake::into_waker to a free function
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Jun 15, 2019
1 parent 8cf0785 commit 572afe7
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 71 deletions.
6 changes: 3 additions & 3 deletions 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.
///
Expand Down Expand Up @@ -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 })
}
14 changes: 7 additions & 7 deletions futures-util/src/compat/compat03as01.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -168,7 +168,7 @@ impl Current {
// FIXME: remove `transmute` when a `Waker` -> `RawWaker` conversion
// function is landed in `core`.
mem::transmute::<task03::Waker, RawWaker>(
Arc::new(ptr_to_current(ptr).clone()).into_waker()
task03::waker(Arc::new(ptr_to_current(ptr).clone()))
)
}
unsafe fn drop(_: *const ()) {}
Expand Down
50 changes: 0 additions & 50 deletions 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.
Expand Down Expand Up @@ -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<Self>);

/// Creates a `Waker` from an Arc<T>, 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<Self>) -> 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<T: ArcWake>(data: *const ()) {
// Retain Arc by creating a copy
let arc: Arc<T> = 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<T: ArcWake>(data: *const ()) -> RawWaker {
increase_refcount::<T>(data);
RawWaker::new(data, waker_vtable!(T))
}

unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
drop(Arc::<T>::from_raw(data as *const T))
}

// used by `waker_ref`
pub(super) unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
let arc: Arc<T> = Arc::from_raw(data as *const T);
ArcWake::wake(arc);
}

// used by `waker_ref`
pub(super) unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
let arc: Arc<T> = Arc::from_raw(data as *const T);
ArcWake::wake_by_ref(&arc);
mem::forget(arc);
}
5 changes: 5 additions & 0 deletions futures-util/src/task/mod.rs
Expand Up @@ -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")]
Expand Down
53 changes: 53 additions & 0 deletions 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<impl ArcWake>`.
///
/// The returned [`Waker`] will call
/// [`ArcWake.wake()`](ArcWake::wake) if awoken.
pub fn waker<W>(wake: Arc<W>) -> 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<T: ArcWake>(data: *const ()) {
// Retain Arc by creating a copy
let arc: Arc<T> = 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<T: ArcWake>(data: *const ()) -> RawWaker {
increase_refcount::<T>(data);
RawWaker::new(data, waker_vtable!(T))
}

unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
let arc: Arc<T> = Arc::from_raw(data as *const T);
ArcWake::wake(arc);
}

// used by `waker_ref`
pub(super) unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
let arc: Arc<T> = Arc::from_raw(data as *const T);
ArcWake::wake_by_ref(&arc);
mem::forget(arc);
}

unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
drop(Arc::<T>::from_raw(data as *const T))
}
13 changes: 5 additions & 8 deletions 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<Target = Waker>`](::std::ops::Deref),
/// so it can be used to get a `&Waker`.
Expand Down Expand Up @@ -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<impl ArcWake>`.
///
/// The resulting [`Waker`](::std::task::Waker) will call
/// The resulting [`Waker`] will call
/// [`ArcWake.wake()`](ArcWake::wake) if awoken.
#[inline]
pub fn waker_ref<W>(wake: &Arc<W>) -> WakerRef<'_>
Expand Down
2 changes: 1 addition & 1 deletion futures/src/lib.rs
Expand Up @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions 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 {
Expand Down Expand Up @@ -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());
Expand Down

0 comments on commit 572afe7

Please sign in to comment.