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