futures_util/async_await/
select_mod.rs

1//! The `select` macro.
2
3macro_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)]
311pub use futures_macro::select_internal;
312
313#[allow(unreachable_pub)]
314#[doc(hidden)]
315pub use futures_macro::select_biased_internal;
316
317document_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}