1 | //! Combinators for the [`Future`] trait. |
2 | //! |
3 | //! # Examples |
4 | //! |
5 | //! ``` |
6 | //! use futures_lite::future; |
7 | //! |
8 | //! # spin_on::spin_on(async { |
9 | //! for step in 0..3 { |
10 | //! println!("step {}" , step); |
11 | //! |
12 | //! // Give other tasks a chance to run. |
13 | //! future::yield_now().await; |
14 | //! } |
15 | //! # }); |
16 | //! ``` |
17 | |
18 | #[cfg (all(not(feature = "std" ), feature = "alloc" ))] |
19 | extern crate alloc; |
20 | |
21 | #[doc (no_inline)] |
22 | pub use core::future::{pending, ready, Future, Pending, Ready}; |
23 | |
24 | use core::fmt; |
25 | use core::pin::Pin; |
26 | |
27 | use pin_project_lite::pin_project; |
28 | |
29 | #[cfg (feature = "std" )] |
30 | use std::{ |
31 | any::Any, |
32 | panic::{catch_unwind, AssertUnwindSafe, UnwindSafe}, |
33 | }; |
34 | |
35 | #[cfg (feature = "race" )] |
36 | use fastrand::Rng; |
37 | |
38 | #[cfg (all(not(feature = "std" ), feature = "alloc" ))] |
39 | use alloc::boxed::Box; |
40 | use core::task::{Context, Poll}; |
41 | |
42 | /// Blocks the current thread on a future. |
43 | /// |
44 | /// # Examples |
45 | /// |
46 | /// ``` |
47 | /// use futures_lite::future; |
48 | /// |
49 | /// let val = future::block_on(async { |
50 | /// 1 + 2 |
51 | /// }); |
52 | /// |
53 | /// assert_eq!(val, 3); |
54 | /// ``` |
55 | #[cfg (feature = "std" )] |
56 | pub fn block_on<T>(future: impl Future<Output = T>) -> T { |
57 | use core::cell::RefCell; |
58 | use core::task::Waker; |
59 | |
60 | use parking::Parker; |
61 | |
62 | // Pin the future on the stack. |
63 | crate::pin!(future); |
64 | |
65 | // Creates a parker and an associated waker that unparks it. |
66 | fn parker_and_waker() -> (Parker, Waker) { |
67 | let parker = Parker::new(); |
68 | let unparker = parker.unparker(); |
69 | let waker = Waker::from(unparker); |
70 | (parker, waker) |
71 | } |
72 | |
73 | thread_local! { |
74 | // Cached parker and waker for efficiency. |
75 | static CACHE: RefCell<(Parker, Waker)> = RefCell::new(parker_and_waker()); |
76 | } |
77 | |
78 | CACHE.with(|cache| { |
79 | // Try grabbing the cached parker and waker. |
80 | let tmp_cached; |
81 | let tmp_fresh; |
82 | let (parker, waker) = match cache.try_borrow_mut() { |
83 | Ok(cache) => { |
84 | // Use the cached parker and waker. |
85 | tmp_cached = cache; |
86 | &*tmp_cached |
87 | } |
88 | Err(_) => { |
89 | // Looks like this is a recursive `block_on()` call. |
90 | // Create a fresh parker and waker. |
91 | tmp_fresh = parker_and_waker(); |
92 | &tmp_fresh |
93 | } |
94 | }; |
95 | |
96 | let cx = &mut Context::from_waker(waker); |
97 | // Keep polling until the future is ready. |
98 | loop { |
99 | match future.as_mut().poll(cx) { |
100 | Poll::Ready(output) => return output, |
101 | Poll::Pending => parker.park(), |
102 | } |
103 | } |
104 | }) |
105 | } |
106 | |
107 | /// Polls a future just once and returns an [`Option`] with the result. |
108 | /// |
109 | /// # Examples |
110 | /// |
111 | /// ``` |
112 | /// use futures_lite::future; |
113 | /// |
114 | /// # spin_on::spin_on(async { |
115 | /// assert_eq!(future::poll_once(future::pending::<()>()).await, None); |
116 | /// assert_eq!(future::poll_once(future::ready(42)).await, Some(42)); |
117 | /// # }) |
118 | /// ``` |
119 | pub fn poll_once<T, F>(f: F) -> PollOnce<F> |
120 | where |
121 | F: Future<Output = T>, |
122 | { |
123 | PollOnce { f } |
124 | } |
125 | |
126 | pin_project! { |
127 | /// Future for the [`poll_once()`] function. |
128 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
129 | pub struct PollOnce<F> { |
130 | #[pin] |
131 | f: F, |
132 | } |
133 | } |
134 | |
135 | impl<F> fmt::Debug for PollOnce<F> { |
136 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
137 | f.debug_struct(name:"PollOnce" ).finish() |
138 | } |
139 | } |
140 | |
141 | impl<T, F> Future for PollOnce<F> |
142 | where |
143 | F: Future<Output = T>, |
144 | { |
145 | type Output = Option<T>; |
146 | |
147 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
148 | match self.project().f.poll(cx) { |
149 | Poll::Ready(t: T) => Poll::Ready(Some(t)), |
150 | Poll::Pending => Poll::Ready(None), |
151 | } |
152 | } |
153 | } |
154 | |
155 | /// Creates a future from a function returning [`Poll`]. |
156 | /// |
157 | /// # Examples |
158 | /// |
159 | /// ``` |
160 | /// use futures_lite::future; |
161 | /// use std::task::{Context, Poll}; |
162 | /// |
163 | /// # spin_on::spin_on(async { |
164 | /// fn f(_: &mut Context<'_>) -> Poll<i32> { |
165 | /// Poll::Ready(7) |
166 | /// } |
167 | /// |
168 | /// assert_eq!(future::poll_fn(f).await, 7); |
169 | /// # }) |
170 | /// ``` |
171 | pub fn poll_fn<T, F>(f: F) -> PollFn<F> |
172 | where |
173 | F: FnMut(&mut Context<'_>) -> Poll<T>, |
174 | { |
175 | PollFn { f } |
176 | } |
177 | |
178 | pin_project! { |
179 | /// Future for the [`poll_fn()`] function. |
180 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
181 | pub struct PollFn<F> { |
182 | f: F, |
183 | } |
184 | } |
185 | |
186 | impl<F> fmt::Debug for PollFn<F> { |
187 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
188 | f.debug_struct(name:"PollFn" ).finish() |
189 | } |
190 | } |
191 | |
192 | impl<T, F> Future for PollFn<F> |
193 | where |
194 | F: FnMut(&mut Context<'_>) -> Poll<T>, |
195 | { |
196 | type Output = T; |
197 | |
198 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> { |
199 | let this: Projection<'_, F> = self.project(); |
200 | (this.f)(cx) |
201 | } |
202 | } |
203 | |
204 | /// Wakes the current task and returns [`Poll::Pending`] once. |
205 | /// |
206 | /// This function is useful when we want to cooperatively give time to the task scheduler. It is |
207 | /// generally a good idea to yield inside loops because that way we make sure long-running tasks |
208 | /// don't prevent other tasks from running. |
209 | /// |
210 | /// # Examples |
211 | /// |
212 | /// ``` |
213 | /// use futures_lite::future; |
214 | /// |
215 | /// # spin_on::spin_on(async { |
216 | /// future::yield_now().await; |
217 | /// # }) |
218 | /// ``` |
219 | pub fn yield_now() -> YieldNow { |
220 | YieldNow(false) |
221 | } |
222 | |
223 | /// Future for the [`yield_now()`] function. |
224 | #[derive (Debug)] |
225 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
226 | pub struct YieldNow(bool); |
227 | |
228 | impl Future for YieldNow { |
229 | type Output = (); |
230 | |
231 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
232 | if !self.0 { |
233 | self.0 = true; |
234 | cx.waker().wake_by_ref(); |
235 | Poll::Pending |
236 | } else { |
237 | Poll::Ready(()) |
238 | } |
239 | } |
240 | } |
241 | |
242 | /// Joins two futures, waiting for both to complete. |
243 | /// |
244 | /// # Examples |
245 | /// |
246 | /// ``` |
247 | /// use futures_lite::future; |
248 | /// |
249 | /// # spin_on::spin_on(async { |
250 | /// let a = async { 1 }; |
251 | /// let b = async { 2 }; |
252 | /// |
253 | /// assert_eq!(future::zip(a, b).await, (1, 2)); |
254 | /// # }) |
255 | /// ``` |
256 | pub fn zip<F1, F2>(future1: F1, future2: F2) -> Zip<F1, F2> |
257 | where |
258 | F1: Future, |
259 | F2: Future, |
260 | { |
261 | Zip { |
262 | future1: Some(future1), |
263 | future2: Some(future2), |
264 | output1: None, |
265 | output2: None, |
266 | } |
267 | } |
268 | |
269 | pin_project! { |
270 | /// Future for the [`zip()`] function. |
271 | #[derive (Debug)] |
272 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
273 | pub struct Zip<F1, F2> |
274 | where |
275 | F1: Future, |
276 | F2: Future, |
277 | { |
278 | #[pin] |
279 | future1: Option<F1>, |
280 | output1: Option<F1::Output>, |
281 | #[pin] |
282 | future2: Option<F2>, |
283 | output2: Option<F2::Output>, |
284 | } |
285 | } |
286 | |
287 | /// Extracts the contents of two options and zips them, handling `(Some(_), None)` cases |
288 | fn take_zip_from_parts<T1, T2>(o1: &mut Option<T1>, o2: &mut Option<T2>) -> Poll<(T1, T2)> { |
289 | match (o1.take(), o2.take()) { |
290 | (Some(t1: T1), Some(t2: T2)) => Poll::Ready((t1, t2)), |
291 | (o1x: Option, o2x: Option) => { |
292 | *o1 = o1x; |
293 | *o2 = o2x; |
294 | Poll::Pending |
295 | } |
296 | } |
297 | } |
298 | |
299 | impl<F1, F2> Future for Zip<F1, F2> |
300 | where |
301 | F1: Future, |
302 | F2: Future, |
303 | { |
304 | type Output = (F1::Output, F2::Output); |
305 | |
306 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
307 | let mut this: Projection<'_, F1, F2> = self.project(); |
308 | |
309 | if let Some(future: Pin<&mut F1>) = this.future1.as_mut().as_pin_mut() { |
310 | if let Poll::Ready(out: ::Output) = future.poll(cx) { |
311 | *this.output1 = Some(out); |
312 | this.future1.set(None); |
313 | } |
314 | } |
315 | |
316 | if let Some(future: Pin<&mut F2>) = this.future2.as_mut().as_pin_mut() { |
317 | if let Poll::Ready(out: ::Output) = future.poll(cx) { |
318 | *this.output2 = Some(out); |
319 | this.future2.set(None); |
320 | } |
321 | } |
322 | |
323 | take_zip_from_parts(o1:this.output1, o2:this.output2) |
324 | } |
325 | } |
326 | |
327 | /// Joins two fallible futures, waiting for both to complete or one of them to error. |
328 | /// |
329 | /// # Examples |
330 | /// |
331 | /// ``` |
332 | /// use futures_lite::future; |
333 | /// |
334 | /// # spin_on::spin_on(async { |
335 | /// let a = async { Ok::<i32, i32>(1) }; |
336 | /// let b = async { Err::<i32, i32>(2) }; |
337 | /// |
338 | /// assert_eq!(future::try_zip(a, b).await, Err(2)); |
339 | /// # }) |
340 | /// ``` |
341 | pub fn try_zip<T1, T2, E, F1, F2>(future1: F1, future2: F2) -> TryZip<F1, T1, F2, T2> |
342 | where |
343 | F1: Future<Output = Result<T1, E>>, |
344 | F2: Future<Output = Result<T2, E>>, |
345 | { |
346 | TryZip { |
347 | future1: Some(future1), |
348 | future2: Some(future2), |
349 | output1: None, |
350 | output2: None, |
351 | } |
352 | } |
353 | |
354 | pin_project! { |
355 | /// Future for the [`try_zip()`] function. |
356 | #[derive (Debug)] |
357 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
358 | pub struct TryZip<F1, T1, F2, T2> { |
359 | #[pin] |
360 | future1: Option<F1>, |
361 | output1: Option<T1>, |
362 | #[pin] |
363 | future2: Option<F2>, |
364 | output2: Option<T2>, |
365 | } |
366 | } |
367 | |
368 | impl<T1, T2, E, F1, F2> Future for TryZip<F1, T1, F2, T2> |
369 | where |
370 | F1: Future<Output = Result<T1, E>>, |
371 | F2: Future<Output = Result<T2, E>>, |
372 | { |
373 | type Output = Result<(T1, T2), E>; |
374 | |
375 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
376 | let mut this = self.project(); |
377 | |
378 | if let Some(future) = this.future1.as_mut().as_pin_mut() { |
379 | if let Poll::Ready(out) = future.poll(cx) { |
380 | match out { |
381 | Ok(t) => { |
382 | *this.output1 = Some(t); |
383 | this.future1.set(None); |
384 | } |
385 | Err(err) => return Poll::Ready(Err(err)), |
386 | } |
387 | } |
388 | } |
389 | |
390 | if let Some(future) = this.future2.as_mut().as_pin_mut() { |
391 | if let Poll::Ready(out) = future.poll(cx) { |
392 | match out { |
393 | Ok(t) => { |
394 | *this.output2 = Some(t); |
395 | this.future2.set(None); |
396 | } |
397 | Err(err) => return Poll::Ready(Err(err)), |
398 | } |
399 | } |
400 | } |
401 | |
402 | take_zip_from_parts(this.output1, this.output2).map(Ok) |
403 | } |
404 | } |
405 | |
406 | /// Returns the result of the future that completes first, preferring `future1` if both are ready. |
407 | /// |
408 | /// If you need to treat the two futures fairly without a preference for either, use the [`race()`] |
409 | /// function or the [`FutureExt::race()`] method. |
410 | /// |
411 | /// # Examples |
412 | /// |
413 | /// ``` |
414 | /// use futures_lite::future::{self, pending, ready}; |
415 | /// |
416 | /// # spin_on::spin_on(async { |
417 | /// assert_eq!(future::or(ready(1), pending()).await, 1); |
418 | /// assert_eq!(future::or(pending(), ready(2)).await, 2); |
419 | /// |
420 | /// // The first future wins. |
421 | /// assert_eq!(future::or(ready(1), ready(2)).await, 1); |
422 | /// # }) |
423 | /// ``` |
424 | pub fn or<T, F1, F2>(future1: F1, future2: F2) -> Or<F1, F2> |
425 | where |
426 | F1: Future<Output = T>, |
427 | F2: Future<Output = T>, |
428 | { |
429 | Or { future1, future2 } |
430 | } |
431 | |
432 | pin_project! { |
433 | /// Future for the [`or()`] function and the [`FutureExt::or()`] method. |
434 | #[derive (Debug)] |
435 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
436 | pub struct Or<F1, F2> { |
437 | #[pin] |
438 | future1: F1, |
439 | #[pin] |
440 | future2: F2, |
441 | } |
442 | } |
443 | |
444 | impl<T, F1, F2> Future for Or<F1, F2> |
445 | where |
446 | F1: Future<Output = T>, |
447 | F2: Future<Output = T>, |
448 | { |
449 | type Output = T; |
450 | |
451 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
452 | let this: Projection<'_, F1, F2> = self.project(); |
453 | |
454 | if let Poll::Ready(t: T) = this.future1.poll(cx) { |
455 | return Poll::Ready(t); |
456 | } |
457 | if let Poll::Ready(t: T) = this.future2.poll(cx) { |
458 | return Poll::Ready(t); |
459 | } |
460 | Poll::Pending |
461 | } |
462 | } |
463 | |
464 | /// Fuse a future such that `poll` will never again be called once it has |
465 | /// completed. This method can be used to turn any `Future` into a |
466 | /// `FusedFuture`. |
467 | /// |
468 | /// Normally, once a future has returned `Poll::Ready` from `poll`, |
469 | /// any further calls could exhibit bad behavior such as blocking |
470 | /// forever, panicking, never returning, etc. If it is known that `poll` |
471 | /// may be called too often then this method can be used to ensure that it |
472 | /// has defined semantics. |
473 | /// |
474 | /// If a `fuse`d future is `poll`ed after having returned `Poll::Ready` |
475 | /// previously, it will return `Poll::Pending`, from `poll` again (and will |
476 | /// continue to do so for all future calls to `poll`). |
477 | /// |
478 | /// This combinator will drop the underlying future as soon as it has been |
479 | /// completed to ensure resources are reclaimed as soon as possible. |
480 | pub fn fuse<F>(future: F) -> Fuse<F> |
481 | where |
482 | F: Future + Sized, |
483 | { |
484 | Fuse::new(future) |
485 | } |
486 | |
487 | pin_project! { |
488 | /// [`Future`] for the [`fuse`] method. |
489 | #[derive (Debug)] |
490 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
491 | pub struct Fuse<Fut> { |
492 | #[pin] |
493 | inner: Option<Fut>, |
494 | } |
495 | } |
496 | |
497 | impl<Fut> Fuse<Fut> { |
498 | fn new(f: Fut) -> Self { |
499 | Self { inner: Some(f) } |
500 | } |
501 | } |
502 | |
503 | impl<Fut: Future> Future for Fuse<Fut> { |
504 | type Output = Fut::Output; |
505 | |
506 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Fut::Output> { |
507 | match self |
508 | .as_mut() |
509 | .project() |
510 | .inner |
511 | .as_pin_mut() |
512 | .map(|f: Pin<&mut Fut>| f.poll(cx)) |
513 | { |
514 | Some(Poll::Ready(output: ::Output)) => { |
515 | self.project().inner.set(None); |
516 | Poll::Ready(output) |
517 | } |
518 | |
519 | Some(Poll::Pending) | None => Poll::Pending, |
520 | } |
521 | } |
522 | } |
523 | |
524 | /// Returns the result of the future that completes first, with no preference if both are ready. |
525 | /// |
526 | /// Each time [`Race`] is polled, the two inner futures are polled in random order. Therefore, no |
527 | /// future takes precedence over the other if both can complete at the same time. |
528 | /// |
529 | /// If you have preference for one of the futures, use the [`or()`] function or the |
530 | /// [`FutureExt::or()`] method. |
531 | /// |
532 | /// # Examples |
533 | /// |
534 | /// ``` |
535 | /// use futures_lite::future::{self, pending, ready}; |
536 | /// |
537 | /// # spin_on::spin_on(async { |
538 | /// assert_eq!(future::race(ready(1), pending()).await, 1); |
539 | /// assert_eq!(future::race(pending(), ready(2)).await, 2); |
540 | /// |
541 | /// // One of the two futures is randomly chosen as the winner. |
542 | /// let res = future::race(ready(1), ready(2)).await; |
543 | /// # }) |
544 | /// ``` |
545 | #[cfg (all(feature = "race" , feature = "std" ))] |
546 | pub fn race<T, F1, F2>(future1: F1, future2: F2) -> Race<F1, F2> |
547 | where |
548 | F1: Future<Output = T>, |
549 | F2: Future<Output = T>, |
550 | { |
551 | Race { |
552 | future1, |
553 | future2, |
554 | rng: Rng::new(), |
555 | } |
556 | } |
557 | |
558 | /// Race two futures but with a predefined random seed. |
559 | /// |
560 | /// This function is identical to [`race`], but instead of using a random seed from a thread-local |
561 | /// RNG, it allows the user to provide a seed. It is useful for when you already have a source of |
562 | /// randomness available, or if you want to use a fixed seed. |
563 | /// |
564 | /// See documentation of the [`race`] function for features and caveats. |
565 | /// |
566 | /// # Examples |
567 | /// |
568 | /// ``` |
569 | /// use futures_lite::future::{self, pending, ready}; |
570 | /// |
571 | /// // A fixed seed is used, so the result is deterministic. |
572 | /// const SEED: u64 = 0x42; |
573 | /// |
574 | /// # spin_on::spin_on(async { |
575 | /// assert_eq!(future::race_with_seed(ready(1), pending(), SEED).await, 1); |
576 | /// assert_eq!(future::race_with_seed(pending(), ready(2), SEED).await, 2); |
577 | /// |
578 | /// // One of the two futures is randomly chosen as the winner. |
579 | /// let res = future::race_with_seed(ready(1), ready(2), SEED).await; |
580 | /// # }) |
581 | /// ``` |
582 | #[cfg (feature = "race" )] |
583 | pub fn race_with_seed<T, F1, F2>(future1: F1, future2: F2, seed: u64) -> Race<F1, F2> |
584 | where |
585 | F1: Future<Output = T>, |
586 | F2: Future<Output = T>, |
587 | { |
588 | Race { |
589 | future1, |
590 | future2, |
591 | rng: Rng::with_seed(seed), |
592 | } |
593 | } |
594 | |
595 | #[cfg (feature = "race" )] |
596 | pin_project! { |
597 | /// Future for the [`race()`] function and the [`FutureExt::race()`] method. |
598 | #[derive (Debug)] |
599 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
600 | pub struct Race<F1, F2> { |
601 | #[pin] |
602 | future1: F1, |
603 | #[pin] |
604 | future2: F2, |
605 | rng: Rng, |
606 | } |
607 | } |
608 | |
609 | #[cfg (feature = "race" )] |
610 | impl<T, F1, F2> Future for Race<F1, F2> |
611 | where |
612 | F1: Future<Output = T>, |
613 | F2: Future<Output = T>, |
614 | { |
615 | type Output = T; |
616 | |
617 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
618 | let this: Projection<'_, F1, F2> = self.project(); |
619 | |
620 | if this.rng.bool() { |
621 | if let Poll::Ready(t: T) = this.future1.poll(cx) { |
622 | return Poll::Ready(t); |
623 | } |
624 | if let Poll::Ready(t: T) = this.future2.poll(cx) { |
625 | return Poll::Ready(t); |
626 | } |
627 | } else { |
628 | if let Poll::Ready(t: T) = this.future2.poll(cx) { |
629 | return Poll::Ready(t); |
630 | } |
631 | if let Poll::Ready(t: T) = this.future1.poll(cx) { |
632 | return Poll::Ready(t); |
633 | } |
634 | } |
635 | Poll::Pending |
636 | } |
637 | } |
638 | |
639 | #[cfg (feature = "std" )] |
640 | pin_project! { |
641 | /// Future for the [`FutureExt::catch_unwind()`] method. |
642 | #[derive (Debug)] |
643 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
644 | pub struct CatchUnwind<F> { |
645 | #[pin] |
646 | inner: F, |
647 | } |
648 | } |
649 | |
650 | #[cfg (feature = "std" )] |
651 | impl<F: Future + UnwindSafe> Future for CatchUnwind<F> { |
652 | type Output = Result<F::Output, Box<dyn Any + Send>>; |
653 | |
654 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
655 | let this: Projection<'_, F> = self.project(); |
656 | catch_unwind(AssertUnwindSafe(|| this.inner.poll(cx)))?.map(Ok) |
657 | } |
658 | } |
659 | |
660 | /// Type alias for `Pin<Box<dyn Future<Output = T> + Send + 'static>>`. |
661 | /// |
662 | /// # Examples |
663 | /// |
664 | /// ``` |
665 | /// use futures_lite::future::{self, FutureExt}; |
666 | /// |
667 | /// // These two lines are equivalent: |
668 | /// let f1: future::Boxed<i32> = async { 1 + 2 }.boxed(); |
669 | /// let f2: future::Boxed<i32> = Box::pin(async { 1 + 2 }); |
670 | /// ``` |
671 | #[cfg (feature = "alloc" )] |
672 | pub type Boxed<T> = Pin<Box<dyn Future<Output = T> + Send + 'static>>; |
673 | |
674 | /// Type alias for `Pin<Box<dyn Future<Output = T> + 'static>>`. |
675 | /// |
676 | /// # Examples |
677 | /// |
678 | /// ``` |
679 | /// use futures_lite::future::{self, FutureExt}; |
680 | /// |
681 | /// // These two lines are equivalent: |
682 | /// let f1: future::BoxedLocal<i32> = async { 1 + 2 }.boxed_local(); |
683 | /// let f2: future::BoxedLocal<i32> = Box::pin(async { 1 + 2 }); |
684 | /// ``` |
685 | #[cfg (feature = "alloc" )] |
686 | pub type BoxedLocal<T> = Pin<Box<dyn Future<Output = T> + 'static>>; |
687 | |
688 | /// Extension trait for [`Future`]. |
689 | pub trait FutureExt: Future { |
690 | /// A convenience for calling [`Future::poll()`] on `!`[`Unpin`] types. |
691 | fn poll(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output> |
692 | where |
693 | Self: Unpin, |
694 | { |
695 | Future::poll(Pin::new(self), cx) |
696 | } |
697 | |
698 | /// Returns the result of `self` or `other` future, preferring `self` if both are ready. |
699 | /// |
700 | /// If you need to treat the two futures fairly without a preference for either, use the |
701 | /// [`race()`] function or the [`FutureExt::race()`] method. |
702 | /// |
703 | /// # Examples |
704 | /// |
705 | /// ``` |
706 | /// use futures_lite::future::{pending, ready, FutureExt}; |
707 | /// |
708 | /// # spin_on::spin_on(async { |
709 | /// assert_eq!(ready(1).or(pending()).await, 1); |
710 | /// assert_eq!(pending().or(ready(2)).await, 2); |
711 | /// |
712 | /// // The first future wins. |
713 | /// assert_eq!(ready(1).or(ready(2)).await, 1); |
714 | /// # }) |
715 | /// ``` |
716 | fn or<F>(self, other: F) -> Or<Self, F> |
717 | where |
718 | Self: Sized, |
719 | F: Future<Output = Self::Output>, |
720 | { |
721 | Or { |
722 | future1: self, |
723 | future2: other, |
724 | } |
725 | } |
726 | |
727 | /// Returns the result of `self` or `other` future, with no preference if both are ready. |
728 | /// |
729 | /// Each time [`Race`] is polled, the two inner futures are polled in random order. Therefore, |
730 | /// no future takes precedence over the other if both can complete at the same time. |
731 | /// |
732 | /// If you have preference for one of the futures, use the [`or()`] function or the |
733 | /// [`FutureExt::or()`] method. |
734 | /// |
735 | /// # Examples |
736 | /// |
737 | /// ``` |
738 | /// use futures_lite::future::{pending, ready, FutureExt}; |
739 | /// |
740 | /// # spin_on::spin_on(async { |
741 | /// assert_eq!(ready(1).race(pending()).await, 1); |
742 | /// assert_eq!(pending().race(ready(2)).await, 2); |
743 | /// |
744 | /// // One of the two futures is randomly chosen as the winner. |
745 | /// let res = ready(1).race(ready(2)).await; |
746 | /// # }) |
747 | /// ``` |
748 | #[cfg (all(feature = "std" , feature = "race" ))] |
749 | fn race<F>(self, other: F) -> Race<Self, F> |
750 | where |
751 | Self: Sized, |
752 | F: Future<Output = Self::Output>, |
753 | { |
754 | Race { |
755 | future1: self, |
756 | future2: other, |
757 | rng: Rng::new(), |
758 | } |
759 | } |
760 | |
761 | /// Catches panics while polling the future. |
762 | /// |
763 | /// # Examples |
764 | /// |
765 | /// ``` |
766 | /// use futures_lite::future::FutureExt; |
767 | /// |
768 | /// # spin_on::spin_on(async { |
769 | /// let fut1 = async {}.catch_unwind(); |
770 | /// let fut2 = async { panic!() }.catch_unwind(); |
771 | /// |
772 | /// assert!(fut1.await.is_ok()); |
773 | /// assert!(fut2.await.is_err()); |
774 | /// # }) |
775 | /// ``` |
776 | #[cfg (feature = "std" )] |
777 | fn catch_unwind(self) -> CatchUnwind<Self> |
778 | where |
779 | Self: Sized + UnwindSafe, |
780 | { |
781 | CatchUnwind { inner: self } |
782 | } |
783 | |
784 | /// Boxes the future and changes its type to `dyn Future + Send + 'a`. |
785 | /// |
786 | /// # Examples |
787 | /// |
788 | /// ``` |
789 | /// use futures_lite::future::{self, FutureExt}; |
790 | /// |
791 | /// # spin_on::spin_on(async { |
792 | /// let a = future::ready('a' ); |
793 | /// let b = future::pending(); |
794 | /// |
795 | /// // Futures of different types can be stored in |
796 | /// // the same collection when they are boxed: |
797 | /// let futures = vec![a.boxed(), b.boxed()]; |
798 | /// # }) |
799 | /// ``` |
800 | #[cfg (feature = "alloc" )] |
801 | fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>> |
802 | where |
803 | Self: Sized + Send + 'a, |
804 | { |
805 | Box::pin(self) |
806 | } |
807 | |
808 | /// Boxes the future and changes its type to `dyn Future + 'a`. |
809 | /// |
810 | /// # Examples |
811 | /// |
812 | /// ``` |
813 | /// use futures_lite::future::{self, FutureExt}; |
814 | /// |
815 | /// # spin_on::spin_on(async { |
816 | /// let a = future::ready('a' ); |
817 | /// let b = future::pending(); |
818 | /// |
819 | /// // Futures of different types can be stored in |
820 | /// // the same collection when they are boxed: |
821 | /// let futures = vec![a.boxed_local(), b.boxed_local()]; |
822 | /// # }) |
823 | /// ``` |
824 | #[cfg (feature = "alloc" )] |
825 | fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>> |
826 | where |
827 | Self: Sized + 'a, |
828 | { |
829 | Box::pin(self) |
830 | } |
831 | } |
832 | |
833 | impl<F: Future + ?Sized> FutureExt for F {} |
834 | |