use crate::ptr::Ptr;
struct BarrierInner {
initial: usize,
current: usize,
cycle: usize,
mtx: super::mutex::Mutex,
cnd: super::condvar::Condvar,
}
#[derive(Copy, Clone)]
pub struct Barrier {
inner: Ptr<BarrierInner>,
}
impl Barrier {
pub fn new(n: usize) -> Self {
Self {
inner: Ptr::new(BarrierInner {
initial: n,
current: n,
cycle: 0,
cnd: super::condvar::Condvar::new(),
mtx: super::mutex::Mutex::new(),
}),
}
}
pub fn wait(&self) -> bool {
self.inner.mtx.lock();
let cycle = self.inner.cycle;
self.inner.get().current -= 1;
if 0 == self.inner.current {
self.inner.get().cycle += 1;
self.inner.get().current = self.inner.initial;
self.inner.mtx.unlock();
self.inner.cnd.notify_all();
return true;
} else {
self.inner
.cnd
.wait_pred(&self.inner.mtx, || cycle != self.inner.cycle);
}
self.inner.mtx.unlock();
false
}
}