1 //! The `select` macro.
2 
3 use proc_macro_hack::proc_macro_hack;
4 
5 macro_rules! document_select_macro {
6     // This branch is required for `futures 0.3.1`, from before select_biased was introduced
7     ($select:item) => {
8         /// Polls multiple futures and streams simultaneously, executing the branch
9         /// for the future that finishes first. If multiple futures are ready,
10         /// one will be pseudo-randomly selected at runtime. Futures directly
11         /// passed to `select!` must be `Unpin` and implement `FusedFuture`.
12         ///
13         /// If an expression which yields a `Future` is passed to `select!`
14         /// (e.g. an `async fn` call) instead of a `Future` by name the `Unpin`
15         /// requirement is relaxed, since the macro will pin the resulting `Future`
16         /// on the stack. However the `Future` returned by the expression must
17         /// still implement `FusedFuture`.
18         ///
19         /// Futures and streams which are not already fused can be fused using the
20         /// `.fuse()` method. Note, though, that fusing a future or stream directly
21         /// in the call to `select!` will not be enough to prevent it from being
22         /// polled after completion if the `select!` call is in a loop, so when
23         /// `select!`ing in a loop, users should take care to `fuse()` outside of
24         /// the loop.
25         ///
26         /// `select!` can be used as an expression and will return the return
27         /// value of the selected branch. For this reason the return type of every
28         /// branch in a `select!` must be the same.
29         ///
30         /// This macro is only usable inside of async functions, closures, and blocks.
31         /// It is also gated behind the `async-await` feature of this library, which is
32         /// activated by default.
33         ///
34         /// Note that `select!` relies on `proc-macro-hack`, and may require to set the
35         /// compiler's recursion limit very high, e.g. `#![recursion_limit="1024"]`.
36         ///
37         /// # Examples
38         ///
39         /// ```
40         /// # futures::executor::block_on(async {
41         /// use futures::future;
42         /// use futures::select;
43         /// let mut a = future::ready(4);
44         /// let mut b = future::pending::<()>();
45         ///
46         /// let res = select! {
47         ///     a_res = a => a_res + 1,
48         ///     _ = b => 0,
49         /// };
50         /// assert_eq!(res, 5);
51         /// # });
52         /// ```
53         ///
54         /// ```
55         /// # futures::executor::block_on(async {
56         /// use futures::future;
57         /// use futures::stream::{self, StreamExt};
58         /// use futures::select;
59         /// let mut st = stream::iter(vec![2]).fuse();
60         /// let mut fut = future::pending::<()>();
61         ///
62         /// select! {
63         ///     x = st.next() => assert_eq!(Some(2), x),
64         ///     _ = fut => panic!(),
65         /// };
66         /// # });
67         /// ```
68         ///
69         /// As described earlier, `select` can directly select on expressions
70         /// which return `Future`s - even if those do not implement `Unpin`:
71         ///
72         /// ```
73         /// # futures::executor::block_on(async {
74         /// use futures::future::FutureExt;
75         /// use futures::select;
76         ///
77         /// // Calling the following async fn returns a Future which does not
78         /// // implement Unpin
79         /// async fn async_identity_fn(arg: usize) -> usize {
80         ///     arg
81         /// }
82         ///
83         /// let res = select! {
84         ///     a_res = async_identity_fn(62).fuse() => a_res + 1,
85         ///     b_res = async_identity_fn(13).fuse() => b_res,
86         /// };
87         /// assert!(res == 63 || res == 13);
88         /// # });
89         /// ```
90         ///
91         /// If a similar async function is called outside of `select` to produce
92         /// a `Future`, the `Future` must be pinned in order to be able to pass
93         /// it to `select`. This can be achieved via `Box::pin` for pinning a
94         /// `Future` on the heap or the `pin_mut!` macro for pinning a `Future`
95         /// on the stack.
96         ///
97         /// ```
98         /// # futures::executor::block_on(async {
99         /// use futures::future::FutureExt;
100         /// use futures::select;
101         /// use futures::pin_mut;
102         ///
103         /// // Calling the following async fn returns a Future which does not
104         /// // implement Unpin
105         /// async fn async_identity_fn(arg: usize) -> usize {
106         ///     arg
107         /// }
108         ///
109         /// let fut_1 = async_identity_fn(1).fuse();
110         /// let fut_2 = async_identity_fn(2).fuse();
111         /// let mut fut_1 = Box::pin(fut_1); // Pins the Future on the heap
112         /// pin_mut!(fut_2); // Pins the Future on the stack
113         ///
114         /// let res = select! {
115         ///     a_res = fut_1 => a_res,
116         ///     b_res = fut_2 => b_res,
117         /// };
118         /// assert!(res == 1 || res == 2);
119         /// # });
120         /// ```
121         ///
122         /// `select` also accepts a `complete` branch and a `default` branch.
123         /// `complete` will run if all futures and streams have already been
124         /// exhausted. `default` will run if no futures or streams are
125         /// immediately ready. `complete` takes priority over `default` in
126         /// the case where all futures have completed.
127         /// A motivating use-case for passing `Future`s by name as well as for
128         /// `complete` blocks is to call `select!` in a loop, which is
129         /// demonstrated in the following example:
130         ///
131         /// ```
132         /// # futures::executor::block_on(async {
133         /// use futures::future;
134         /// use futures::select;
135         /// let mut a_fut = future::ready(4);
136         /// let mut b_fut = future::ready(6);
137         /// let mut total = 0;
138         ///
139         /// loop {
140         ///     select! {
141         ///         a = a_fut => total += a,
142         ///         b = b_fut => total += b,
143         ///         complete => break,
144         ///         default => panic!(), // never runs (futures run first, then complete)
145         ///     };
146         /// }
147         /// assert_eq!(total, 10);
148         /// # });
149         /// ```
150         ///
151         /// Note that the futures that have been matched over can still be mutated
152         /// from inside the `select!` block's branches. This can be used to implement
153         /// more complex behavior such as timer resets or writing into the head of
154         /// a stream.
155         $select
156     };
157 
158     ($select:item $select_biased:item) => {
159         document_select_macro!($select);
160 
161         /// Polls multiple futures and streams simultaneously, executing the branch
162         /// for the future that finishes first. Unlike [`select!`], if multiple futures are ready,
163         /// one will be selected in order of declaration. Futures directly
164         /// passed to `select_biased!` must be `Unpin` and implement `FusedFuture`.
165         ///
166         /// If an expression which yields a `Future` is passed to `select_biased!`
167         /// (e.g. an `async fn` call) instead of a `Future` by name the `Unpin`
168         /// requirement is relaxed, since the macro will pin the resulting `Future`
169         /// on the stack. However the `Future` returned by the expression must
170         /// still implement `FusedFuture`.
171         ///
172         /// Futures and streams which are not already fused can be fused using the
173         /// `.fuse()` method. Note, though, that fusing a future or stream directly
174         /// in the call to `select_biased!` will not be enough to prevent it from being
175         /// polled after completion if the `select_biased!` call is in a loop, so when
176         /// `select_biased!`ing in a loop, users should take care to `fuse()` outside of
177         /// the loop.
178         ///
179         /// `select_biased!` can be used as an expression and will return the return
180         /// value of the selected branch. For this reason the return type of every
181         /// branch in a `select_biased!` must be the same.
182         ///
183         /// This macro is only usable inside of async functions, closures, and blocks.
184         /// It is also gated behind the `async-await` feature of this library, which is
185         /// activated by default.
186         ///
187         /// # Examples
188         ///
189         /// ```
190         /// # futures::executor::block_on(async {
191         /// use futures::future;
192         /// use futures::select_biased;
193         /// let mut a = future::ready(4);
194         /// let mut b = future::pending::<()>();
195         ///
196         /// let res = select_biased! {
197         ///     a_res = a => a_res + 1,
198         ///     _ = b => 0,
199         /// };
200         /// assert_eq!(res, 5);
201         /// # });
202         /// ```
203         ///
204         /// ```
205         /// # futures::executor::block_on(async {
206         /// use futures::future;
207         /// use futures::stream::{self, StreamExt};
208         /// use futures::select_biased;
209         /// let mut st = stream::iter(vec![2]).fuse();
210         /// let mut fut = future::pending::<()>();
211         ///
212         /// select_biased! {
213         ///     x = st.next() => assert_eq!(Some(2), x),
214         ///     _ = fut => panic!(),
215         /// };
216         /// # });
217         /// ```
218         ///
219         /// As described earlier, `select_biased` can directly select on expressions
220         /// which return `Future`s - even if those do not implement `Unpin`:
221         ///
222         /// ```
223         /// # futures::executor::block_on(async {
224         /// use futures::future::FutureExt;
225         /// use futures::select_biased;
226         ///
227         /// // Calling the following async fn returns a Future which does not
228         /// // implement Unpin
229         /// async fn async_identity_fn(arg: usize) -> usize {
230         ///     arg
231         /// }
232         ///
233         /// let res = select_biased! {
234         ///     a_res = async_identity_fn(62).fuse() => a_res + 1,
235         ///     b_res = async_identity_fn(13).fuse() => b_res,
236         /// };
237         /// assert!(res == 63 || res == 12);
238         /// # });
239         /// ```
240         ///
241         /// If a similar async function is called outside of `select_biased` to produce
242         /// a `Future`, the `Future` must be pinned in order to be able to pass
243         /// it to `select_biased`. This can be achieved via `Box::pin` for pinning a
244         /// `Future` on the heap or the `pin_mut!` macro for pinning a `Future`
245         /// on the stack.
246         ///
247         /// ```
248         /// # futures::executor::block_on(async {
249         /// use futures::future::FutureExt;
250         /// use futures::select_biased;
251         /// use futures::pin_mut;
252         ///
253         /// // Calling the following async fn returns a Future which does not
254         /// // implement Unpin
255         /// async fn async_identity_fn(arg: usize) -> usize {
256         ///     arg
257         /// }
258         ///
259         /// let fut_1 = async_identity_fn(1).fuse();
260         /// let fut_2 = async_identity_fn(2).fuse();
261         /// let mut fut_1 = Box::pin(fut_1); // Pins the Future on the heap
262         /// pin_mut!(fut_2); // Pins the Future on the stack
263         ///
264         /// let res = select_biased! {
265         ///     a_res = fut_1 => a_res,
266         ///     b_res = fut_2 => b_res,
267         /// };
268         /// assert!(res == 1 || res == 2);
269         /// # });
270         /// ```
271         ///
272         /// `select_biased` also accepts a `complete` branch and a `default` branch.
273         /// `complete` will run if all futures and streams have already been
274         /// exhausted. `default` will run if no futures or streams are
275         /// immediately ready. `complete` takes priority over `default` in
276         /// the case where all futures have completed.
277         /// A motivating use-case for passing `Future`s by name as well as for
278         /// `complete` blocks is to call `select_biased!` in a loop, which is
279         /// demonstrated in the following example:
280         ///
281         /// ```
282         /// # futures::executor::block_on(async {
283         /// use futures::future;
284         /// use futures::select_biased;
285         /// let mut a_fut = future::ready(4);
286         /// let mut b_fut = future::ready(6);
287         /// let mut total = 0;
288         ///
289         /// loop {
290         ///     select_biased! {
291         ///         a = a_fut => total += a,
292         ///         b = b_fut => total += b,
293         ///         complete => break,
294         ///         default => panic!(), // never runs (futures run first, then complete)
295         ///     };
296         /// }
297         /// assert_eq!(total, 10);
298         /// # });
299         /// ```
300         ///
301         /// Note that the futures that have been matched over can still be mutated
302         /// from inside the `select_biased!` block's branches. This can be used to implement
303         /// more complex behavior such as timer resets or writing into the head of
304         /// a stream.
305         ///
306         /// [`select!`]: macro.select.html
307         $select_biased
308     };
309 }
310 
311 #[cfg(feature = "std")]
312 #[doc(hidden)]
313 #[proc_macro_hack(support_nested, only_hack_old_rustc)]
314 pub use futures_macro::select_internal;
315 
316 #[doc(hidden)]
317 #[proc_macro_hack(support_nested, only_hack_old_rustc)]
318 pub use futures_macro::select_biased_internal;
319 
320 document_select_macro! {
321     #[cfg(feature = "std")]
322     #[macro_export]
323     macro_rules! select {
324         ($($tokens:tt)*) => {{
325             use $crate::__private as __futures_crate;
326             $crate::select_internal! {
327                 $( $tokens )*
328             }
329         }}
330     }
331 
332     #[macro_export]
333     macro_rules! select_biased {
334         ($($tokens:tt)*) => {{
335             use $crate::__private as __futures_crate;
336             $crate::select_biased_internal! {
337                 $( $tokens )*
338             }
339         }}
340     }
341 }
342