use crate::sync::SetOnce; use loom::future::block_on; use loom::sync::atomic::AtomicU32; use loom::thread; use std::sync::atomic::Ordering; use std::sync::Arc; #[derive(Clone)] struct DropCounter { pub drops: Arc, } impl DropCounter { pub fn new() -> Self { Self { drops: Arc::new(AtomicU32::new(0)), } } fn assert_num_drops(&self, value: u32) { assert_eq!(value, self.drops.load(Ordering::Relaxed)); } } impl Drop for DropCounter { fn drop(&mut self) { self.drops.fetch_add(1, Ordering::Relaxed); } } #[test] fn set_once_drop_test() { loom::model(|| { let set_once = Arc::new(SetOnce::new()); let set_once_clone = Arc::clone(&set_once); let drop_counter = DropCounter::new(); let counter_cl = drop_counter.clone(); let thread = thread::spawn(move || set_once_clone.set(counter_cl).is_ok()); let foo = drop_counter.clone(); let set = set_once.set(foo).is_ok(); let res = thread.join().unwrap(); drop(set_once); drop_counter.assert_num_drops(2); assert!(res != set); }); } #[test] fn set_once_wait_test() { loom::model(|| { let tx = Arc::new(SetOnce::new()); let rx_one = tx.clone(); let rx_two = tx.clone(); let thread = thread::spawn(move || { assert!(rx_one.set(2).is_ok()); }); block_on(async { assert_eq!(*rx_two.wait().await, 2); }); thread.join().unwrap(); }); }