2019-11-23 00:41:01 +00:00
|
|
|
// Copyright 2020 The Chromium OS Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
// Need non-snake case so the macro can re-use type names for variables.
|
|
|
|
#![allow(non_snake_case)]
|
|
|
|
|
|
|
|
use std::future::Future;
|
|
|
|
use std::pin::Pin;
|
2020-11-20 10:30:49 +00:00
|
|
|
use std::task::{Context, Poll};
|
2019-11-23 00:41:01 +00:00
|
|
|
|
2020-11-20 10:30:49 +00:00
|
|
|
use futures::future::{maybe_done, MaybeDone};
|
|
|
|
use pin_utils::unsafe_pinned;
|
2019-11-23 00:41:01 +00:00
|
|
|
|
|
|
|
// Macro-generate future combinators to allow for running different numbers of top-level futures in
|
|
|
|
// this FutureList. Generates the implementation of `FutureList` for the completion types. For an
|
|
|
|
// explicit example this is modeled after, see `UnitFutures`.
|
|
|
|
macro_rules! generate {
|
|
|
|
($(
|
|
|
|
$(#[$doc:meta])*
|
|
|
|
($Complete:ident, <$($Fut:ident),*>),
|
|
|
|
)*) => ($(
|
|
|
|
#[must_use = "Combinations of futures don't do anything unless run in an executor."]
|
2020-11-20 10:30:49 +00:00
|
|
|
pub(crate) struct $Complete<$($Fut: Future),*> {
|
|
|
|
$($Fut: MaybeDone<$Fut>,)*
|
2019-11-23 00:41:01 +00:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:30:49 +00:00
|
|
|
impl<$($Fut),*> $Complete<$($Fut),*>
|
|
|
|
where $(
|
|
|
|
$Fut: Future,
|
|
|
|
)*
|
|
|
|
{
|
|
|
|
// Safety:
|
|
|
|
// * No Drop impl
|
|
|
|
// * No Unpin impl
|
|
|
|
// * Not #[repr(packed)]
|
|
|
|
$(
|
|
|
|
unsafe_pinned!($Fut: MaybeDone<$Fut>);
|
|
|
|
)*
|
|
|
|
|
|
|
|
pub(crate) fn new($($Fut: $Fut),*) -> $Complete<$($Fut),*> {
|
|
|
|
$(
|
|
|
|
let $Fut = maybe_done($Fut);
|
|
|
|
)*
|
|
|
|
$Complete {
|
|
|
|
$($Fut),*
|
2019-11-23 00:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-20 10:30:49 +00:00
|
|
|
impl<$($Fut),*> Future for $Complete<$($Fut),*>
|
|
|
|
where $(
|
|
|
|
$Fut: Future,
|
|
|
|
)*
|
|
|
|
{
|
2019-11-23 00:41:01 +00:00
|
|
|
type Output = ($($Fut::Output),*);
|
|
|
|
|
2020-11-20 10:30:49 +00:00
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
|
|
|
let mut complete = true;
|
|
|
|
$(
|
|
|
|
complete &= self.as_mut().$Fut().poll(cx).is_ready();
|
|
|
|
)*
|
2019-11-23 00:41:01 +00:00
|
|
|
|
2020-11-20 10:30:49 +00:00
|
|
|
if complete {
|
2019-11-23 00:41:01 +00:00
|
|
|
$(
|
2020-11-20 10:30:49 +00:00
|
|
|
let $Fut = self.as_mut().$Fut().take_output().unwrap();
|
2019-11-23 00:41:01 +00:00
|
|
|
)*
|
2020-11-20 10:30:49 +00:00
|
|
|
Poll::Ready(($($Fut), *))
|
|
|
|
} else {
|
|
|
|
Poll::Pending
|
2019-11-23 00:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)*)
|
|
|
|
}
|
|
|
|
|
|
|
|
generate! {
|
|
|
|
/// _Future for the [`complete2`] function.
|
|
|
|
(Complete2, <_Fut1, _Fut2>),
|
|
|
|
|
|
|
|
/// _Future for the [`complete3`] function.
|
|
|
|
(Complete3, <_Fut1, _Fut2, _Fut3>),
|
|
|
|
|
|
|
|
/// _Future for the [`complete4`] function.
|
|
|
|
(Complete4, <_Fut1, _Fut2, _Fut3, _Fut4>),
|
|
|
|
|
|
|
|
/// _Future for the [`complete5`] function.
|
|
|
|
(Complete5, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5>),
|
|
|
|
}
|