use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use {Pulse, Signal, Waiting, Signals};
pub struct Inner {
pub count: AtomicUsize,
pub trigger: Mutex<Option<Pulse>>,
}
pub struct Barrier {
inner: Arc<Inner>,
}
pub struct Handle(pub Arc<Inner>);
impl Barrier {
pub fn new(pulses: &[Signal]) -> Barrier {
let inner = Arc::new(Inner {
count: AtomicUsize::new(pulses.len()),
trigger: Mutex::new(None),
});
for pulse in pulses {
pulse.clone().arm(Waiting::barrier(Handle(inner.clone())));
}
Barrier { inner: inner }
}
}
impl Signals for Barrier {
fn signal(&self) -> Signal {
let (p, t) = Signal::new();
let mut guard = self.inner.trigger.lock().unwrap();
if self.inner.count.load(Ordering::Relaxed) == 0 {
t.pulse();
} else {
*guard = Some(t);
}
p
}
}