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
//! 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,
    )*) => { {
        // Require all arguments to be `Unpin` so that we don't have to pin them,
        // allowing uncompleted futures to be reused by the caller after the
        // `select!` resolves.
        $(
            $crate::async_await::assert_unpin(&$name);
        )*

        #[allow(bad_style)]
        enum __PrivResult<$($name,)*> {
            $(
                $name($name),
            )*
        }

        let __priv_res = await!($crate::future::poll_fn(|cx| {
            $(
                match $crate::core_reexport::future::Future::poll(
                    $crate::core_reexport::mem::PinMut::new(&mut $name), cx)
                {
                    $crate::core_reexport::task::Poll::Ready(x) =>
                        return $crate::core_reexport::task::Poll::Ready(__PrivResult::$name(x)),
                    $crate::core_reexport::task::Poll::Pending => {},
                }
            )*
            $crate::core_reexport::task::Poll::Pending
        }));
        match __priv_res {
            $(
                __PrivResult::$name($name) => {
                    let _ = $name; // Suppress "unused" warning for binding name
                    $body
                }
            )*
        }
    } };
}