1
1
#![ unstable( feature = "wake_trait" , issue = "0" ) ]
2
2
//! 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 } ;
5
5
6
6
use crate :: sync:: Arc ;
7
7
8
8
/// The implementation of waking a task on an executor.
9
- ///
9
+ ///
10
10
/// This trait can be used to create a [`Waker`]. An executor can define an
11
11
/// implementation of this trait, and use that to construct a Waker to pass
12
12
/// to the tasks that are executed on that executor.
13
13
///
14
14
/// This trait is a memory-safe and ergonomic alternative to constructing a
15
15
/// [`RawWaker`]. It supports the common executor design in which the data
16
16
/// 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`]
18
18
/// exists as an alternative for those systems.
19
19
#[ unstable( feature = "wake_trait" , issue = "0" ) ]
20
20
pub trait Wake {
@@ -36,9 +36,9 @@ pub trait Wake {
36
36
#[ unstable( feature = "wake_trait" , issue = "0" ) ]
37
37
impl < W : Wake + Send + Sync + ' static > From < Arc < W > > for Waker {
38
38
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 ) ) }
42
42
}
43
43
}
44
44
@@ -56,7 +56,6 @@ impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
56
56
// explicitly.
57
57
#[ inline( always) ]
58
58
fn raw_waker < W : Wake + Send + Sync + ' static > ( waker : Arc < W > ) -> RawWaker {
59
-
60
59
// Increment the reference count of the arc to clone it.
61
60
unsafe fn clone_waker < W : Wake + Send + Sync + ' static > ( waker : * const ( ) ) -> RawWaker {
62
61
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 {
70
69
Wake :: wake ( waker) ;
71
70
}
72
71
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
74
73
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 ) ) ;
76
75
Wake :: wake_by_ref ( & waker) ;
77
- mem:: forget ( waker) ;
78
76
}
79
77
80
78
// Decrement the reference count of the Arc on drop
81
79
unsafe fn drop_waker < W : Wake + Send + Sync + ' static > ( waker : * const ( ) ) {
82
80
mem:: drop ( Arc :: from_raw ( waker as * const W ) ) ;
83
81
}
84
82
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 > ) ,
90
86
) )
91
87
}
0 commit comments