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}