swactor/tests/inbox_wake_loom.rs

63 lines
2.1 KiB
Rust
Raw Normal View History

//! Loom model for the external-inbox pop/register/pop wake protocol.
//!
//! The two mutexes model the linearization points supplied by the lock-free
//! queue and `AtomicWaker`; they are not the production implementation.
use loom::sync::atomic::{AtomicBool, Ordering};
use loom::sync::{Arc, Mutex};
use loom::thread;
#[test]
fn send_cannot_be_lost_while_receiver_registers() {
loom::model(|| {
let queued = Arc::new(Mutex::new(false));
let registered = Arc::new(Mutex::new(false));
let ready = Arc::new(AtomicBool::new(false));
let woken = Arc::new(AtomicBool::new(false));
let sender_queued = queued.clone();
let sender_registered = registered.clone();
let sender_woken = woken.clone();
let sender = thread::spawn(move || {
*sender_queued.lock().unwrap() = true;
if *sender_registered.lock().unwrap() {
sender_woken.store(true, Ordering::Release);
}
});
let receiver_queued = queued.clone();
let receiver_registered = registered.clone();
let receiver_ready = ready.clone();
let receiver = thread::spawn(move || {
{
let mut queued = receiver_queued.lock().unwrap();
if *queued {
*queued = false;
receiver_ready.store(true, Ordering::Release);
return;
}
}
*receiver_registered.lock().unwrap() = true;
let mut queued = receiver_queued.lock().unwrap();
if *queued {
*queued = false;
receiver_ready.store(true, Ordering::Release);
}
});
sender.join().unwrap();
receiver.join().unwrap();
let ready = ready.load(Ordering::Acquire);
let woken = woken.load(Ordering::Acquire);
let queued = *queued.lock().unwrap();
let registered = *registered.lock().unwrap();
assert!(
ready || woken,
"ready={ready}, woken={woken}, queued={queued}, registered={registered}"
);
});
}