async_macros/
select.rs

1#![allow(non_snake_case)]
2
3/// Waits for either one of several similarly-typed futures to complete.
4///
5/// Awaits multiple futures simultaneously, returning all results once complete.
6///
7/// This function will return a new future which awaits for either one of both
8/// futures to complete. If multiple futures are completed at the same time,
9/// resolution will occur in the order that they have been passed.
10///
11/// Note that this macro consumes all futures passed, and once a future is
12/// completed, all other futures are dropped.
13///
14/// This macro is only usable inside of async functions, closures, and blocks.
15///
16/// # Examples
17///
18/// ```
19/// #![feature(async_await)]
20/// # futures::executor::block_on(async {
21/// use async_macros::select;
22/// use futures::future;
23///
24/// let a = future::pending();
25/// let b = future::ready(1u8);
26/// let c = future::ready(2u8);
27///
28/// assert_eq!(select!(a, b, c).await, 1u8);
29/// # });
30/// ```
31#[macro_export]
32macro_rules! select {
33    ($($fut:ident),* $(,)?) => { {
34        async {
35            $(
36                // Move future into a local so that it is pinned in one place and
37                // is no longer accessible by the end user.
38                let mut $fut = $crate::MaybeDone::new($fut);
39            )*
40            $crate::utils::poll_fn(move |cx| {
41                use $crate::utils::future::Future;
42                use $crate::utils::task::Poll;
43                use $crate::utils::pin::Pin;
44
45                $(
46                    let fut = unsafe { Pin::new_unchecked(&mut $fut) };
47                    if Future::poll(fut, cx).is_ready() {
48                        let fut = unsafe { Pin::new_unchecked(&mut $fut) };
49                        let output = fut.take().unwrap();
50                        return Poll::Ready(output);
51                    }
52                )*
53
54                // If nothing matched we return Pending.
55                Poll::Pending
56            }).await
57        }
58    } }
59}