use super::*;
#[test]
fn notify_one_is_never_lost() {
explore("notify_one_is_never_lost", 3, 5, || {
let notify = Arc::new(Notify::new());
let waiter = {
let notify = Arc::clone(¬ify);
thread::spawn(move || block_on(notify.notified()))
};
notify.notify_one();
waiter.join().expect("waiter");
});
}
#[test]
fn notify_waiters_reaches_a_registered_waiter() {
explore("notify_waiters_reaches_a_registered_waiter", 3, 3, || {
let notify = Arc::new(Notify::new());
let queued = Arc::new(AtomicBool::new(false));
let waiter = {
let (notify, flag) = (Arc::clone(¬ify), Arc::clone(&queued));
thread::spawn(move || block_on(flag_when_queued(notify.notified(), &flag)))
};
wait_for(&queued);
notify.notify_waiters();
waiter.join().expect("waiter");
});
}
#[test]
fn an_older_notified_queued_behind_a_newer_one_gets_the_broadcast() {
explore(
"an_older_notified_queued_behind_a_newer_one_gets_the_broadcast",
3,
5,
|| {
let notify = Arc::new(Notify::new());
let created = Arc::new(AtomicBool::new(false));
let older = {
let (notify, created) = (Arc::clone(¬ify), Arc::clone(&created));
thread::spawn(move || {
let waiting = notify.notified();
created.store(true, Ordering::Release);
block_on(waiting);
})
};
wait_for(&created);
notify.notify_waiters();
let mut newer = Box::pin(notify.notified());
let polled = newer
.as_mut()
.poll(&mut Context::from_waker(std::task::Waker::noop()));
assert!(polled.is_pending(), "nothing notified it");
older.join().expect("older");
drop(newer);
},
);
}
#[test]
fn a_dropped_notified_passes_its_notify_one_on() {
explore("a_dropped_notified_passes_its_notify_one_on", 1, 5, || {
let notify = Arc::new(Notify::new());
let canceller = {
let notify = Arc::clone(¬ify);
thread::spawn(move || !poll_once_then_drop(notify.notified()))
};
let waiter = {
let notify = Arc::clone(¬ify);
thread::spawn(move || block_on(notify.notified()))
};
notify.notify_one();
if canceller.join().expect("canceller") {
notify.notify_one();
}
waiter.join().expect("waiter");
});
}
#[test]
fn a_notified_dropped_while_its_broadcast_wakes_it_outlives_the_wake_list() {
explore(
"a_notified_dropped_while_its_broadcast_wakes_it_outlives_the_wake_list",
3,
5,
|| {
let notify = Arc::new(Notify::new());
let queued = Arc::new(AtomicBool::new(false));
let dropper = {
let (notify, queued) = (Arc::clone(¬ify), Arc::clone(&queued));
thread::spawn(move || {
let mut waiting = Box::pin(notify.notified());
let polled = waiting
.as_mut()
.poll(&mut Context::from_waker(std::task::Waker::noop()));
assert!(polled.is_pending(), "nothing notified it yet");
queued.store(true, Ordering::Release);
drop(waiting);
})
};
wait_for(&queued);
notify.notify_waiters();
dropper.join().expect("dropper");
},
);
}