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}