1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
// Pasts // Copyright © 2019-2021 Jeron Aldaron Lau. // // Licensed under any of: // - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0) // - MIT License (https://mit-license.org/) // - Boost Software License, Version 1.0 (https://www.boost.org/LICENSE_1_0.txt) // At your choosing (See accompanying files LICENSE_APACHE_2_0.txt, // LICENSE_MIT.txt and LICENSE_BOOST_1_0.txt). /// Create a future that waits on multiple futures concurrently and returns the /// first result. /// /// Takes an array of types that implement [`Future`](core::future::Future) and /// [`Unpin`](core::marker::Unpin). /// /// # Example: Await on The Fastest Future /// `race!()` will always poll the first future in the array first. /// /// ```rust /// use core::{future::Future, pin::Pin}; /// use pasts::race; /// /// async fn async_main() { /// let hello: Pin<Box<dyn Future<Output=&str>>> = Box::pin(async { "Hello" }); /// let world: Pin<Box<dyn Future<Output=&str>>> = Box::pin(async { "World" }); /// let mut array = [hello, world]; /// // Hello is ready, so returns with index and result. /// assert_eq!((0, "Hello"), race!(array)); /// } /// /// pasts::block_on(async_main()); /// ``` #[macro_export] macro_rules! race { ($f:expr) => {{ use core::{ future::Future, pin::Pin, task::{Context, Poll}, }; struct Fut<'a, T, F: Future<Output = T> + Unpin> { futures: &'a mut [F], } impl<T, F: Future<Output = T> + Unpin> Unpin for Fut<'_, T, F> {} impl<T: Unpin, F: Future<Output = T> + Unpin> Future for Fut<'_, T, F> { type Output = (usize, T); fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Self::Output> { let tasks = &mut self.get_mut().futures; for (task_id, mut task) in tasks.iter_mut().enumerate() { let pin_fut = Pin::new(&mut task); let task = pin_fut.poll(cx); match task { Poll::Ready(ret) => return Poll::Ready((task_id, ret)), Poll::Pending => {} } } Poll::Pending } } Pin::<&mut (dyn Future<Output = _> + Unpin)>::new(&mut Fut { futures: &mut $f[..], }) .await }}; } /// Similar to [`race!()`], except doesn't take an array, but rather a list of /// asynchronous expressions. #[macro_export] macro_rules! wait { ($($f:expr),* $(,)?) => {{ use core::{pin::Pin, future::Future}; // Safe because future can't move because it can't be directly // accessed $crate::race!([$(unsafe { Pin::<&mut dyn Future<Output = _>>::new_unchecked( &mut async { $f } ) }),*]).1 }}; }