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