@@ -4,11 +4,21 @@ use futures_01::{
44 StartSend as StartSend01 , Stream as Stream01 ,
55} ;
66use futures_core:: {
7- task as task03, TryFuture as TryFuture03 , TryStream as TryStream03 ,
7+ task:: {
8+ self as task03,
9+ RawWaker ,
10+ RawWakerVTable ,
11+ } ,
12+ TryFuture as TryFuture03 ,
13+ TryStream as TryStream03 ,
814} ;
915use futures_sink:: Sink as Sink03 ;
10- use crate :: task:: ArcWake as ArcWake03 ;
11- use std:: { pin:: Pin , sync:: Arc } ;
16+ use crate :: task:: { ArcWake as ArcWake03 , WakerRef } ;
17+ use std:: {
18+ mem,
19+ pin:: Pin ,
20+ sync:: Arc ,
21+ } ;
1222
1323/// Converts a futures 0.3 [`TryFuture`](futures_core::future::TryFuture),
1424/// [`TryStream`](futures_core::stream::TryStream) or
@@ -108,19 +118,40 @@ where
108118 }
109119}
110120
121+ #[ derive( Clone ) ]
111122struct Current ( task01:: Task ) ;
112123
113124impl Current {
114125 fn new ( ) -> Current {
115126 Current ( task01:: current ( ) )
116127 }
117128
118- fn as_waker ( & self ) -> task03:: Waker {
119- // For simplicity reasons wrap the Waker into an Arc.
120- // We can optimize this again later on and reintroduce WakerLt<'a> which
121- // derefs to Waker, and where cloning it through RawWakerVTable returns
122- // an Arc version
123- ArcWake03 :: into_waker ( Arc :: new ( Current ( self . 0 . clone ( ) ) ) )
129+ fn as_waker ( & self ) -> WakerRef < ' _ > {
130+ unsafe fn ptr_to_current < ' a > ( ptr : * const ( ) ) -> & ' a Current {
131+ & * ( ptr as * const Current )
132+ }
133+ fn current_to_ptr ( current : & Current ) -> * const ( ) {
134+ current as * const Current as * const ( )
135+ }
136+
137+ unsafe fn clone ( ptr : * const ( ) ) -> RawWaker {
138+ // Lazily create the `Arc` only when the waker is actually cloned.
139+ // FIXME: remove `transmute` when a `Waker` -> `RawWaker` conversion
140+ // function is landed in `core`.
141+ mem:: transmute :: < task03:: Waker , RawWaker > (
142+ Arc :: new ( ptr_to_current ( ptr) . clone ( ) ) . into_waker ( )
143+ )
144+ }
145+ unsafe fn drop ( _: * const ( ) ) { }
146+ unsafe fn wake ( ptr : * const ( ) ) {
147+ ptr_to_current ( ptr) . 0 . notify ( )
148+ }
149+
150+ let ptr = current_to_ptr ( self ) ;
151+ let vtable = & RawWakerVTable { clone, drop, wake } ;
152+ unsafe {
153+ WakerRef :: new ( task03:: Waker :: new_unchecked ( RawWaker :: new ( ptr, vtable) ) )
154+ }
124155 }
125156}
126157
0 commit comments