use std::sync::{Condvar, Mutex};
use std::time::Duration;
pub(crate) const PATIENCE: Duration = Duration::from_secs(10);
pub(crate) const SERIAL_PATIENCE: Duration = Duration::from_millis(200);
pub(crate) struct Rendezvous {
arrived: Mutex<usize>,
changed: Condvar,
target: usize,
patience: Duration,
}
impl Rendezvous {
pub(crate) fn new(target: usize) -> Rendezvous {
return Rendezvous { arrived: Mutex::new(0), changed: Condvar::new(), target, patience: PATIENCE };
}
pub(crate) fn impatient(target: usize, patience: Duration) -> Rendezvous {
return Rendezvous { patience, ..Rendezvous::new(target) };
}
pub(crate) fn arrive(&self) -> bool {
let mut count = self.arrived.lock().expect("lock");
*count += 1;
self.changed.notify_all();
return self.wait_while_short(count);
}
pub(crate) fn wait_for_target(&self) -> bool {
let count = self.arrived.lock().expect("lock");
return self.wait_while_short(count);
}
pub(crate) fn arrive_without_waiting(&self) {
let mut count = self.arrived.lock().expect("lock");
*count += 1;
self.changed.notify_all();
}
fn wait_while_short(&self, count: std::sync::MutexGuard<'_, usize>) -> bool {
let (guard, timeout) = self.changed.wait_timeout_while(count, self.patience, |seen: &mut usize| { return *seen < self.target; }).expect("wait");
drop(guard);
return !timeout.timed_out();
}
}