···22 future::{ScopedFuture, Wake},
33 utils::{MaybeDone, maybe_done},
44};
55-use std::pin::Pin;
66-use std::task::Poll;
55+use std::mem;
66+use std::{pin::Pin, sync::atomic::Ordering};
77+use std::{sync::atomic::AtomicBool, task::Poll};
7889/// from yoshuawuyts/futures-concurrency
910/// Wait for all futures to complete.
···6970// https://github.com/yoshuawuyts/futures-concurrency/blob/main/src/utils/wakers/array/waker.rs
7071// possibly copy large portions of futures-concurrency over here
71727272-/// implements unsafe logic for a set of wakers waking one waker
7373-pub struct WakerArray<'scope, const N: usize> {
7474- parent_waker: Option<Wake<'scope>>,
7575- // TODO bit packing
7676- child_readiness: [bool; N],
7777- child_wakers: [Wake<'scope>; N],
7878-}
7373+// struct Waker<'scope> {
7474+// parent_waker: Wake<'scope>,
7575+// }
7676+7777+// impl<'scope> Waker<'scope> {
7878+// fn wake(&mut self) {
7979+// (*self.parent_waker)();
8080+// }
8181+// }
79828080-impl<'scope, const N: usize> WakerArray<'scope, N> {
8181- fn new() -> Self {
8282- // let mut this = Self {
8383- // parent_waker: None,
8484- // child_readiness: [false; N],
8585- // child_wakers: [|| {}; N],
8686- // };
8787- // this.child_wakers = [|x| 2 * x; N];
8888- // this
8989- }
9090-}
8383+// /// implements unsafe logic for a set of wakers waking one waker
8484+// pub struct WakerArray<'scope, const N: usize> {
8585+// parent_waker: Option<&'scope dyn Wake<'scope>>,
8686+// // TODO bit packing
8787+// child_readiness: [bool; N],
8888+// pub child_wakers: Option<[Waker<'scope>; N]>,
8989+// }
9090+9191+// impl<'scope, const N: usize> WakerArray<'scope, N> {
9292+// fn new() -> Self {
9393+// Self {
9494+// parent_waker: None,
9595+// child_readiness: [false; N],
9696+// child_wakers: None,
9797+// }
9898+// }
9999+100100+// fn register_parent_wake(&mut self, wake: Wake<'scope>) {
101101+// self.parent_waker = Some(wake);
102102+// self.child_wakers = Some(
103103+// [Waker {
104104+// parent_waker: &self.parent_waker,
105105+// }; N],
106106+// );
107107+// }
108108+// }
9110992110// would be rly nice if rust had java functional interfaces for wake(&mut Self)
931119494-// TODO bit packing
95112struct WakeStore<'scope> {
9696- ready: bool,
9797- parent: Wake<'scope>,
113113+ // no extra storage bc None is 0x000 ptr
114114+ parent: Option<&'scope dyn Wake<'scope>>,
115115+ ready: AtomicBool,
98116}
99117100118impl<'scope> WakeStore<'scope> {
101101- fn new(parent: Wake<'scope>) -> Self {
119119+ fn new() -> Self {
102120 Self {
103103- parent,
104104- ready: true,
121121+ parent: Option::None,
122122+ ready: true.into(),
105123 }
106124 }
107125108126 fn take_ready(&mut self) -> bool {
109109- let out = self.ready;
110110- self.ready = false;
111111- out
127127+ self.ready.swap(false, Ordering::SeqCst)
112128 }
113129}
114130115115-// impl ScopedWake for WakeStore<'_> {
116116-// fn wake(&mut self) {
117117-// self.ready = true;
118118-// self.parent.wake();
119119-// }
120120-// }
131131+impl<'scope> Wake<'scope> for WakeStore<'scope> {
132132+ fn wake(&self) {
133133+ self.ready.swap(true, Ordering::SeqCst);
134134+ if let Some(parent) = self.parent {
135135+ parent.wake();
136136+ }
137137+ }
138138+}
121139122140// heavily based on https://github.com/yoshuawuyts/futures-concurrency
123141macro_rules! impl_join_tuple {
···128146 // future_$F and waker_$F
129147 #[allow(non_snake_case)]
130148 struct Wakers<'scope> {
149149+ // inefficient, needs tt muncher for actual [T; LEN] traversal, fewer cache misses
131150 $($F: WakeStore<'scope>,)*
132151 }
133152134153 #[allow(non_snake_case)]
135154 pub struct $StructName<'scope, $($F: ScopedFuture<'scope>),+> {
136136- parent_waker: Option<Wake<'scope>>,
155155+ // parent_waker: Option<&'scope dyn Wake>,
137156 $($F: MaybeDone<'scope, $F>,)*
138157 wakers: Wakers<'scope>,
139158 }
140159141141- impl<'scope, $($F: ScopedFuture<'scope>),+> ScopedFuture<'scope> for $StructName<'scope, $($F),+> {
160160+ impl<'scope, $($F: ScopedFuture<'scope> + 'scope),+> ScopedFuture<'scope> for $StructName<'scope, $($F),+>
161161+ {
142162 type Output = ($($F::Output),+);
143163144144- fn register_wake(self: Pin<&mut Self>, waker: Wake<'scope>) {
145145- unsafe { self.get_unchecked_mut() }.parent_waker = Some(waker);
146146- }
147147-148148- fn poll(self: Pin<&mut Self>) -> Poll<Self::Output> {
164164+ fn poll(self: Pin<&mut Self>, wake: &'scope dyn Wake<'scope>) -> Poll<Self::Output>
165165+ {
149166 let this = unsafe { self.get_unchecked_mut() };
150167151168 let mut ready = true;
152169153153- // "loop" through all ready futures, poll if ready
154154- //
155155- // this combinator is complete when all internal futures have
156156- // polled to completion
157170 $(
158158- // let $F = unsafe { &mut self.map_unchecked_mut(|f| &mut f.$F) };
171171+ this.wakers.$F.parent = Some(wake);
172172+159173 if let MaybeDone::Future(fut) = &mut this.$F {
160174 ready &= if this.wakers.$F.take_ready() {
161161- unsafe { Pin::new_unchecked(fut) }.poll().is_ready()
175175+ unsafe {
176176+ Pin::new_unchecked(fut).poll(mem::transmute(&this.wakers.$F as &dyn Wake)).is_ready()
177177+ }
162178 } else {
163179 false
164180 };
···167183168184 if ready {
169185 Poll::Ready(($(
170170- // unwrap_unchecked is safe here because we know all
171171- // futures have been polled to completion
172172- // (`MaybeDone::Done`) and have never been converted
173173- // to `MaybeDone::Gone`
174174- unsafe { Pin::new_unchecked(&mut this.$F).take_output().unwrap_unchecked() },
186186+ // unwrap_unchecked is safe here because we know all
187187+ // futures have been polled to completion
188188+ // (`MaybeDone::Done`) and have never been converted
189189+ // to `MaybeDone::Gone`
190190+ unsafe { Pin::new_unchecked(&mut this.$F).take_output().unwrap_unchecked() },
175191 )*))
176192 } else {
177193 Poll::Pending
···180196 }
181197 }
182198183183- // impl<'scope, $($F: ScopedFuture<'scope>),+> Wake<'scope> for $StructName<'scope, $($F),+> {
184184- // fn wake(&mut self) {
185185- // if let Some(waker) = &mut self.parent_waker {
186186- // waker.wake();
187187- // };
188188- // }
189189- // }
190190-191191- impl<'scope, $($F: ScopedFuture<'scope>),+> Join<'scope> for ($($F),+) {
199199+ impl<'scope, $($F: ScopedFuture<'scope> + 'scope),+> Join<'scope> for ($($F),+) {
192200 type Output = ($($F::Output),*);
193201 type Future = $StructName<'scope, $($F),+>;
194202195203 #[allow(non_snake_case)]
196204 fn join(self) -> Self::Future {
197205 let ($($F),+): ($($F),+) = self;
198198- // $StructName {
199199- // parent_waker: Option::None,
200200- // $($F: maybe_done($F),)*
201201- // wakers: $(Wakers { $F: WakeStore::new(&mut Self) }),*
202202- // }
203203- todo!()
204204- // TODO register all wakers
206206+ $StructName {
207207+ // parent_waker: Option::None,
208208+ $($F: maybe_done($F),)*
209209+ wakers: Wakers { $($F: WakeStore::new(),)* }
210210+ }
205211 }
206212 }
207213 };
+9-6
futures/src/future.rs
···44///
55/// This acts as a handle for a reactor to indicate when a `ScopedFuture` is
66/// once again ready to be polled.
77-pub type Wake<'scope> = &'scope dyn FnMut() -> ();
77+pub trait Wake<'scope> {
88+ fn wake(&self);
99+}
810911/// ScopedFuture represents a unit of asynchronous computation that must be
1012/// polled by an external actor.
···4244/// If waker is ownable/cloneable, that erases the lifetime's importance.
4345/// If the waker is a non clonable mutable reference that lives for 'scope,
4446/// it cannot be passed into `poll` every time the future is polled, instead it
4545-/// must only be registered once.
4747+/// must only be registered once, leading to a register_waker api that is very
4848+/// cumbersome without unsafe poll/unsafe register_waker. Instead, it's easier
4949+/// to use a non clonable immutable reference and have waking occur via
5050+/// interior mutability (this is fine since combinators rely on interior
5151+/// mutability anyway for a 1 parent : many children waker relationship)
4652pub trait ScopedFuture<'scope> {
4753 type Output;
48544949- // these could be made unsafe to guarantee polling to completion?
5050- fn register_wake(self: Pin<&mut Self>, wake: Wake<'scope>);
5151-5252- fn poll(self: Pin<&mut Self>) -> Poll<Self::Output>;
5555+ fn poll(self: Pin<&mut Self>, wake: &'scope dyn Wake<'scope>) -> Poll<Self::Output>;
5356}
+6-3
futures/src/utils/maybe_done.rs
···11//! Definition of the MaybeDone combinator
2233-use crate::future::{ScopedFuture, ScopedWake};
33+use crate::future::{ScopedFuture, Wake};
4455use super::assert_future;
66use core::mem;
77use core::pin::Pin;
88-use std::task::Poll;
88+use std::task::{Poll, ready};
991010/// A future that may have completed.
1111///
···8989impl<'scope, Fut: ScopedFuture<'scope>> ScopedFuture<'scope> for MaybeDone<'scope, Fut> {
9090 type Output = ();
91919292- fn poll(mut self: Pin<&mut Self>, cx: &'scope mut dyn ScopedWake) -> Poll<Self::Output> {
9292+ fn poll(mut self: Pin<&mut Self>, cx: &'scope dyn Wake<'scope>) -> Poll<Self::Output>
9393+// where
9494+ // 'scope: 'react,
9595+ {
9396 unsafe {
9497 match self.as_mut().get_unchecked_mut() {
9598 Self::Future(f) => {