#![cfg(loom)]
use loom::sync::{
atomic::{AtomicBool, AtomicUsize, Ordering},
Arc, Mutex,
};
use loom::thread;
struct ScopeState {
pending: AtomicUsize,
wait_lock: Mutex<()>,
completion_released_state: AtomicBool,
}
#[test]
fn zero_publication_happens_inside_wait_lock() {
loom::model(|| {
let state = Arc::new(ScopeState {
pending: AtomicUsize::new(1),
wait_lock: Mutex::new(()),
completion_released_state: AtomicBool::new(false),
});
let completion_state = Arc::clone(&state);
let completion = thread::spawn(move || {
let _guard = completion_state.wait_lock.lock().unwrap();
assert_eq!(
completion_state.pending.compare_exchange(
1,
0,
Ordering::AcqRel,
Ordering::Acquire
),
Ok(1)
);
completion_state
.completion_released_state
.store(true, Ordering::Release);
});
while state.pending.load(Ordering::Acquire) != 0 {
thread::yield_now();
}
let _guard = state.wait_lock.lock().unwrap();
assert!(
state.completion_released_state.load(Ordering::Acquire),
"zero must not authorize destruction before completion releases state"
);
drop(_guard);
completion.join().unwrap();
});
}