use std::sync::{Arc, Mutex};
use std::collections::HashMap;
use {Signal, ArmedSignal, Pulse, Waiting, Barrier, Signals};
pub struct Inner {
pub ready: Vec<usize>,
pub trigger: Option<Pulse>,
}
pub struct Handle(pub Arc<Mutex<Inner>>);
pub struct Select {
inner: Arc<Mutex<Inner>>,
signals: HashMap<usize, ArmedSignal>,
}
impl Select {
pub fn new() -> Select {
Select {
inner: Arc::new(Mutex::new(Inner {
ready: Vec::new(),
trigger: None,
})),
signals: HashMap::new(),
}
}
pub fn add(&mut self, pulse: Signal) -> usize {
let id = pulse.id();
let p = pulse.arm(Waiting::select(Handle(self.inner.clone())));
self.signals.insert(id, p);
id
}
pub fn remove(&mut self, id: usize) -> Option<Signal> {
self.signals
.remove(&id)
.map(|x| x.disarm())
}
pub fn into_barrier(self) -> Barrier {
let vec: Vec<Signal> = self.signals
.into_iter()
.map(|(_, p)| p.disarm())
.collect();
Barrier::new(&vec)
}
pub fn try_next(&mut self) -> Option<Signal> {
let mut guard = self.inner.lock().unwrap();
if let Some(x) = guard.ready.pop() {
return Some(self.signals.remove(&x).map(|x| x.disarm()).unwrap());
}
None
}
pub fn len(&self) -> usize {
self.signals.len()
}
}
impl Iterator for Select {
type Item = Signal;
fn next(&mut self) -> Option<Signal> {
loop {
if self.signals.len() == 0 {
return None;
}
let pulse = {
let mut guard = self.inner.lock().unwrap();
while let Some(x) = guard.ready.pop() {
if let Some(x) = self.signals.remove(&x) {
return Some(x.disarm());
}
}
let (pulse, t) = Signal::new();
guard.trigger = Some(t);
pulse
};
pulse.wait().unwrap();
}
}
}
impl Signals for Select {
fn signal(&self) -> Signal {
let (pulse, t) = Signal::new();
let mut guard = self.inner.lock().unwrap();
if guard.ready.len() == 0 {
guard.trigger = Some(t);
} else {
t.pulse();
}
pulse
}
}
pub struct SelectMap<T> {
select: Select,
items: HashMap<usize, T>,
}
impl<T> SelectMap<T> {
pub fn new() -> SelectMap<T> {
SelectMap {
select: Select::new(),
items: HashMap::new(),
}
}
pub fn add(&mut self, signal: Signal, value: T) {
let id = self.select.add(signal);
self.items.insert(id, value);
}
pub fn try_next(&mut self) -> Option<(Signal, T)> {
self.select.try_next().map(|x| {
let id = x.id();
(x, self.items.remove(&id).unwrap())
})
}
pub fn len(&self) -> usize {
self.items.len()
}
}
impl<T> Iterator for SelectMap<T> {
type Item = (Signal, T);
fn next(&mut self) -> Option<(Signal, T)> {
self.select.next().map(|x| {
let id = x.id();
(x, self.items.remove(&id).unwrap())
})
}
}
impl<T> Signals for SelectMap<T> {
fn signal(&self) -> Signal {
self.select.signal()
}
}