1 // Copyright 2020 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Need non-snake case so the macro can re-use type names for variables. 6 #![allow(non_snake_case)] 7 8 use std::future::Future; 9 use std::pin::Pin; 10 use std::task::{Context, Poll}; 11 12 use futures::future::{maybe_done, FutureExt, MaybeDone}; 13 14 pub enum SelectResult<F: Future> { 15 Pending(F), 16 Finished(F::Output), 17 } 18 19 // Macro-generate future combinators to allow for running different numbers of top-level futures in 20 // this FutureList. Generates the implementation of `FutureList` for the select types. For an 21 // explicit example this is modeled after, see `UnitFutures`. 22 macro_rules! generate { 23 ($( 24 $(#[$doc:meta])* 25 ($Select:ident, <$($Fut:ident),*>), 26 )*) => ($( 27 #[must_use = "Combinations of futures don't do anything unless run in an executor."] 28 paste::item! { 29 pub(crate) struct $Select<$($Fut: Future + Unpin),*> { 30 $($Fut: MaybeDone<$Fut>,)* 31 } 32 } 33 34 impl<$($Fut: Future + Unpin),*> $Select<$($Fut),*> { 35 paste::item! { 36 pub(crate) fn new($($Fut: $Fut),*) -> $Select<$($Fut),*> { 37 $Select { 38 $($Fut: maybe_done($Fut),)* 39 } 40 } 41 } 42 } 43 44 impl<$($Fut: Future + Unpin),*> Future for $Select<$($Fut),*> { 45 type Output = ($(SelectResult<$Fut>),*); 46 47 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { 48 let mut complete = false; 49 $( 50 let $Fut = Pin::new(&mut self.$Fut); 51 // The future impls `Unpin`, use `poll_unpin` to avoid wrapping it in 52 // `Pin` to call `poll`. 53 complete |= self.$Fut.poll_unpin(cx).is_ready(); 54 )* 55 56 if complete { 57 Poll::Ready(($( 58 match std::mem::replace(&mut self.$Fut, MaybeDone::Gone) { 59 MaybeDone::Future(f) => SelectResult::Pending(f), 60 MaybeDone::Done(o) => SelectResult::Finished(o), 61 MaybeDone::Gone => unreachable!(), 62 } 63 ), *)) 64 } else { 65 Poll::Pending 66 } 67 } 68 } 69 )*) 70 } 71 72 generate! { 73 /// _Future for the [`select2`] function. 74 (Select2, <_Fut1, _Fut2>), 75 76 /// _Future for the [`select3`] function. 77 (Select3, <_Fut1, _Fut2, _Fut3>), 78 79 /// _Future for the [`select4`] function. 80 (Select4, <_Fut1, _Fut2, _Fut3, _Fut4>), 81 82 /// _Future for the [`select5`] function. 83 (Select5, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5>), 84 85 /// _Future for the [`select6`] function. 86 (Select6, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5, _Fut6>), 87 } 88