1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#![cfg(feature = "loom")] use lite_sync::notify::SingleWaiterNotify; use loom::future::block_on; use loom::sync::Arc; use loom::thread; #[test] fn loom_notify_basic() { loom::model(|| { let notify = Arc::new(SingleWaiterNotify::new()); let notify_rx = notify.clone(); let notify_tx = notify.clone(); thread::spawn(move || { notify_tx.notify_one(); }); block_on(async move { notify_rx.notified().await; }); }); } #[test] fn loom_notify_concurrent_notify() { loom::model(|| { let notify = Arc::new(SingleWaiterNotify::new()); let rx = notify.clone(); let tx1 = notify.clone(); let tx2 = notify.clone(); thread::spawn(move || { tx1.notify_one(); }); thread::spawn(move || { tx2.notify_one(); }); block_on(async move { rx.notified().await; }); }); } #[test] fn loom_notify_drop_safety() { loom::model(|| { let notify = Arc::new(SingleWaiterNotify::new()); let rx = notify.clone(); let tx = notify.clone(); thread::spawn(move || { tx.notify_one(); }); block_on(async move { // Start waiting but cancel (by dropping future indirectly/completing) // Here we just complete, but model checks memory safety. rx.notified().await; }); }); }