use parking_lot::{Condvar, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
#[derive(Debug, Default)]
pub struct Gate {
mutex: Mutex<()>,
condvar: Condvar,
}
impl Gate {
#[inline]
pub fn wait_while<F: Fn() -> bool>(&self, condition: F) {
if condition() {
let mut lock = self.mutex.lock();
while condition() {
self.condvar.wait(&mut lock);
}
}
}
pub fn notify_all(&self) {
let _lock = self.mutex.lock();
self.condvar.notify_all();
}
}
#[derive(Debug, Default)]
pub struct PhasedGate {
mutex: Mutex<()>,
condvar: Condvar,
phase: AtomicUsize,
}
impl PhasedGate {
#[inline]
pub fn wait_while<F: Fn() -> bool>(&self, condition: F) {
if condition() {
let phase = self.phase.load(Ordering::SeqCst);
let mut lock = self.mutex.lock();
while phase == self.phase.load(Ordering::Relaxed) && condition() {
self.condvar.wait(&mut lock);
}
let _ = self.phase.compare_exchange(
phase,
phase.wrapping_add(1),
Ordering::SeqCst,
Ordering::Relaxed,
);
}
}
pub fn notify_all(&self) {
let _lock = self.mutex.lock();
self.condvar.notify_all();
}
}