1use core::future::Future;
2use core::pin::Pin;
3use core::task::{Context, Poll};
4
5use alloc::boxed::Box;
6
7#[allow(unused)]
8pub struct Join2<F1, F2>
9where
10 F1: Future,
11 F2: Future,
12{
13 future1: Pin<Box<F1>>,
14 future2: Pin<Box<F2>>,
15 future1_done: bool,
16 future2_done: bool,
17 output1: Option<F1::Output>,
18 output2: Option<F2::Output>,
19}
20
21impl<F1, F2> Join2<F1, F2>
22where
23 F1: Future,
24 F2: Future,
25{
26 pub fn new(future1: F1, future2: F2) -> Self {
27 Self {
28 future1: Box::pin(future1),
29 future2: Box::pin(future2),
30 future1_done: false,
31 future2_done: false,
32 output1: None,
33 output2: None,
34 }
35 }
36}
37
38impl<F1, F2> Future for Join2<F1, F2>
39where
40 F1: Future,
41 F2: Future,
42{
43 type Output = (F1::Output, F2::Output);
44
45 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
46 let this = unsafe { self.get_unchecked_mut() };
47
48 if !this.future1_done {
49 match this.future1.as_mut().poll(cx) {
50 Poll::Ready(output) => {
51 this.output1 = Some(output);
52 this.future1_done = true;
53 }
54 Poll::Pending => {}
55 }
56 }
57
58 if !this.future2_done {
59 match this.future2.as_mut().poll(cx) {
60 Poll::Ready(output) => {
61 this.output2 = Some(output);
62 this.future2_done = true;
63 }
64 Poll::Pending => {}
65 }
66 }
67
68 if this.future1_done && this.future2_done {
69 let output1 = this.output1.take().unwrap();
70 let output2 = this.output2.take().unwrap();
71 Poll::Ready((output1, output2))
72 } else {
73 cx.waker().wake_by_ref();
74 Poll::Pending
75 }
76 }
77}
78
79impl<F1, F2> Unpin for Join2<F1, F2>
80where
81 F1: Future,
82 F2: Future,
83{
84}
85
86#[allow(unused)]
87pub fn join<F1, F2>(future1: F1, future2: F2) -> Join2<F1, F2>
88where
89 F1: Future,
90 F2: Future,
91{
92 Join2::new(future1, future2)
93}
94
95#[macro_export]
97macro_rules! join {
98 ($fut1:expr, $fut2:expr) => {
99 async {
100 $crate::sys::join($fut1, $fut2).await
101 }.await
102 };
103 ($fut1:expr, $fut2:expr, $fut3:expr) => {
104 async {
105 let ((r1, r2), r3) = $crate::sys::join(
106 $crate::sys::join($fut1, $fut2),
107 $fut3
108 ).await;
109 (r1, r2, r3)
110 }.await
111 };
112 ($fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr) => {
113 async {
114 let ((r1, r2), (r3, r4)) = $crate::sys::join(
115 $crate::sys::join($fut1, $fut2),
116 $crate::sys::join($fut3, $fut4)
117 ).await;
118 (r1, r2, r3, r4)
119 }.await
120 };
121}