Skip to content

Commit 4757307

Browse files
committed
compat: use a CurrentRef waker in 01 compat
Just to poll a `Future01`, it isn't yet necessary to call `task01::current()`, nor store it in an `Arc::new`. All that is needed is a "reference", and if someone calls `waker().clone()`, *then* we can do the allocations.
1 parent 2b20489 commit 4757307

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

futures-util/src/compat/compat03to01.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use futures_core::{
88
task as task03, TryFuture as TryFuture03, TryStream as TryStream03,
99
};
1010
use futures_sink::Sink as Sink03;
11-
use std::{marker::Unpin, pin::PinMut, sync::Arc};
11+
use std::{marker::Unpin, pin::PinMut, ptr::NonNull, sync::Arc};
1212

1313
impl<Fut, Sp> Future01 for Compat<Fut, Sp>
1414
where
@@ -85,14 +85,32 @@ where
8585
}
8686
}
8787

88-
fn current_as_waker() -> task03::LocalWaker {
89-
let arc_waker = Arc::new(Current(task01::current()));
90-
task03::local_waker_from_nonlocal(arc_waker)
88+
fn current_ref_as_waker() -> task03::LocalWaker {
89+
unsafe {
90+
task03::LocalWaker::new(NonNull::<CurrentRef>::dangling())
91+
}
9192
}
9293

93-
struct Current(task01::Task);
94+
struct CurrentRef;
95+
96+
struct CurrentOwned(task01::Task);
97+
98+
unsafe impl task03::UnsafeWake for CurrentRef {
99+
#[inline]
100+
unsafe fn clone_raw(&self) -> task03::Waker {
101+
task03::Waker::from(Arc::new(CurrentOwned(task01::current())))
102+
}
103+
104+
#[inline]
105+
unsafe fn drop_raw(&self) {} // Does nothing
106+
107+
#[inline]
108+
unsafe fn wake(&self) {
109+
task01::current().notify();
110+
}
111+
}
94112

95-
impl task03::Wake for Current {
113+
impl task03::Wake for CurrentOwned {
96114
fn wake(arc_self: &Arc<Self>) {
97115
arc_self.0.notify();
98116
}
@@ -104,7 +122,7 @@ where
104122
E: task03::Spawn,
105123
F: FnOnce(PinMut<T>, &mut task03::Context) -> R,
106124
{
107-
let waker = current_as_waker();
125+
let waker = current_ref_as_waker();
108126
let spawn = compat.spawn.as_mut().unwrap();
109127
let mut cx = task03::Context::new(&waker, spawn);
110128
f(PinMut::new(&mut compat.inner), &mut cx)

0 commit comments

Comments
 (0)