Skip to main content

leodos_libcfs/runtime/
join.rs

1//! Structured concurrency primitives.
2//!
3//! [`join!`] and [`try_join!`] poll multiple futures
4//! concurrently until all complete. `try_join!` returns
5//! early on the first error.
6//!
7//! ```ignore
8//! use leodos_libcfs::join;
9//! use leodos_libcfs::try_join;
10//!
11//! let (a, b) = join!(fut_a, fut_b).await;
12//! let (a, b) = try_join!(fut_a, fut_b).await?;
13//! ```
14
15/// Polls futures concurrently, returning a tuple of all
16/// outputs when every future has completed.
17#[macro_export]
18macro_rules! join {
19    ($f1:expr, $f2:expr $(,)?) => {
20        async {
21            use ::core::future::Future;
22            let f1 = $f1;
23            let f2 = $f2;
24            $crate::runtime::pin_mut!(f1, f2);
25            let (mut s1, mut s2) = (None, None);
26            ::core::future::poll_fn(|cx| {
27                if s1.is_none() { if let ::core::task::Poll::Ready(v) = f1.as_mut().poll(cx) { s1 = Some(v); } }
28                if s2.is_none() { if let ::core::task::Poll::Ready(v) = f2.as_mut().poll(cx) { s2 = Some(v); } }
29                if s1.is_some() && s2.is_some() {
30                    ::core::task::Poll::Ready((s1.take().unwrap(), s2.take().unwrap()))
31                } else { ::core::task::Poll::Pending }
32            }).await
33        }
34    };
35    ($f1:expr, $f2:expr, $f3:expr $(,)?) => {
36        async {
37            use ::core::future::Future;
38            let f1 = $f1;
39            let f2 = $f2;
40            let f3 = $f3;
41            $crate::runtime::pin_mut!(f1, f2, f3);
42            let (mut s1, mut s2, mut s3) = (None, None, None);
43            ::core::future::poll_fn(|cx| {
44                if s1.is_none() { if let ::core::task::Poll::Ready(v) = f1.as_mut().poll(cx) { s1 = Some(v); } }
45                if s2.is_none() { if let ::core::task::Poll::Ready(v) = f2.as_mut().poll(cx) { s2 = Some(v); } }
46                if s3.is_none() { if let ::core::task::Poll::Ready(v) = f3.as_mut().poll(cx) { s3 = Some(v); } }
47                if s1.is_some() && s2.is_some() && s3.is_some() {
48                    ::core::task::Poll::Ready((s1.take().unwrap(), s2.take().unwrap(), s3.take().unwrap()))
49                } else { ::core::task::Poll::Pending }
50            }).await
51        }
52    };
53    ($f1:expr, $f2:expr, $f3:expr, $f4:expr $(,)?) => {
54        async {
55            use ::core::future::Future;
56            let f1 = $f1;
57            let f2 = $f2;
58            let f3 = $f3;
59            let f4 = $f4;
60            $crate::runtime::pin_mut!(f1, f2, f3, f4);
61            let (mut s1, mut s2, mut s3, mut s4) = (None, None, None, None);
62            ::core::future::poll_fn(|cx| {
63                if s1.is_none() { if let ::core::task::Poll::Ready(v) = f1.as_mut().poll(cx) { s1 = Some(v); } }
64                if s2.is_none() { if let ::core::task::Poll::Ready(v) = f2.as_mut().poll(cx) { s2 = Some(v); } }
65                if s3.is_none() { if let ::core::task::Poll::Ready(v) = f3.as_mut().poll(cx) { s3 = Some(v); } }
66                if s4.is_none() { if let ::core::task::Poll::Ready(v) = f4.as_mut().poll(cx) { s4 = Some(v); } }
67                if s1.is_some() && s2.is_some() && s3.is_some() && s4.is_some() {
68                    ::core::task::Poll::Ready((s1.take().unwrap(), s2.take().unwrap(), s3.take().unwrap(), s4.take().unwrap()))
69                } else { ::core::task::Poll::Pending }
70            }).await
71        }
72    };
73}
74
75/// Polls futures concurrently, returning `Ok(tuple)` when
76/// all complete successfully, or the first `Err` encountered.
77#[macro_export]
78macro_rules! try_join {
79    ($f1:expr, $f2:expr $(,)?) => {
80        async {
81            use ::core::future::Future;
82            let f1 = $f1;
83            let f2 = $f2;
84            $crate::runtime::pin_mut!(f1, f2);
85            let (mut s1, mut s2) = (None, None);
86            ::core::future::poll_fn(|cx| {
87                if s1.is_none() { if let ::core::task::Poll::Ready(v) = f1.as_mut().poll(cx) {
88                    match v { Ok(v) => s1 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
89                }}
90                if s2.is_none() { if let ::core::task::Poll::Ready(v) = f2.as_mut().poll(cx) {
91                    match v { Ok(v) => s2 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
92                }}
93                if s1.is_some() && s2.is_some() {
94                    ::core::task::Poll::Ready(Ok((s1.take().unwrap(), s2.take().unwrap())))
95                } else { ::core::task::Poll::Pending }
96            }).await
97        }
98    };
99    ($f1:expr, $f2:expr, $f3:expr $(,)?) => {
100        async {
101            use ::core::future::Future;
102            let f1 = $f1;
103            let f2 = $f2;
104            let f3 = $f3;
105            $crate::runtime::pin_mut!(f1, f2, f3);
106            let (mut s1, mut s2, mut s3) = (None, None, None);
107            ::core::future::poll_fn(|cx| {
108                if s1.is_none() { if let ::core::task::Poll::Ready(v) = f1.as_mut().poll(cx) {
109                    match v { Ok(v) => s1 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
110                }}
111                if s2.is_none() { if let ::core::task::Poll::Ready(v) = f2.as_mut().poll(cx) {
112                    match v { Ok(v) => s2 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
113                }}
114                if s3.is_none() { if let ::core::task::Poll::Ready(v) = f3.as_mut().poll(cx) {
115                    match v { Ok(v) => s3 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
116                }}
117                if s1.is_some() && s2.is_some() && s3.is_some() {
118                    ::core::task::Poll::Ready(Ok((s1.take().unwrap(), s2.take().unwrap(), s3.take().unwrap())))
119                } else { ::core::task::Poll::Pending }
120            }).await
121        }
122    };
123    ($f1:expr, $f2:expr, $f3:expr, $f4:expr $(,)?) => {
124        async {
125            use ::core::future::Future;
126            let f1 = $f1;
127            let f2 = $f2;
128            let f3 = $f3;
129            let f4 = $f4;
130            $crate::runtime::pin_mut!(f1, f2, f3, f4);
131            let (mut s1, mut s2, mut s3, mut s4) = (None, None, None, None);
132            ::core::future::poll_fn(|cx| {
133                if s1.is_none() { if let ::core::task::Poll::Ready(v) = f1.as_mut().poll(cx) {
134                    match v { Ok(v) => s1 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
135                }}
136                if s2.is_none() { if let ::core::task::Poll::Ready(v) = f2.as_mut().poll(cx) {
137                    match v { Ok(v) => s2 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
138                }}
139                if s3.is_none() { if let ::core::task::Poll::Ready(v) = f3.as_mut().poll(cx) {
140                    match v { Ok(v) => s3 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
141                }}
142                if s4.is_none() { if let ::core::task::Poll::Ready(v) = f4.as_mut().poll(cx) {
143                    match v { Ok(v) => s4 = Some(v), Err(e) => return ::core::task::Poll::Ready(Err(e)) }
144                }}
145                if s1.is_some() && s2.is_some() && s3.is_some() && s4.is_some() {
146                    ::core::task::Poll::Ready(Ok((s1.take().unwrap(), s2.take().unwrap(), s3.take().unwrap(), s4.take().unwrap())))
147                } else { ::core::task::Poll::Pending }
148            }).await
149        }
150    };
151}