Skip to content

Commit 5002e87

Browse files
committed
Preserve same vtable pointer when cloning raw waker, to fix Waker::will_wake
1 parent 793b45f commit 5002e87

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

library/alloc/src/task.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,7 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
138138
// Increment the reference count of the arc to clone it.
139139
unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
140140
unsafe { Arc::increment_strong_count(waker as *const W) };
141-
RawWaker::new(
142-
waker as *const (),
143-
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
144-
)
141+
RawWaker::new(waker as *const (), vtable::<W>())
145142
}
146143

147144
// Wake by value, moving the Arc into the Wake::wake function
@@ -161,10 +158,15 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
161158
unsafe { Arc::decrement_strong_count(waker as *const W) };
162159
}
163160

164-
RawWaker::new(
165-
Arc::into_raw(waker) as *const (),
166-
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
167-
)
161+
fn vtable<W: Wake + Send + Sync + 'static>() -> &'static RawWakerVTable {
162+
// Perform this const promotion in a single place used by both initial
163+
// construction of the RawWaker below and by clone_waker above. This way
164+
// the vtable pointer comparison performed by Waker::will_wake sees that
165+
// a cloned waker will wake the original one and vice versa.
166+
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>)
167+
}
168+
169+
RawWaker::new(Arc::into_raw(waker) as *const (), vtable::<W>())
168170
}
169171

170172
/// An analogous trait to `Wake` but used to construct a `LocalWaker`. This API
@@ -306,10 +308,7 @@ fn local_raw_waker<W: LocalWake + 'static>(waker: Rc<W>) -> RawWaker {
306308
// Increment the reference count of the Rc to clone it.
307309
unsafe fn clone_waker<W: LocalWake + 'static>(waker: *const ()) -> RawWaker {
308310
unsafe { Rc::increment_strong_count(waker as *const W) };
309-
RawWaker::new(
310-
waker as *const (),
311-
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
312-
)
311+
RawWaker::new(waker as *const (), vtable::<W>())
313312
}
314313

315314
// Wake by value, moving the Rc into the LocalWake::wake function
@@ -329,8 +328,9 @@ fn local_raw_waker<W: LocalWake + 'static>(waker: Rc<W>) -> RawWaker {
329328
unsafe { Rc::decrement_strong_count(waker as *const W) };
330329
}
331330

332-
RawWaker::new(
333-
Rc::into_raw(waker) as *const (),
334-
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
335-
)
331+
fn vtable<W: LocalWake + 'static>() -> &'static RawWakerVTable {
332+
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>)
333+
}
334+
335+
RawWaker::new(Rc::into_raw(waker) as *const (), vtable::<W>())
336336
}

0 commit comments

Comments
 (0)