···55use std::mem;
66use std::{pin::Pin, sync::atomic::Ordering};
77use std::{sync::atomic::AtomicBool, task::Poll};
88+89/// from yoshuawuyts/futures-concurrency
910/// Wait for all futures to complete.
1011///
···1314pub trait Join<'scope> {
1415 /// The resulting output type.
1516 type Output;
1616- /// The [`Future`] implementation returned by this method.
1717+ /// The [`ScopedFuture`] implementation returned by this method.
1718 type Future: ScopedFuture<'scope, Output = Self::Output>;
1819 /// Waits for multiple futures to complete.
1920 ///
···8788}
88898990macro_rules! impl_join_tuple {
9090- ($StructName:ident $($F:ident)+) => {
9191- #[allow(non_snake_case)]
9292- struct Wakers<'scope> {
9393- $($F: WakeStore<'scope>,)*
9191+ ($namespace: ident $StructName:ident $($F:ident)+) => {
9292+9393+ mod $namespace {
9494+ use super::WakeStore;
9595+9696+ #[allow(non_snake_case)]
9797+ pub struct Wakers<'scope> {
9898+ $(pub $F: WakeStore<'scope>,)*
9999+ }
94100 }
9510196102 #[allow(non_snake_case)]
97103 pub struct $StructName<'scope, $($F: ScopedFuture<'scope>),+> {
98104 $($F: MaybeDone<'scope, $F>,)*
9999- wakers: Wakers<'scope>,
105105+ wakers: $namespace::Wakers<'scope>,
100106 }
101107102108 impl<'scope, $($F: ScopedFuture<'scope> + 'scope),+> ScopedFuture<'scope>
···113119114120 if let MaybeDone::Future(fut) = &mut this.$F {
115121 ready &= if this.wakers.$F.take_ready() {
122122+ // # Safety
123123+ //
124124+ // mem::transmute is necessary to convert between
125125+ // `&'poll dyn Wake<'scope>` and
126126+ // `&'scope dyn Wake<'scope>`, where `'poll` is the
127127+ // lifetime implicitly assigned to the `&mut self`
128128+ // argument.
129129+ //
130130+ // This is safe because
131131+ // - `Self: 'scope` (all data inside `Join` live
132132+ // for at least `'scope`)
133133+ // - `this.wakers.$F` is pinned
134134+ // - mutation to `this.wakers.$F.parent` doesn't
135135+ // violate the `&'scope dyn Wake`
116136 unsafe {
117137 Pin::new_unchecked(fut).poll(
118138 mem::transmute::<&dyn Wake<'scope>, &'scope dyn Wake<'scope>>(
···129149 if ready {
130150 Poll::Ready((
131151 $(
152152+ // # Safety
153153+ //
154154+ // All $Fs start as `MaybeDone::Future`.
155155+ //
156156+ // `ready == true` is only hit when we know every
157157+ // future either just finished or previously
158158+ // finished, meaning they are all
159159+ // `MaybeDone::Done`.
160160+ //
161161+ // `MaybeDone::Done::take_output()` always returns
162162+ // the owned output of the inner future.
132163 unsafe {
133164 Pin::new_unchecked(&mut this.$F)
134165 .take_output()
···152183153184 $StructName {
154185 $($F: maybe_done($F),)*
155155- wakers: Wakers { $($F: WakeStore::new(),)* },
186186+ wakers: $namespace::Wakers { $($F: WakeStore::new(),)* },
156187 }
157188 }
158189 }
159190 };
160191}
161192162162-impl_join_tuple!(Join2 A B);
193193+impl_join_tuple!(join2 Join2 A B);
194194+impl_join_tuple!(join3 Join3 A B C);
195195+impl_join_tuple!(join4 Join4 A B C D);
196196+impl_join_tuple!(join5 Join5 A B C D E);
197197+impl_join_tuple!(join6 Join6 A B C D E F);
198198+impl_join_tuple!(join7 Join7 A B C D E F G);
199199+impl_join_tuple!(join8 Join8 A B C D E F G H);
200200+impl_join_tuple!(join9 Join9 A B C D E F G H I);
201201+impl_join_tuple!(join10 Join10 A B C D E F G H I J);
202202+impl_join_tuple!(join11 Join11 A B C D E F G H I J K);
203203+impl_join_tuple!(join12 Join12 A B C D E F G H I J K L);