1 /// Wait on multiple concurrent branches, returning when **all** branches 2 /// complete. 3 /// 4 /// The `join!` macro must be used inside of async functions, closures, and 5 /// blocks. 6 /// 7 /// The `join!` macro takes a list of async expressions and evaluates them 8 /// concurrently on the same task. Each async expression evaluates to a future 9 /// and the futures from each expression are multiplexed on the current task. 10 /// 11 /// When working with async expressions returning `Result`, `join!` will wait 12 /// for **all** branches complete regardless if any complete with `Err`. Use 13 /// [`try_join!`] to return early when `Err` is encountered. 14 /// 15 /// [`try_join!`]: macro@try_join 16 /// 17 /// # Notes 18 /// 19 /// The supplied futures are stored inline and does not require allocating a 20 /// `Vec`. 21 /// 22 /// ### Runtime characteristics 23 /// 24 /// By running all async expressions on the current task, the expressions are 25 /// able to run **concurrently** but not in **parallel**. This means all 26 /// expressions are run on the same thread and if one branch blocks the thread, 27 /// all other expressions will be unable to continue. If parallelism is 28 /// required, spawn each async expression using [`tokio::spawn`] and pass the 29 /// join handle to `join!`. 30 /// 31 /// [`tokio::spawn`]: crate::spawn 32 /// 33 /// # Examples 34 /// 35 /// Basic join with two branches 36 /// 37 /// ``` 38 /// async fn do_stuff_async() { 39 /// // async work 40 /// } 41 /// 42 /// async fn more_async_work() { 43 /// // more here 44 /// } 45 /// 46 /// #[tokio::main] 47 /// async fn main() { 48 /// let (first, second) = tokio::join!( 49 /// do_stuff_async(), 50 /// more_async_work()); 51 /// 52 /// // do something with the values 53 /// } 54 /// ``` 55 #[macro_export] 56 #[cfg_attr(docsrs, doc(cfg(feature = "macros")))] 57 macro_rules! join { 58 (@ { 59 // One `_` for each branch in the `join!` macro. This is not used once 60 // normalization is complete. 61 ( $($count:tt)* ) 62 63 // Normalized join! branches 64 $( ( $($skip:tt)* ) $e:expr, )* 65 66 }) => {{ 67 use $crate::macros::support::{maybe_done, poll_fn, Future, Pin}; 68 use $crate::macros::support::Poll::{Ready, Pending}; 69 70 // Safety: nothing must be moved out of `futures`. This is to satisfy 71 // the requirement of `Pin::new_unchecked` called below. 72 let mut futures = ( $( maybe_done($e), )* ); 73 74 poll_fn(move |cx| { 75 let mut is_pending = false; 76 77 $( 78 // Extract the future for this branch from the tuple. 79 let ( $($skip,)* fut, .. ) = &mut futures; 80 81 // Safety: future is stored on the stack above 82 // and never moved. 83 let mut fut = unsafe { Pin::new_unchecked(fut) }; 84 85 // Try polling 86 if fut.poll(cx).is_pending() { 87 is_pending = true; 88 } 89 )* 90 91 if is_pending { 92 Pending 93 } else { 94 Ready(($({ 95 // Extract the future for this branch from the tuple. 96 let ( $($skip,)* fut, .. ) = &mut futures; 97 98 // Safety: future is stored on the stack above 99 // and never moved. 100 let mut fut = unsafe { Pin::new_unchecked(fut) }; 101 102 fut.take_output().expect("expected completed future") 103 },)*)) 104 } 105 }).await 106 }}; 107 108 // ===== Normalize ===== 109 110 (@ { ( $($s:tt)* ) $($t:tt)* } $e:expr, $($r:tt)* ) => { 111 $crate::join!(@{ ($($s)* _) $($t)* ($($s)*) $e, } $($r)*) 112 }; 113 114 // ===== Entry point ===== 115 116 ( $($e:expr),* $(,)?) => { 117 $crate::join!(@{ () } $($e,)*) 118 }; 119 } 120