@@ -44,3 +44,150 @@ pub use rayon_core::ThreadPool;
44
44
pub use rayon_core:: join;
45
45
pub use rayon_core:: { scope, Scope } ;
46
46
pub use rayon_core:: spawn;
47
+
48
+ /// Fork and join many expressions at once.
49
+ ///
50
+ /// The syntax is one or more occurrences of
51
+ ///
52
+ /// ```ignore
53
+ /// let <irrefutable pattern> = fork <closure expresssion>;`.
54
+ /// ```
55
+ ///
56
+ /// For example,
57
+ ///
58
+ /// ```
59
+ /// #[macro_use]
60
+ /// extern crate rayon;
61
+ ///
62
+ /// # fn main() {
63
+ /// join! {
64
+ /// let w = fork || 0;
65
+ /// let x = fork || 1;
66
+ /// let y = fork || 2;
67
+ /// let z = fork || 3;
68
+ /// }
69
+ ///
70
+ /// assert_eq!(w, 0);
71
+ /// assert_eq!(x, 1);
72
+ /// assert_eq!(y, 2);
73
+ /// assert_eq!(z, 3);
74
+ /// # }
75
+ /// ```
76
+ ///
77
+ /// This is equivalent to nesting calls to `rayon::join` like this:
78
+ ///
79
+ /// ```
80
+ /// # extern crate rayon;
81
+ /// let (w, (x, (y, z))) = rayon::join(
82
+ /// || 0,
83
+ /// || rayon::join(
84
+ /// || 1,
85
+ /// || rayon::join(
86
+ /// || 2,
87
+ /// || 3,
88
+ /// )
89
+ /// )
90
+ /// );
91
+ /// ```
92
+ ///
93
+ /// Alternatively, you can just get a flattened tuple of results, without
94
+ /// binding the results to any variable inside the macro.
95
+ ///
96
+ /// The syntax is one or more occurrences of `<closure expression> ,` where the
97
+ /// last `,` is optional.
98
+ ///
99
+ /// ```rust
100
+ /// #[macro_use]
101
+ /// extern crate rayon;
102
+ ///
103
+ /// # fn main() {
104
+ /// let (w, x, y, z) = join!(|| 0, || 1, || 2, || 3);
105
+ ///
106
+ /// assert_eq!(w, 0);
107
+ /// assert_eq!(x, 1);
108
+ /// assert_eq!(y, 2);
109
+ /// assert_eq!(z, 3);
110
+ /// # }
111
+ /// ```
112
+ #[ macro_export]
113
+ macro_rules! join {
114
+ // Entry point for `let <pat> = fork <closure>;` usage.
115
+ ( $( let $lhs: pat = fork $rhs: expr ; ) + ) => {
116
+ let join!( @left $( $lhs , ) + ) = join!( @right $( $rhs , ) + ) ;
117
+ } ;
118
+
119
+ // Entry point for `<closure>,` usage.
120
+ ( $x: expr $( , $xs: expr ) * ) => {
121
+ join! { @flat $x $( , $xs ) * }
122
+ } ;
123
+
124
+ // Flattening tuples with temporary variables.
125
+ ( @flat $( let $lhs: ident = $rhs: expr ; ) + ) => {
126
+ {
127
+ let join!( @left $( $lhs , ) + ) = join!( @right $( $rhs , ) + ) ;
128
+ ( $( $lhs ) ,+)
129
+ }
130
+ } ;
131
+ ( @flat $( let $lhs: ident = $rhs: expr ; ) * $x: expr $( , $xs: expr ) * ) => {
132
+ join! { @flat
133
+ $( let $lhs = $rhs ; ) *
134
+ let lhs = $x;
135
+ $( $xs) ,*
136
+ }
137
+ } ;
138
+
139
+ // Left hand side recursion to nest individual patterns into tuple patterns
140
+ // like `(x, (y, (z, ...)))`.
141
+ ( @left $x: pat , ) => {
142
+ $x
143
+ } ;
144
+ ( @left $x: pat , $( $xs: pat , ) + ) => {
145
+ ( $x , join!( @left $( $xs , ) + ) )
146
+ } ;
147
+
148
+ // Right hand side recursion to nest exprs into rayon fork-joins
149
+ // like:
150
+ //
151
+ // rayon::join(
152
+ // x,
153
+ // || rayon::join(
154
+ // y,
155
+ // || rayon::join(
156
+ // z,
157
+ // || ...)))
158
+ ( @right $x: expr , ) => {
159
+ ( $x) ( )
160
+ } ;
161
+ ( @right $x: expr , $( $xs: expr , ) + ) => {
162
+ :: rayon:: join( $x , || join!( @right $( $xs , ) + ) )
163
+ }
164
+ }
165
+
166
+ // Necessary for the tests using macros that expand to `::rayon::whatever`.
167
+ #[ cfg( test) ]
168
+ mod rayon {
169
+ pub use super :: * ;
170
+ }
171
+
172
+ #[ cfg( test) ]
173
+ mod tests {
174
+ #[ macro_use]
175
+ use super :: * ;
176
+
177
+ #[ test]
178
+ fn join_macro_with_more_complex_patterns ( ) {
179
+ struct Point ( usize , usize ) ;
180
+
181
+ join ! {
182
+ let Point ( w, x) = fork || Point ( 1 , 2 ) ;
183
+ let Point ( y, z) = fork || Point ( 3 , 4 ) ;
184
+ let ( ( ( ( ( a, _) , _) , _) , _) , _) = fork || ( ( ( ( ( 5 , 4 ) , 3 ) , 2 ) , 1 ) , 0 ) ;
185
+ } ;
186
+
187
+ assert_eq ! ( w, 1 ) ;
188
+ assert_eq ! ( x, 2 ) ;
189
+ assert_eq ! ( y, 3 ) ;
190
+ assert_eq ! ( z, 4 ) ;
191
+ assert_eq ! ( a, 5 ) ;
192
+ }
193
+ }
0 commit comments