1
1
//! The `join` macro.
2
2
3
3
/// Polls multiple futures simultaneously, returning a tuple
4
- /// of all results once complete.
5
- ///
4
+ /// of all results once complete.
5
+ ///
6
6
/// While `join!(a, b)` is similar to `(await!(a), await!(b))`,
7
7
/// `join!` polls both futures concurrently and therefore is more efficent.
8
- ///
8
+ ///
9
9
/// This macro is only usable inside of async functions, closures, and blocks.
10
- ///
10
+ ///
11
11
/// # Examples
12
- ///
12
+ ///
13
13
/// ```
14
14
/// #![feature(pin, async_await, await_macro, futures_api)]
15
15
/// # futures::executor::block_on(async {
16
16
/// use futures::{join, future};
17
17
///
18
18
/// let a = future::ready(1);
19
19
/// let b = future::ready(2);
20
- ///
20
+ ///
21
21
/// assert_eq!(join!(a, b), (1, 2));
22
22
/// # });
23
23
/// ```
@@ -31,7 +31,7 @@ macro_rules! join {
31
31
loop {
32
32
let mut all_done = true ;
33
33
$(
34
- if let $crate:: core_reexport :: task :: Poll :: Pending = $crate :: poll!( $fut. reborrow( ) ) {
34
+ if $crate:: poll!( $fut. reborrow( ) ) . is_pending ( ) {
35
35
all_done = false ;
36
36
}
37
37
) *
@@ -47,3 +47,77 @@ macro_rules! join {
47
47
) * )
48
48
} }
49
49
}
50
+
51
+ /// Polls multiple futures simultaneously, resolving to a [`Result`] containing
52
+ /// either a tuple of the successful outputs or an error.
53
+ ///
54
+ /// `try_join!` is similar to [`join!`], but completes immediately if any of
55
+ /// the futures return an error.
56
+ ///
57
+ /// This macro is only usable inside of async functions, closures, and blocks.
58
+ ///
59
+ /// # Examples
60
+ ///
61
+ /// When used on multiple futures that return `Ok`, `try_join!` will return
62
+ /// `Ok` of a tuple of the values:
63
+ ///
64
+ /// ```
65
+ /// #![feature(pin, async_await, await_macro, futures_api)]
66
+ /// # futures::executor::block_on(async {
67
+ /// use futures::{try_join, future};
68
+ ///
69
+ /// let a = future::ready(Ok::<i32, i32>(1));
70
+ /// let b = future::ready(Ok::<u64, i32>(2));
71
+ ///
72
+ /// assert_eq!(try_join!(a, b), Ok((1, 2)));
73
+ /// # });
74
+ /// ```
75
+ ///
76
+ /// If one of the futures resolves to an error, `try_join!` will return
77
+ /// that error:
78
+ ///
79
+ /// ```
80
+ /// #![feature(pin, async_await, await_macro, futures_api)]
81
+ /// # futures::executor::block_on(async {
82
+ /// use futures::{try_join, future};
83
+ ///
84
+ /// let a = future::ready(Ok::<i32, i32>(1));
85
+ /// let b = future::ready(Err::<u64, i32>(2));
86
+ ///
87
+ /// assert_eq!(try_join!(a, b), Err(2));
88
+ /// # });
89
+ /// ```
90
+ #[ macro_export]
91
+ macro_rules! try_join {
92
+ ( $( $fut: ident) ,* ) => { {
93
+ $(
94
+ let mut $fut = $crate:: future:: maybe_done( $fut) ;
95
+ $crate:: pin_mut!( $fut) ;
96
+ ) *
97
+ let res: $crate:: core_reexport:: result:: Result <( ) , _> = loop {
98
+ let mut all_done = true ;
99
+ $(
100
+ if $crate:: poll!( $fut. reborrow( ) ) . is_pending( ) {
101
+ all_done = false ;
102
+ } else if $fut. reborrow( ) . output_mut( ) . unwrap( ) . is_err( ) {
103
+ // `.err().unwrap()` rather than `.unwrap_err()` so that we don't introduce
104
+ // a `T: Debug` bound.
105
+ break $crate:: core_reexport:: result:: Result :: Err (
106
+ $fut. reborrow( ) . take_output( ) . unwrap( ) . err( ) . unwrap( )
107
+ ) ;
108
+ }
109
+ ) *
110
+ if all_done {
111
+ break $crate:: core_reexport:: result:: Result :: Ok ( ( ) ) ;
112
+ } else {
113
+ $crate:: pending!( ) ;
114
+ }
115
+ } ;
116
+
117
+ res. map( |( ) | ( $(
118
+ // `.ok().unwrap()` rather than `.unwrap()` so that we don't introduce
119
+ // an `E: Debug` bound.
120
+ $fut. reborrow( ) . take_output( ) . unwrap( ) . ok( ) . unwrap( ) ,
121
+ ) * ) )
122
+ } }
123
+ }
0 commit comments