@@ -5,7 +5,7 @@ use core::sync::atomic::{AtomicBool, AtomicPtr};
55
66use super :: abort:: abort;
77use super :: ReadyToRunQueue ;
8- use crate :: task:: { waker_ref , ArcWake , WakerRef } ;
8+ use crate :: task:: ArcWake ;
99
1010pub ( super ) struct Task < Fut > {
1111 // The future
@@ -77,8 +77,8 @@ impl<Fut> ArcWake for Task<Fut> {
7777
7878impl < Fut > Task < Fut > {
7979 /// Returns a waker reference for this task without cloning the Arc.
80- pub ( super ) fn waker_ref ( this : & Arc < Self > ) -> WakerRef < ' _ > {
81- waker_ref ( this)
80+ pub ( super ) unsafe fn waker_ref ( this : & Arc < Self > ) -> waker_ref :: WakerRef < ' _ > {
81+ unsafe { waker_ref:: waker_ref ( this) }
8282 }
8383
8484 /// Spins until `next_all` is no longer set to `pending_next_all`.
@@ -123,3 +123,92 @@ impl<Fut> Drop for Task<Fut> {
123123 }
124124 }
125125}
126+
127+ mod waker_ref {
128+ use alloc:: sync:: Arc ;
129+ use core:: marker:: PhantomData ;
130+ use core:: mem;
131+ use core:: mem:: ManuallyDrop ;
132+ use core:: ops:: Deref ;
133+ use core:: task:: { RawWaker , RawWakerVTable , Waker } ;
134+ use futures_task:: ArcWake ;
135+
136+ pub ( crate ) struct WakerRef < ' a > {
137+ waker : ManuallyDrop < Waker > ,
138+ _marker : PhantomData < & ' a ( ) > ,
139+ }
140+
141+ impl WakerRef < ' _ > {
142+ #[ inline]
143+ fn new_unowned ( waker : ManuallyDrop < Waker > ) -> Self {
144+ Self { waker, _marker : PhantomData }
145+ }
146+ }
147+
148+ impl Deref for WakerRef < ' _ > {
149+ type Target = Waker ;
150+
151+ #[ inline]
152+ fn deref ( & self ) -> & Waker {
153+ & self . waker
154+ }
155+ }
156+
157+ /// Copy of `future_task::waker_ref` without `W: 'static` bound.
158+ ///
159+ /// # Safety
160+ ///
161+ /// The caller must guarantee that use-after-free will not occur.
162+ #[ inline]
163+ pub ( crate ) unsafe fn waker_ref < W > ( wake : & Arc < W > ) -> WakerRef < ' _ >
164+ where
165+ W : ArcWake ,
166+ {
167+ // simply copy the pointer instead of using Arc::into_raw,
168+ // as we don't actually keep a refcount by using ManuallyDrop.<
169+ let ptr = Arc :: as_ptr ( wake) . cast :: < ( ) > ( ) ;
170+
171+ let waker =
172+ ManuallyDrop :: new ( unsafe { Waker :: from_raw ( RawWaker :: new ( ptr, waker_vtable :: < W > ( ) ) ) } ) ;
173+ WakerRef :: new_unowned ( waker)
174+ }
175+
176+ fn waker_vtable < W : ArcWake > ( ) -> & ' static RawWakerVTable {
177+ & RawWakerVTable :: new (
178+ clone_arc_raw :: < W > ,
179+ wake_arc_raw :: < W > ,
180+ wake_by_ref_arc_raw :: < W > ,
181+ drop_arc_raw :: < W > ,
182+ )
183+ }
184+
185+ // FIXME: panics on Arc::clone / refcount changes could wreak havoc on the
186+ // code here. We should guard against this by aborting.
187+
188+ unsafe fn increase_refcount < T : ArcWake > ( data : * const ( ) ) {
189+ // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
190+ let arc = mem:: ManuallyDrop :: new ( unsafe { Arc :: < T > :: from_raw ( data. cast :: < T > ( ) ) } ) ;
191+ // Now increase refcount, but don't drop new refcount either
192+ let _arc_clone: mem:: ManuallyDrop < _ > = arc. clone ( ) ;
193+ }
194+
195+ unsafe fn clone_arc_raw < T : ArcWake > ( data : * const ( ) ) -> RawWaker {
196+ unsafe { increase_refcount :: < T > ( data) }
197+ RawWaker :: new ( data, waker_vtable :: < T > ( ) )
198+ }
199+
200+ unsafe fn wake_arc_raw < T : ArcWake > ( data : * const ( ) ) {
201+ let arc: Arc < T > = unsafe { Arc :: from_raw ( data. cast :: < T > ( ) ) } ;
202+ ArcWake :: wake ( arc) ;
203+ }
204+
205+ unsafe fn wake_by_ref_arc_raw < T : ArcWake > ( data : * const ( ) ) {
206+ // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
207+ let arc = mem:: ManuallyDrop :: new ( unsafe { Arc :: < T > :: from_raw ( data. cast :: < T > ( ) ) } ) ;
208+ ArcWake :: wake_by_ref ( & arc) ;
209+ }
210+
211+ unsafe fn drop_arc_raw < T : ArcWake > ( data : * const ( ) ) {
212+ drop ( unsafe { Arc :: < T > :: from_raw ( data. cast :: < T > ( ) ) } )
213+ }
214+ }
0 commit comments