async_core/
joiner.rs

1use core::pin::Pin;
2use core::{
3    future::Future,
4    task::{Context, Poll},
5};
6
7extern crate alloc;
8use alloc::vec::Vec;
9
10use crate::BoxFuture;
11
12/// A future cosisting of multiple other futures. Ready once all of the inner futures are ready.
13pub struct JoinedFuture<'a, T> {
14    futures: Vec<(Option<T>, BoxFuture<'a, T>)>,
15}
16
17impl<'a, T> JoinedFuture<'a, T> {
18    #[inline]
19    fn new(futures: Vec<BoxFuture<'a, T>>) -> Self {
20        Self {
21            futures: futures.into_iter().map(|x| (None, x)).collect(),
22        }
23    }
24}
25
26impl<'a, T> Future for JoinedFuture<'a, T> {
27    type Output = Vec<T>;
28
29    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
30        let mut done = true;
31        let me = unsafe {
32            // SAFETY: This is the only way to access the futures array, and is safe because the
33            // pin necessarily lives as long as poll() and is owned, so won't be modified
34            self.get_unchecked_mut()
35        };
36        for future in me.futures.iter_mut() {
37            if future.0.is_some() {
38                continue;
39            }
40            done = false;
41            if let Poll::Ready(content) = future.1.as_mut().poll(cx) {
42                future.0 = Some(content);
43            }
44        }
45        if done {
46            Poll::Ready(me.futures.iter_mut().map(|x| x.0.take().unwrap()).collect())
47        } else {
48            Poll::Pending
49        }
50    }
51}
52
53/// Joins multiple futures into one, which will be ready once all of the inner ones are. This is
54/// effectively a small one-time-use runtime without the ability to add any tasks.
55#[inline]
56pub fn join<T>(futures: Vec<BoxFuture<T>>) -> JoinedFuture<T> {
57    JoinedFuture::new(futures)
58}
59
60#[macro_export]
61macro_rules! join {
62    ($($a:expr),* $(,)?) => {
63        join(vec![$(
64            $crate::prep($a),
65        )*])
66    };
67}
68
69#[macro_export]
70macro_rules! join_boxed {
71    ($($a:expr),* $(,)?) => {
72        join(vec![$(
73            $a,
74        )*])
75    };
76}