use corundum::Root; use corundum::default::*; use corundum::open_flags::*; type P = Allocator; struct Consumer { buf: PMutex, volume: Parc> } #[derive(Root)] struct Root { volume: Parc>, consumers: PRefCell>> } fn main() { use std::env; use std::vec::Vec as StdVec; let mut args: StdVec = env::args().collect(); if args.len() < 2 { println!("usage: {} file-name [OPTIONS]", args[0]); println!("OPTIONS:"); println!(" -i Initial value (default: 1000000)"); println!(" -t Number of threads (default: 4)"); println!(" -r Reset"); return; } let root = P::open::(&args[1], O_CFNE | O_4GB).unwrap(); let mut resetting = false; let mut init_val = 1000000; let mut t = root.consumers.borrow().len(); args.remove(0); args.remove(0); while !args.is_empty() { if args[0] == "-i" && args.len() > 1 { args.remove(0); init_val = args[0].parse::().expect("Error: Expected a number"); } else if args[0] == "-t" && args.len() > 1 { args.remove(0); t = args[0].parse::().expect("Error: Expected a number"); assert!(t>0); } else if args[0] == "-r" { resetting = true; } else { panic!("Bad option `{}`", args[0]); } args.remove(0); } if resetting || root.consumers.borrow().is_empty() { println!("Initializing the consumers to pour {} gallons of oil into {} barrels", init_val, t); let r = root.clone(); P::transaction(move |j| { let mut volume = r.volume.lock(j); let mut consumers = r.consumers.borrow_mut(j); *volume = init_val; if t == 0 { t = 4 }; let quota = init_val / t as u64; consumers.clear(); for _ in 0..t-1 { consumers.push(Parc::new(Consumer{ buf: PMutex::new(quota), volume: r.volume.pclone(j) }, j), j); init_val -= quota; } consumers.push(Parc::new(Consumer{ buf: PMutex::new(init_val), volume: r.volume.pclone(j) }, j), j); }).unwrap(); } let mut threads = vec![]; for c in &*root.consumers.borrow() { let v = c.demote(); threads.push(std::thread::spawn(move || { loop { let v = v.clone(); let mut b = P::transaction(|j| { if let Some(c) = v.promote(j) { let mut b = c.buf.lock(j); let mut vol = c.volume.lock(j); if *b > 100 { *b -= 100; *vol -= 100; 100 } else { let r = *b; *vol -= r; *b = 0; r } } else { 0 } }).unwrap(); if b == 0 { break } P::transaction(move |j| { if let Some(c) = v.promote(j) { while b > 0 { let vol = c.volume.lock(j); b -= 1; eprint!("\r\x1b[?25lRemaining: {:<12} \x1b[?25h", *vol + b); } } }).unwrap(); } })); } for t in threads { t.join().unwrap(); } }