11#![ unstable( feature = "wake_trait" , issue = "0" ) ]
22//! Types and Traits for working with asynchronous tasks.
3- use core:: mem;
4- use core:: task:: { Waker , RawWaker , RawWakerVTable } ;
3+ use core:: mem:: { self , ManuallyDrop } ;
4+ use core:: task:: { RawWaker , RawWakerVTable , Waker } ;
55
66use crate :: sync:: Arc ;
77
88/// The implementation of waking a task on an executor.
9- ///
9+ ///
1010/// This trait can be used to create a [`Waker`]. An executor can define an
1111/// implementation of this trait, and use that to construct a Waker to pass
1212/// to the tasks that are executed on that executor.
1313///
1414/// This trait is a memory-safe and ergonomic alternative to constructing a
1515/// [`RawWaker`]. It supports the common executor design in which the data
1616/// used to wake up a task is stored in an [`Arc`]. Some executors (especially
17- /// those for embedded systems) cannot use this API, which is way [`RawWaker`]
17+ /// those for embedded systems) cannot use this API, which is why [`RawWaker`]
1818/// exists as an alternative for those systems.
1919#[ unstable( feature = "wake_trait" , issue = "0" ) ]
2020pub trait Wake {
@@ -36,9 +36,9 @@ pub trait Wake {
3636#[ unstable( feature = "wake_trait" , issue = "0" ) ]
3737impl < W : Wake + Send + Sync + ' static > From < Arc < W > > for Waker {
3838 fn from ( waker : Arc < W > ) -> Waker {
39- unsafe {
40- Waker :: from_raw ( raw_waker ( waker ) )
41- }
39+ // SAFETY: This is safe because raw_waker safely constructs
40+ // a RawWaker from Arc<W>.
41+ unsafe { Waker :: from_raw ( raw_waker ( waker ) ) }
4242 }
4343}
4444
@@ -56,7 +56,6 @@ impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
5656// explicitly.
5757#[ inline( always) ]
5858fn raw_waker < W : Wake + Send + Sync + ' static > ( waker : Arc < W > ) -> RawWaker {
59-
6059 // Increment the reference count of the arc to clone it.
6160 unsafe fn clone_waker < W : Wake + Send + Sync + ' static > ( waker : * const ( ) ) -> RawWaker {
6261 let waker: Arc < W > = Arc :: from_raw ( waker as * const W ) ;
@@ -70,22 +69,19 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
7069 Wake :: wake ( waker) ;
7170 }
7271
73- // Wake by reference, forgetting the Arc to avoid decrementing the reference count
72+ // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it
7473 unsafe fn wake_by_ref < W : Wake + Send + Sync + ' static > ( waker : * const ( ) ) {
75- let waker: Arc < W > = Arc :: from_raw ( waker as * const W ) ;
74+ let waker: ManuallyDrop < Arc < W > > = ManuallyDrop :: new ( Arc :: from_raw ( waker as * const W ) ) ;
7675 Wake :: wake_by_ref ( & waker) ;
77- mem:: forget ( waker) ;
7876 }
7977
8078 // Decrement the reference count of the Arc on drop
8179 unsafe fn drop_waker < W : Wake + Send + Sync + ' static > ( waker : * const ( ) ) {
8280 mem:: drop ( Arc :: from_raw ( waker as * const W ) ) ;
8381 }
8482
85- RawWaker :: new ( Arc :: into_raw ( waker) as * const ( ) , & RawWakerVTable :: new (
86- clone_waker :: < W > ,
87- wake :: < W > ,
88- wake_by_ref :: < W > ,
89- drop_waker :: < W > ,
83+ RawWaker :: new (
84+ Arc :: into_raw ( waker) as * const ( ) ,
85+ & RawWakerVTable :: new ( clone_waker :: < W > , wake :: < W > , wake_by_ref :: < W > , drop_waker :: < W > ) ,
9086 ) )
9187}
0 commit comments