diff --git a/src/bin/test_simple.rs b/src/bin/test_simple.rs index bb1df9f..c0d9f5b 100644 --- a/src/bin/test_simple.rs +++ b/src/bin/test_simple.rs @@ -1,5 +1,5 @@ use rand::Rng; -use rustmp::par_for; +use rustmp::{par_for, critical}; use std::time; #[derive(Debug)] @@ -11,9 +11,11 @@ struct Student { impl Student { pub fn new(age: u8) -> Student { - Student { name: "Default".to_string(), - age, - gpa: age as f32 } + Student { + name: "Default".to_string(), + age, + gpa: age as f32, + } } } @@ -21,23 +23,32 @@ fn main() { let numbers: Vec = vec![]; par_for! { - for i in 1..32, capturing numbers { - //std::thread::sleep( - // time::Duration::from_secs( - // rand::thread_rng().gen_range(1..10))); - let mut lock = numbers.write(); - lock.push(Student::new(i)); - println!("Thread {} running!", i); - } }; - - par_for! { - for i in 1..32, blocksize 16, capturing numbers { - let mut lock = numbers.write(); - lock.push(Student::new(i)); - println!("Thread {} running!", i); - } }; + for i in 1..32, blocksize 4, capturing numbers, { + //std::thread::sleep( + // time::Duration::from_secs( + // rand::thread_rng().gen_range(1..10))); + critical! { + // Automatically locks numbers as read+write, + // and makes the result accessible as number + readwrite numbers; + numbers.push(Student::new(i)); + } + println!("Thread {} running!", i); + } + } for num in numbers { - println!("{:?}", num); + println!("{:?}", num); } + + //let mut local = 0; + //par_for! { + //for i in 1..32, blocksize 1, capturing numbers, private local, { + //local += 1; + //println!("{}", local); + //let mut lock = numbers.write(); + //lock.push(Student::new(i)); + //println!("Thread {} running!", i); + //} } + } diff --git a/src/lib.rs b/src/lib.rs index af0e402..5b17c0a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,18 +39,54 @@ impl Capture { } } +#[macro_export] +macro_rules! critical { + (read $($r:ident)+; readwrite $($w:ident)+; $($ops:tt)+) => { + { + $(let $r = $r.read();)* + $(let mut $w = $w.write();)* + $($ops)* + } + }; + (readwrite $($w:ident)+; read $($r:ident)+; $($ops:tt)+) => { + { + $(let $r = $r.read();)* + $(let mut $w = $w.write();)* + $($ops)* + } + }; + (readwrite $($w:ident)+; $($ops:tt)+) => { + { + $(let mut $w = $w.write();)* + $($ops)* + } + }; + (read $($r:ident)+; $($ops:tt)+) => { + { + $(let $r = $r.read();)* + $($ops)* + } + }; +} + #[macro_export] macro_rules! __internal_par_for { - ($name:ident, $iterator:expr, $size:expr, $($captured:ident)*, $blk:block) => { + (var_name($name:ident), + iterator($iter:expr), + blocksize($size:expr), + captured($($captured:ident)*), + private($($private:ident)*), + $blk:block) => { let mut __rmp_tasks = Vec::new(); $(let $captured = rustmp::Capture::new($captured);)* { let __rmp_tpm_mtx = rustmp::ThreadPoolManager::get_instance_guard(); let __rmp_tpm = __rmp_tpm_mtx.lock().unwrap(); - let __rmp_iters = __rmp_tpm.split_iterators($iterator, $size); + let __rmp_iters = __rmp_tpm.split_iterators($iter, $size); for iter in __rmp_iters { $(let $captured = $captured.clone();)* __rmp_tasks.push(rustmp::as_static_job(move || { + $(let mut $private = $private.clone();)* for &$name in &iter $blk })); @@ -59,6 +95,54 @@ macro_rules! __internal_par_for { } $(let $captured = $captured.unwrap();)* }; + // Parse blocksize + (var_name($name:ident), + iterator($iter:expr), + blocksize($size:expr), + captured($($captured:ident)*), + private($($private:ident)*), + blocksize $new_size:expr, + $($rem:tt)+) => { + rustmp::__internal_par_for!( + var_name($name), + iterator($iter), + blocksize($new_size), + captured($($captured)*), + private($($private)*), + $($rem)*) + }; + // Parse capturing + (var_name($name:ident), + iterator($iter:expr), + blocksize($size:expr), + captured($($captured:ident)*), + private($($private:ident)*), + capturing $($new_captured:ident)*, + $($rem:tt)+) => { + rustmp::__internal_par_for!( + var_name($name), + iterator($iter), + blocksize($size), + captured($($new_captured)*), + private($($private)*), + $($rem)*) + }; + // Parse private + (var_name($name:ident), + iterator($iter:expr), + blocksize($size:expr), + captured($($captured:ident)*), + private($($private:ident)*), + private $($new_private:ident)*, + $($rem:tt)+) => { + rustmp::__internal_par_for!( + var_name($name), + iterator($iter), + blocksize($size), + captured($($captured)*), + private($($new_private)*), + $($rem)*) + }; } /// "parallel for" wrapper @@ -67,22 +151,13 @@ macro_rules! __internal_par_for { /// Current implementation save limited (max depth 32) stack space for macro expansion. #[macro_export] macro_rules! par_for { - (for $name:ident in $iterator:expr, blocksize $size:expr, capturing $($captured:ident)+, $blk:block) => { - rustmp::__internal_par_for!($name, $iterator, $size, $($captured)*, $blk); - }; - (for $name:ident in $iterator:expr, blocksize $size:expr, capturing $($captured:ident)+ $blk:block) => { - rustmp::__internal_par_for!($name, $iterator, $size, $($captured)*, $blk); - }; - (for $name:ident in $iterator:expr, capturing $($captured:ident)+, blocksize $size:expr, $blk:block) => { - rustmp::__internal_par_for!($name, $iterator, $size, $($captured)*, $blk); - }; - (for $name:ident in $iterator:expr, blocksize $size:expr, $blk:block) => { - rustmp::__internal_par_for!($name, $iterator, $size,, $blk); - }; - (for $name:ident in $iterator:expr, capturing $($captured:ident)+, $blk:block) => { - rustmp::__internal_par_for!($name, $iterator, 1, $($captured)*, $blk); - }; - (for $name:ident in $iterator:expr, capturing $($captured:ident)+ $blk:block) => { - rustmp::__internal_par_for!($name, $iterator, 1, $($captured)*, $blk); + (for $name:ident in $iter:expr, $($rem:tt)+) => { + rustmp::__internal_par_for!( + var_name($name), + iterator($iter), + blocksize(1), + captured(), + private(), + $($rem)*) } }