1
- use super :: arc_wake:: ArcWake ;
2
- use super :: waker:: { clone_arc_raw , wake_by_ref_arc_raw } ;
1
+ use super :: arc_wake:: { ArcWake } ;
2
+ use super :: waker:: waker_vtable ;
3
3
use alloc:: sync:: Arc ;
4
+ use core:: mem:: ManuallyDrop ;
4
5
use core:: marker:: PhantomData ;
5
6
use core:: ops:: Deref ;
6
- use core:: task:: { Waker , RawWaker , RawWakerVTable } ;
7
+ use core:: task:: { Waker , RawWaker } ;
7
8
8
9
/// A [`Waker`] that is only valid for a given lifetime.
9
10
///
10
11
/// Note: this type implements [`Deref<Target = Waker>`](std::ops::Deref),
11
12
/// so it can be used to get a `&Waker`.
12
13
#[ derive( Debug ) ]
13
14
pub struct WakerRef < ' a > {
14
- waker : Waker ,
15
+ waker : ManuallyDrop < Waker > ,
15
16
_marker : PhantomData < & ' a ( ) > ,
16
17
}
17
18
18
- impl WakerRef < ' _ > {
19
- /// Create a new [`WakerRef`] from a [`Waker`].
19
+ impl < ' a > WakerRef < ' a > {
20
+ /// Create a new [`WakerRef`] from a [`Waker`] reference.
21
+ pub fn new ( waker : & ' a Waker ) -> Self {
22
+ // copy the underlying (raw) waker without calling a clone,
23
+ // as we won't call Waker::drop either.
24
+ let waker = ManuallyDrop :: new ( unsafe { core:: ptr:: read ( waker) } ) ;
25
+ WakerRef {
26
+ waker,
27
+ _marker : PhantomData ,
28
+ }
29
+ }
30
+
31
+ /// Create a new [`WakerRef`] from a [`Waker`] that must not be dropped.
20
32
///
21
- /// Note: this function is safe, but it is generally only used
22
- /// from `unsafe` contexts that need to create a `Waker`
23
- /// that is guaranteed not to outlive a particular lifetime.
24
- pub fn new ( waker : Waker ) -> Self {
33
+ /// Note: this if for rare cases where the caller created a [`Waker`] in
34
+ /// an unsafe way (that will be valid only for a lifetime to be determined
35
+ /// by the caller), and the [`Waker`] doesn't need to or must not be
36
+ /// destroyed.
37
+ pub fn new_unowned ( waker : ManuallyDrop < Waker > ) -> Self {
25
38
WakerRef {
26
39
waker,
27
40
_marker : PhantomData ,
@@ -37,21 +50,6 @@ impl Deref for WakerRef<'_> {
37
50
}
38
51
}
39
52
40
- #[ inline]
41
- unsafe fn noop ( _data : * const ( ) ) { }
42
-
43
- unsafe fn wake_unreachable ( _data : * const ( ) ) {
44
- // With only a reference, calling `wake_arc_raw()` would be unsound,
45
- // since the `WakerRef` didn't increment the refcount of the `ArcWake`,
46
- // and `wake_arc_raw` would *decrement* it.
47
- //
48
- // This should never be reachable, since `WakerRef` only provides a `Deref`
49
- // to the inner `Waker`.
50
- //
51
- // Still, safer to panic here than to call `wake_arc_raw`.
52
- unreachable ! ( "WakerRef::wake" ) ;
53
- }
54
-
55
53
/// Creates a reference to a [`Waker`] from a reference to `Arc<impl ArcWake>`.
56
54
///
57
55
/// The resulting [`Waker`] will call
@@ -61,21 +59,12 @@ pub fn waker_ref<W>(wake: &Arc<W>) -> WakerRef<'_>
61
59
where
62
60
W : ArcWake
63
61
{
64
- // This uses the same mechanism as Arc::into_raw, without needing a reference.
65
- // This is potentially not stable
66
- let ptr = & * wake as & W as * const W as * const ( ) ;
67
-
68
- // Similar to `waker_vtable`, but with a no-op `drop` function.
69
- // Clones of the resulting `RawWaker` will still be dropped normally.
70
- let vtable = & RawWakerVTable :: new (
71
- clone_arc_raw :: < W > ,
72
- wake_unreachable,
73
- wake_by_ref_arc_raw :: < W > ,
74
- noop,
75
- ) ;
62
+ // simply copy the pointer instead of using Arc::into_raw,
63
+ // as we don't actually keep a refcount by using ManuallyDrop.<
64
+ let ptr = ( & * * wake as * const W ) as * const ( ) ;
76
65
77
- let waker = unsafe {
78
- Waker :: from_raw ( RawWaker :: new ( ptr, vtable ) )
79
- } ;
80
- WakerRef :: new ( waker)
66
+ let waker = ManuallyDrop :: new ( unsafe {
67
+ Waker :: from_raw ( RawWaker :: new ( ptr, waker_vtable :: < W > ( ) ) )
68
+ } ) ;
69
+ WakerRef :: new_unowned ( waker)
81
70
}
0 commit comments