// 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; use std::task::{Context, Poll}; use futures::future::{maybe_done, MaybeDone}; use pin_utils::unsafe_pinned; // 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."] pub(crate) struct $Complete<$($Fut: Future),*> { $($Fut: MaybeDone<$Fut>,)* } 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),* } } } impl<$($Fut),*> Future for $Complete<$($Fut),*> where $( $Fut: Future, )* { type Output = ($($Fut::Output),*); fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { let mut complete = true; $( complete &= self.as_mut().$Fut().poll(cx).is_ready(); )* if complete { $( let $Fut = self.as_mut().$Fut().take_output().unwrap(); )* Poll::Ready(($($Fut), *)) } else { Poll::Pending } } } )*) } 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>), }