I use loom to test a customized condvar, in specific its wait_timeout method. To make sure the waiter times out instead of getting woken up, I use std::thread::sleep() to freeze the notifier for a while. But it turns out assert!(timed_out) always fails when using loom. Is it because loom doesn't respect std::thread::sleep()? Or loom inject spurious wakes into loom::sync::condvar?
The test:
use loom::sync::atomic::{AtomicUsize, Ordering};
use loom::sync::{Arc, Mutex};
use loom::thread;
#[test]
fn test_condvar_loom() {
loom::model(|| {
let short_timeout_millis = 1;
let mu = Arc::new(Mutex::new(()));
let condv = Arc::new(Condvar::new());
let mut ts = vec![];
let enter_ticket = Arc::new(AtomicUsize::new(0));
for i in 0..2 {
let (mu, condv, enter) = (
mu.clone(),
condv.clone(),
enter_ticket.clone(),
);
let t = thread::spawn(move || {
let guard = mu.lock().unwrap();
enter.fetch_add(1, Ordering::Relaxed);
let (_, timed_out) = condv.wait_timeout(
guard,
Duration::from_millis(short_timeout_millis),
);
assert_eq!(timed_out, true);
});
ts.push(t);
}
ts.push(thread::spawn(move || {
while enter_ticket.load(Ordering::Relaxed) != 2 {
thread::yield_now();
}
{
let _guard = mu.lock().unwrap();
std::thread::sleep(Duration::from_millis(short_timeout_millis * 5);
condv.notify_all();
}
}));
for t in ts {
t.join().unwrap();
}
});
}
I use loom to test a customized condvar, in specific its
wait_timeout
method. To make sure the waiter times out instead of getting woken up, I usestd::thread::sleep()
to freeze the notifier for a while. But it turns outassert!(timed_out)
always fails when using loom. Is it because loom doesn't respectstd::thread::sleep()
? Or loom inject spurious wakes intoloom::sync::condvar
?The test: