Skip to content

Commit df25d79

Browse files
committed
Auto merge of rust-lang#59733 - cramertj:wake-by-ref, r=withoutboats
Final (one can only hope) futures_api adjustments Based on rust-lang#59119 -- this change is only the latter two commits. cc rust-lang#59725 r? @withoutboats
2 parents 9a612b2 + 6786fa7 commit df25d79

File tree

4 files changed

+78
-24
lines changed

4 files changed

+78
-24
lines changed

src/libcore/task/wake.rs

+49-11
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,18 @@ pub struct RawWakerVTable {
7272
/// This function will be called when `wake` is called on the [`Waker`].
7373
/// It must wake up the task associated with this [`RawWaker`].
7474
///
75-
/// The implemention of this function must not consume the provided data
76-
/// pointer.
75+
/// The implementation of this function must make sure to release any
76+
/// resources that are associated with this instance of a [`RawWaker`] and
77+
/// associated task.
7778
wake: unsafe fn(*const ()),
7879

80+
/// This function will be called when `wake_by_ref` is called on the [`Waker`].
81+
/// It must wake up the task associated with this [`RawWaker`].
82+
///
83+
/// This function is similar to `wake`, but must not consume the provided data
84+
/// pointer.
85+
wake_by_ref: unsafe fn(*const ()),
86+
7987
/// This function gets called when a [`RawWaker`] gets dropped.
8088
///
8189
/// The implementation of this function must make sure to release any
@@ -85,8 +93,8 @@ pub struct RawWakerVTable {
8593
}
8694

8795
impl RawWakerVTable {
88-
/// Creates a new `RawWakerVTable` from the provided `clone`, `wake`, and
89-
/// `drop` functions.
96+
/// Creates a new `RawWakerVTable` from the provided `clone`, `wake`,
97+
/// `wake_by_ref`, and `drop` functions.
9098
///
9199
/// # `clone`
92100
///
@@ -103,7 +111,16 @@ impl RawWakerVTable {
103111
/// This function will be called when `wake` is called on the [`Waker`].
104112
/// It must wake up the task associated with this [`RawWaker`].
105113
///
106-
/// The implemention of this function must not consume the provided data
114+
/// The implementation of this function must make sure to release any
115+
/// resources that are associated with this instance of a [`RawWaker`] and
116+
/// associated task.
117+
///
118+
/// # `wake_by_ref`
119+
///
120+
/// This function will be called when `wake_by_ref` is called on the [`Waker`].
121+
/// It must wake up the task associated with this [`RawWaker`].
122+
///
123+
/// This function is similar to `wake`, but must not consume the provided data
107124
/// pointer.
108125
///
109126
/// # `drop`
@@ -120,11 +137,13 @@ impl RawWakerVTable {
120137
pub const fn new(
121138
clone: unsafe fn(*const ()) -> RawWaker,
122139
wake: unsafe fn(*const ()),
140+
wake_by_ref: unsafe fn(*const ()),
123141
drop: unsafe fn(*const ()),
124142
) -> Self {
125143
Self {
126144
clone,
127145
wake,
146+
wake_by_ref,
128147
drop,
129148
}
130149
}
@@ -187,14 +206,33 @@ unsafe impl Sync for Waker {}
187206
impl Waker {
188207
/// Wake up the task associated with this `Waker`.
189208
#[inline]
190-
pub fn wake(&self) {
209+
pub fn wake(self) {
191210
// The actual wakeup call is delegated through a virtual function call
192211
// to the implementation which is defined by the executor.
212+
let wake = self.waker.vtable.wake;
213+
let data = self.waker.data;
193214

194-
// SAFETY: This is safe because `Waker::new_unchecked` is the only way
215+
// Don't call `drop` -- the waker will be consumed by `wake`.
216+
crate::mem::forget(self);
217+
218+
// SAFETY: This is safe because `Waker::from_raw` is the only way
195219
// to initialize `wake` and `data` requiring the user to acknowledge
196220
// that the contract of `RawWaker` is upheld.
197-
unsafe { (self.waker.vtable.wake)(self.waker.data) }
221+
unsafe { (wake)(data) };
222+
}
223+
224+
/// Wake up the task associated with this `Waker` without consuming the `Waker`.
225+
///
226+
/// This is similar to `wake`, but may be slightly less efficient in the case
227+
/// where an owned `Waker` is available. This method should be preferred to
228+
/// calling `waker.clone().wake()`.
229+
#[inline]
230+
pub fn wake_by_ref(&self) {
231+
// The actual wakeup call is delegated through a virtual function call
232+
// to the implementation which is defined by the executor.
233+
234+
// SAFETY: see `wake`
235+
unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) }
198236
}
199237

200238
/// Returns `true` if this `Waker` and another `Waker` have awoken the same task.
@@ -215,7 +253,7 @@ impl Waker {
215253
/// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld.
216254
/// Therefore this method is unsafe.
217255
#[inline]
218-
pub unsafe fn new_unchecked(waker: RawWaker) -> Waker {
256+
pub unsafe fn from_raw(waker: RawWaker) -> Waker {
219257
Waker {
220258
waker,
221259
}
@@ -226,7 +264,7 @@ impl Clone for Waker {
226264
#[inline]
227265
fn clone(&self) -> Self {
228266
Waker {
229-
// SAFETY: This is safe because `Waker::new_unchecked` is the only way
267+
// SAFETY: This is safe because `Waker::from_raw` is the only way
230268
// to initialize `clone` and `data` requiring the user to acknowledge
231269
// that the contract of [`RawWaker`] is upheld.
232270
waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
@@ -237,7 +275,7 @@ impl Clone for Waker {
237275
impl Drop for Waker {
238276
#[inline]
239277
fn drop(&mut self) {
240-
// SAFETY: This is safe because `Waker::new_unchecked` is the only way
278+
// SAFETY: This is safe because `Waker::from_raw` is the only way
241279
// to initialize `drop` and `data` requiring the user to acknowledge
242280
// that the contract of `RawWaker` is upheld.
243281
unsafe { (self.waker.vtable.drop)(self.waker.data) }

src/test/run-pass/async-await.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ struct Counter {
1919
}
2020

2121
impl ArcWake for Counter {
22-
fn wake(arc_self: &Arc<Self>) {
22+
fn wake(self: Arc<Self>) {
23+
Self::wake_by_ref(&self)
24+
}
25+
fn wake_by_ref(arc_self: &Arc<Self>) {
2326
arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
2427
}
2528
}
@@ -34,7 +37,7 @@ impl Future for WakeOnceThenComplete {
3437
if self.0 {
3538
Poll::Ready(())
3639
} else {
37-
cx.waker().wake();
40+
cx.waker().wake_by_ref();
3841
self.0 = true;
3942
Poll::Pending
4043
}

src/test/run-pass/auxiliary/arc_wake.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,30 @@ macro_rules! waker_vtable {
1212
&RawWakerVTable::new(
1313
clone_arc_raw::<$ty>,
1414
wake_arc_raw::<$ty>,
15+
wake_by_ref_arc_raw::<$ty>,
1516
drop_arc_raw::<$ty>,
1617
)
1718
};
1819
}
1920

2021
pub trait ArcWake {
21-
fn wake(arc_self: &Arc<Self>);
22+
fn wake(self: Arc<Self>);
23+
24+
fn wake_by_ref(arc_self: &Arc<Self>) {
25+
arc_self.clone().wake()
26+
}
2227

2328
fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
2429
{
25-
let ptr = Arc::into_raw(wake) as *const();
30+
let ptr = Arc::into_raw(wake) as *const ();
2631

2732
unsafe {
28-
Waker::new_unchecked(RawWaker::new(ptr, waker_vtable!(Self)))
33+
Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
2934
}
3035
}
3136
}
3237

33-
unsafe fn increase_refcount<T: ArcWake>(data: *const()) {
38+
unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
3439
// Retain Arc by creating a copy
3540
let arc: Arc<T> = Arc::from_raw(data as *const T);
3641
let arc_clone = arc.clone();
@@ -39,18 +44,23 @@ unsafe fn increase_refcount<T: ArcWake>(data: *const()) {
3944
let _ = Arc::into_raw(arc_clone);
4045
}
4146

42-
unsafe fn clone_arc_raw<T: ArcWake>(data: *const()) -> RawWaker {
47+
unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
4348
increase_refcount::<T>(data);
4449
RawWaker::new(data, waker_vtable!(T))
4550
}
4651

47-
unsafe fn drop_arc_raw<T: ArcWake>(data: *const()) {
52+
unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
4853
// Drop Arc
4954
let _: Arc<T> = Arc::from_raw(data as *const T);
5055
}
5156

52-
unsafe fn wake_arc_raw<T: ArcWake>(data: *const()) {
57+
unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
58+
let arc: Arc<T> = Arc::from_raw(data as *const T);
59+
ArcWake::wake(arc);
60+
}
61+
62+
unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
5363
let arc: Arc<T> = Arc::from_raw(data as *const T);
54-
ArcWake::wake(&arc);
64+
ArcWake::wake_by_ref(&arc);
5565
let _ = Arc::into_raw(arc);
5666
}

src/test/run-pass/futures-api.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ struct Counter {
2020
}
2121

2222
impl ArcWake for Counter {
23-
fn wake(arc_self: &Arc<Self>) {
23+
fn wake(self: Arc<Self>) {
24+
Self::wake_by_ref(&self)
25+
}
26+
fn wake_by_ref(arc_self: &Arc<Self>) {
2427
arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
2528
}
2629
}
@@ -32,8 +35,8 @@ impl Future for MyFuture {
3235
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
3336
// Wake twice
3437
let waker = cx.waker();
35-
waker.wake();
36-
waker.wake();
38+
waker.wake_by_ref();
39+
waker.wake_by_ref();
3740
Poll::Ready(())
3841
}
3942
}

0 commit comments

Comments
 (0)