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}