Skip to content

Commit aade6fb

Browse files
committed
Prevent unnecessary allocation in compat03as01 Waker
1 parent 0e058f7 commit aade6fb

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

futures-util/src/compat/compat03as01.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,28 @@ impl Current {
115115
Current(task01::current())
116116
}
117117

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())))
118+
fn as_waker(&self) -> task03::WakerRef<'_> {
119+
unsafe fn ptr_to_current(ptr: *const ()) -> &Current {
120+
&*(ptr as *const Current)
121+
}
122+
unsafe fn current_to_ptr(current: &Current) -> *const () {
123+
waker as *const Current as *const ()
124+
}
125+
126+
unsafe fn clone(ptr: *const ()) -> RawWaker {
127+
// Lazily create the `Arc` only when the waker is actually cloned.
128+
Arc::new(ptr_to_current(ptr).clone()).into_waker().into_raw()
129+
}
130+
unsafe fn drop(_: *const ()) {}
131+
unsafe fn wake(ptr: *const ()) {
132+
ptr_to_current(ptr).0.notify()
133+
}
134+
135+
let ptr = waker_to_ptr(self);
136+
let vtable = &RawWakerVTable { clone, drop, wake };
137+
unsafe {
138+
task03::WakerRef::new(task03::Waker::new_unchecked(RawWaker::new(ptr, vtable)))
139+
}
124140
}
125141
}
126142

0 commit comments

Comments
 (0)