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 | #[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)] |
311 | pub use futures_macro::select_internal; |
312 | |
313 | #[allow (unreachable_pub)] |
314 | #[doc (hidden)] |
315 | pub use futures_macro::select_biased_internal; |
316 | |
317 | document_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 | } |
339 | |