Skip to main content

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