1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! The `select` macro.

/// Polls multiple futures simultaneously, executing the branch for the future 
/// that finishes first.
/// 
/// `select!` can select over futures with different output types, but each 
/// branch has to have the same return type. Inside each branch, the respective 
/// future's output is available via a variable with the same name as the future.
/// 
/// This macro is only usable inside of async functions, closures, and blocks.
/// 
/// # Examples
/// 
/// ```
/// #![feature(pin, async_await, await_macro, futures_api)]
/// # futures::executor::block_on(async {
/// use futures::{select, future};
/// let mut a = future::ready(4);
/// let mut b: future::Empty<()> = future::empty();
/// 
/// let res = select! {
///     a => a + 1,
///     b => 0,
/// };
/// assert_eq!(res, 5);
/// # });
/// ```
#[macro_export]
macro_rules! select {
    () => {
        compile_error!("The `select!` macro requires at least one branch")
    };
    ($(
        $name:ident => $body:expr,
    )*) => { {
        $(
            $crate::async_await::assert_unpin(&$name);
        )*
        #[allow(bad_style)]
        struct __priv<$($name,)*> {
            $(
                $name: $name,
            )*
        }
        let mut __priv_futures = __priv {
            $(
                $name: $crate::future::maybe_done(&mut $name),
            )*
        };
        loop {
            $(
                if let $crate::core_reexport::task::Poll::Ready(()) =
                    $crate::poll!($crate::core_reexport::mem::PinMut::new(
                        &mut __priv_futures.$name))
                {
                    break;
                }
            )*
            $crate::pending!();
        }
        if false {
            unreachable!()
        }
        $(
            else if let Some($name) =
                $crate::core_reexport::mem::PinMut::new(&mut __priv_futures.$name).take_output()
            {
                let _ = $name; // suppress "unused" warning for binding name
                $body
            }
        )*
        else {
            unreachable!()
        }
    } };
}