@@ -4,11 +4,21 @@ use futures_01::{
4
4
StartSend as StartSend01 , Stream as Stream01 ,
5
5
} ;
6
6
use 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 ,
8
14
} ;
9
15
use 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
+ } ;
12
22
13
23
/// Converts a futures 0.3 [`TryFuture`](futures_core::future::TryFuture),
14
24
/// [`TryStream`](futures_core::stream::TryStream) or
@@ -108,19 +118,40 @@ where
108
118
}
109
119
}
110
120
121
+ #[ derive( Clone ) ]
111
122
struct Current ( task01:: Task ) ;
112
123
113
124
impl Current {
114
125
fn new ( ) -> Current {
115
126
Current ( task01:: current ( ) )
116
127
}
117
128
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
+ }
124
155
}
125
156
}
126
157
0 commit comments