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