#![deny(warnings, rust_2018_idioms)] use loom::sync::atomic::AtomicUsize; use loom::sync::{Condvar, Mutex}; use loom::thread; use std::sync::atomic::Ordering::SeqCst; use std::sync::Arc; #[test] fn notify_one() { loom::model(|| { let inc = Arc::new(Inc::new()); for _ in 0..1 { let inc = inc.clone(); thread::spawn(move || inc.inc()); } inc.wait(); }); } #[test] fn notify_all() { loom::model(|| { let inc = Arc::new(Inc::new()); let mut waiters = Vec::new(); for _ in 0..2 { let inc = inc.clone(); waiters.push(thread::spawn(move || inc.wait())); } thread::spawn(move || inc.inc_all()).join().expect("inc"); for th in waiters { th.join().expect("waiter"); } }); } struct Inc { num: AtomicUsize, mutex: Mutex<()>, condvar: Condvar, } impl Inc { fn new() -> Inc { Inc { num: AtomicUsize::new(0), mutex: Mutex::new(()), condvar: Condvar::new(), } } fn wait(&self) { let mut guard = self.mutex.lock().unwrap(); loop { let val = self.num.load(SeqCst); if 1 == val { break; } guard = self.condvar.wait(guard).unwrap(); } } fn inc(&self) { self.num.store(1, SeqCst); drop(self.mutex.lock().unwrap()); self.condvar.notify_one(); } fn inc_all(&self) { self.num.store(1, SeqCst); drop(self.mutex.lock().unwrap()); self.condvar.notify_all(); } }