Skip to content

Commit

Permalink
Add the join! macro
Browse files Browse the repository at this point in the history
The `join!` macro forks and joins many expressions at once. This is easier to
use than deeply nesting calls to `rayon::join`.
  • Loading branch information
fitzgen committed Sep 11, 2017
1 parent ea50fb4 commit dfdac48
Showing 1 changed file with 113 additions and 0 deletions.
113 changes: 113 additions & 0 deletions src/lib.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,116 @@ pub use rayon_core::spawn;
pub use rayon_core::spawn_future;
#[cfg(rayon_unstable)]
pub use rayon_core::RayonFuture;

/// Fork and join many expressions at once.
///
/// The syntax is one or more recurrences of `let <ident> = fork <closure
/// expresssion>;`.
///
/// ```
/// #[macro_use]
/// extern crate rayon;
///
/// # fn main() {
/// join! {
/// let w = fork || 0;
/// let x = fork || 1;
/// let y = fork || 2;
/// let z = fork || 3;
/// }
///
/// assert_eq!(w, 0);
/// assert_eq!(x, 1);
/// assert_eq!(y, 2);
/// assert_eq!(z, 3);
/// # }
/// ```
///
/// This is equivalent to nesting calls to `rayon::join` like this:
///
/// ```
/// # extern crate rayon;
/// let (w, (x, (y, z))) = rayon::join(
/// || 0,
/// || rayon::join(
/// || 1,
/// || rayon::join(
/// || 2,
/// || 3,
/// )
/// )
/// );
/// ```
///
/// Alternatively, you can just get a flattened tuple of results, without
/// binding the results to any variable inside the macro.
///
/// The syntax is one or more occurrences of `<closure expression> ,` where the
/// last `,` is optional.
///
/// ```rust
/// #[macro_use]
/// extern crate rayon;
///
/// # fn main() {
/// let (w, x, y, z) = join!(|| 0, || 1, || 2, || 3);
///
/// assert_eq!(w, 0);
/// assert_eq!(x, 1);
/// assert_eq!(y, 2);
/// assert_eq!(z, 3);
/// # }
/// ```
#[macro_export]
macro_rules! join {
// Entry point for `let <ident> = fork <closure>;` usage.
( $( let $lhs:ident = fork $rhs:expr ; )+ ) => {
let join!( @left $( $lhs , )+ ) = join!( @right $( $rhs , )+ );
};

// Entry point for `<closure>,` usage.
( $x:expr $( , $xs:expr )* ) => {
join! { @flat $x $( , $xs )* }
};

// Flattening tuples with temporary variables.
( @flat $( let $lhs:ident = $rhs:expr ; )+ ) => {
{
let join!( @left $( $lhs , )+ ) = join!( @right $( $rhs , )+ );
($( $lhs ),+)
}
};
( @flat $( let $lhs:ident = $rhs:expr ; )* $x:expr $( , $xs:expr )*) => {
join! { @flat
$( let $lhs = $rhs ; )*
let lhs = $x;
$($xs),*
}
};

// Left hand side recursion to nest individual patterns into tuple patterns
// like `(x, (y, (z, ...)))`.
( @left $x:ident , ) => {
$x
};
( @left $x:ident , $( $xs:ident , )+ ) => {
( $x , join!( @left $( $xs , )+ ) )
};

// Right hand side recursion to nest exprs into rayon fork-joins
// like:
//
// rayon::join(
// x,
// || rayon::join(
// y,
// || rayon::join(
// z,
// || ...)))
( @right $x:expr , ) => {
($x)()
};
( @right $x:expr , $( $xs:expr , )+ ) => {
::rayon::join( $x , || join!( @right $( $xs , )+ ) )
}
}

0 comments on commit dfdac48

Please sign in to comment.