use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
use std::time::Duration;
use omnigraph::failpoints::ScopedFailPoint;
pub struct Rendezvous {
name: String,
reached: Arc<AtomicBool>,
release: Arc<AtomicBool>,
_failpoint: ScopedFailPoint,
}
impl Rendezvous {
pub fn park_first(name: &str) -> Self {
let reached = Arc::new(AtomicBool::new(false));
let release = Arc::new(AtomicBool::new(false));
let (cb_reached, cb_release) = (Arc::clone(&reached), Arc::clone(&release));
let _failpoint = ScopedFailPoint::with_callback(name, move || {
if cb_reached
.compare_exchange(false, true, SeqCst, SeqCst)
.is_ok()
{
for _ in 0..6000 {
if cb_release.load(SeqCst) {
return;
}
std::thread::sleep(Duration::from_millis(5));
}
}
});
Self {
name: name.to_string(),
reached,
release,
_failpoint,
}
}
pub async fn wait_until_reached(&self) {
for _ in 0..2400 {
if self.reached.load(SeqCst) {
return;
}
tokio::time::sleep(Duration::from_millis(5)).await;
}
panic!("rendezvous: failpoint '{}' was never reached", self.name);
}
pub fn reached(&self) -> bool {
self.reached.load(SeqCst)
}
pub fn release(&self) {
self.release.store(true, SeqCst);
}
}