use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use tokio::sync::Notify;
const PATIENCE: Duration = Duration::from_secs(5);
#[derive(Default)]
pub(crate) struct TestHooks {
paused: AtomicBool,
parked: AtomicBool,
resume: Notify,
}
impl TestHooks {
pub(super) fn pause(&self) {
self.paused.store(true, Ordering::Release);
}
pub(super) fn release(&self) {
self.paused.store(false, Ordering::Release);
self.resume.notify_waiters();
}
pub(super) async fn wait_until_parked(&self) {
let deadline = tokio::time::Instant::now() + PATIENCE;
while tokio::time::Instant::now() < deadline {
if self.parked.load(Ordering::Acquire) {
return;
}
tokio::time::sleep(Duration::from_millis(1)).await;
}
panic!("the batcher never reached the barrier within {PATIENCE:?}");
}
pub(super) async fn barrier(&self) {
if !self.paused.load(Ordering::Acquire) {
return;
}
self.parked.store(true, Ordering::Release);
loop {
let resumed = self.resume.notified();
if !self.paused.load(Ordering::Acquire) {
break;
}
resumed.await;
}
self.parked.store(false, Ordering::Release);
}
}