macro_rules! doc {
($join:item) => {
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
$join
};
}
#[cfg(doc)]
doc! {macro_rules! join {
($(biased;)? $($future:expr),*) => { unimplemented!() }
}}
#[cfg(not(doc))]
doc! {macro_rules! join {
(@ {
// Type of rotator that controls which inner future to start with
// when polling our output future.
rotator_select=$rotator_select:ty;
// One `_` for each branch in the `join!` macro. This is not used once
// normalization is complete.
( $($count:tt)* )
( $($total:tt)* )
$( ( $($skip:tt)* ) $e:expr, )*
}) => {{
use $crate::macros::support::{maybe_done, poll_fn, Future, Pin, RotatorSelect};
use $crate::macros::support::Poll::{Ready, Pending};
let mut futures = ( $( maybe_done($e), )* );
let mut futures = &mut futures;
let mut rotator = <$rotator_select as RotatorSelect>::Rotator::<{$($total)*}>::default();
poll_fn(move |cx| {
const COUNT: u32 = $($total)*;
let mut is_pending = false;
let mut to_run = COUNT;
let mut skip = rotator.num_skip();
loop {
$(
if skip == 0 {
if to_run == 0 {
break;
}
to_run -= 1;
let ( $($skip,)* fut, .. ) = &mut *futures;
let mut fut = unsafe { Pin::new_unchecked(fut) };
if fut.poll(cx).is_pending() {
is_pending = true;
}
} else {
skip -= 1;
}
)*
}
if is_pending {
Pending
} else {
Ready(($({
let ( $($skip,)* fut, .. ) = &mut futures;
let mut fut = unsafe { Pin::new_unchecked(fut) };
fut.take_output().expect("expected completed future")
},)*))
}
}).await
}};
(@ { rotator_select=$rotator_select:ty; ( $($s:tt)* ) ( $($n:tt)* ) $($t:tt)* } $e:expr, $($r:tt)* ) => {
$crate::join!(@{ rotator_select=$rotator_select; ($($s)* _) ($($n)* + 1) $($t)* ($($s)*) $e, } $($r)*)
};
( biased; $($e:expr),+ $(,)?) => {
$crate::join!(@{ rotator_select=$crate::macros::support::SelectBiased; () (0) } $($e,)*)
};
( $($e:expr),+ $(,)?) => {
$crate::join!(@{ rotator_select=$crate::macros::support::SelectNormal; () (0) } $($e,)*)
};
(biased;) => { async {}.await };
() => { async {}.await }
}}
pub trait RotatorSelect {
type Rotator<const COUNT: u32>: Default;
}
#[derive(Debug)]
pub struct SelectNormal;
#[derive(Debug)]
pub struct SelectBiased;
impl RotatorSelect for SelectNormal {
type Rotator<const COUNT: u32> = Rotator<COUNT>;
}
impl RotatorSelect for SelectBiased {
type Rotator<const COUNT: u32> = BiasedRotator;
}
#[derive(Default, Debug)]
pub struct Rotator<const COUNT: u32> {
next: u32,
}
impl<const COUNT: u32> Rotator<COUNT> {
#[inline]
pub fn num_skip(&mut self) -> u32 {
let num_skip = self.next;
self.next += 1;
if self.next == COUNT {
self.next = 0;
}
num_skip
}
}
#[derive(Default, Debug)]
pub struct BiasedRotator {}
impl BiasedRotator {
#[inline]
pub fn num_skip(&mut self) -> u32 {
0
}
}