xref: /aosp_15_r20/external/crosvm/cros_async/src/complete.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker // Need non-snake case so the macro can re-use type names for variables.
6*bb4ee6a4SAndroid Build Coastguard Worker #![allow(non_snake_case)]
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use std::future::Future;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::pin::Pin;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::task::Context;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::task::Poll;
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker use futures::future::maybe_done;
14*bb4ee6a4SAndroid Build Coastguard Worker use futures::future::MaybeDone;
15*bb4ee6a4SAndroid Build Coastguard Worker use pin_utils::unsafe_pinned;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker // Macro-generate future combinators to allow for running different numbers of top-level futures in
18*bb4ee6a4SAndroid Build Coastguard Worker // this FutureList. Generates the implementation of `FutureList` for the completion types. For an
19*bb4ee6a4SAndroid Build Coastguard Worker // explicit example this is modeled after, see `UnitFutures`.
20*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! generate {
21*bb4ee6a4SAndroid Build Coastguard Worker     ($(
22*bb4ee6a4SAndroid Build Coastguard Worker         $(#[$doc:meta])*
23*bb4ee6a4SAndroid Build Coastguard Worker         ($Complete:ident, <$($Fut:ident),*>),
24*bb4ee6a4SAndroid Build Coastguard Worker     )*) => ($(
25*bb4ee6a4SAndroid Build Coastguard Worker         #[must_use = "Combinations of futures don't do anything unless run in an executor."]
26*bb4ee6a4SAndroid Build Coastguard Worker         pub(crate) struct $Complete<$($Fut: Future),*> {
27*bb4ee6a4SAndroid Build Coastguard Worker             $($Fut: MaybeDone<$Fut>,)*
28*bb4ee6a4SAndroid Build Coastguard Worker         }
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker         impl<$($Fut),*> $Complete<$($Fut),*>
31*bb4ee6a4SAndroid Build Coastguard Worker         where $(
32*bb4ee6a4SAndroid Build Coastguard Worker             $Fut: Future,
33*bb4ee6a4SAndroid Build Coastguard Worker         )*
34*bb4ee6a4SAndroid Build Coastguard Worker         {
35*bb4ee6a4SAndroid Build Coastguard Worker             // Safety:
36*bb4ee6a4SAndroid Build Coastguard Worker             // * No Drop impl
37*bb4ee6a4SAndroid Build Coastguard Worker             // * No Unpin impl
38*bb4ee6a4SAndroid Build Coastguard Worker             // * Not #[repr(packed)]
39*bb4ee6a4SAndroid Build Coastguard Worker             $(
40*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe_pinned!($Fut: MaybeDone<$Fut>);
41*bb4ee6a4SAndroid Build Coastguard Worker             )*
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker             pub(crate) fn new($($Fut: $Fut),*) -> $Complete<$($Fut),*> {
44*bb4ee6a4SAndroid Build Coastguard Worker                 $(
45*bb4ee6a4SAndroid Build Coastguard Worker                     let $Fut = maybe_done($Fut);
46*bb4ee6a4SAndroid Build Coastguard Worker                 )*
47*bb4ee6a4SAndroid Build Coastguard Worker                 $Complete {
48*bb4ee6a4SAndroid Build Coastguard Worker                     $($Fut),*
49*bb4ee6a4SAndroid Build Coastguard Worker                 }
50*bb4ee6a4SAndroid Build Coastguard Worker             }
51*bb4ee6a4SAndroid Build Coastguard Worker         }
52*bb4ee6a4SAndroid Build Coastguard Worker 
53*bb4ee6a4SAndroid Build Coastguard Worker         impl<$($Fut),*> Future for $Complete<$($Fut),*>
54*bb4ee6a4SAndroid Build Coastguard Worker         where $(
55*bb4ee6a4SAndroid Build Coastguard Worker             $Fut: Future,
56*bb4ee6a4SAndroid Build Coastguard Worker         )*
57*bb4ee6a4SAndroid Build Coastguard Worker         {
58*bb4ee6a4SAndroid Build Coastguard Worker             type Output = ($($Fut::Output),*);
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker             fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
61*bb4ee6a4SAndroid Build Coastguard Worker                 let mut complete = true;
62*bb4ee6a4SAndroid Build Coastguard Worker                 $(
63*bb4ee6a4SAndroid Build Coastguard Worker                     complete &= self.as_mut().$Fut().poll(cx).is_ready();
64*bb4ee6a4SAndroid Build Coastguard Worker                 )*
65*bb4ee6a4SAndroid Build Coastguard Worker 
66*bb4ee6a4SAndroid Build Coastguard Worker                 if complete {
67*bb4ee6a4SAndroid Build Coastguard Worker                     $(
68*bb4ee6a4SAndroid Build Coastguard Worker                         let $Fut = self.as_mut().$Fut().take_output().unwrap();
69*bb4ee6a4SAndroid Build Coastguard Worker                     )*
70*bb4ee6a4SAndroid Build Coastguard Worker                     Poll::Ready(($($Fut), *))
71*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
72*bb4ee6a4SAndroid Build Coastguard Worker                     Poll::Pending
73*bb4ee6a4SAndroid Build Coastguard Worker                 }
74*bb4ee6a4SAndroid Build Coastguard Worker             }
75*bb4ee6a4SAndroid Build Coastguard Worker         }
76*bb4ee6a4SAndroid Build Coastguard Worker     )*)
77*bb4ee6a4SAndroid Build Coastguard Worker }
78*bb4ee6a4SAndroid Build Coastguard Worker 
79*bb4ee6a4SAndroid Build Coastguard Worker generate! {
80*bb4ee6a4SAndroid Build Coastguard Worker     /// _Future for the [`complete2`] function.
81*bb4ee6a4SAndroid Build Coastguard Worker     (Complete2, <_Fut1, _Fut2>),
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker     /// _Future for the [`complete3`] function.
84*bb4ee6a4SAndroid Build Coastguard Worker     (Complete3, <_Fut1, _Fut2, _Fut3>),
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker     /// _Future for the [`complete4`] function.
87*bb4ee6a4SAndroid Build Coastguard Worker     (Complete4, <_Fut1, _Fut2, _Fut3, _Fut4>),
88*bb4ee6a4SAndroid Build Coastguard Worker 
89*bb4ee6a4SAndroid Build Coastguard Worker     /// _Future for the [`complete5`] function.
90*bb4ee6a4SAndroid Build Coastguard Worker     (Complete5, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5>),
91*bb4ee6a4SAndroid Build Coastguard Worker }
92