use super::{ Fuse, Bomb, Flame, spin, SPIN_ITERATIONS };
pub type MultiFuze<T> = MultiFuse<T>;
#[derive(Clone)]
pub struct MultiBomb<T: Clone> {
inner: Bomb<(MultiBomb<T>, T)>
}
pub struct MultiFuse<T: Clone> {
inner: Fuse<(MultiBomb<T>, T)>
}
impl<T: Clone> MultiBomb<T> {
pub fn new() -> (MultiFuse<T>, MultiBomb<T>) {
let fuse = MultiFuse::new();
let bomb = Self {
inner: Bomb {
data: fuse.inner.data.clone(),
}
};
(fuse, bomb)
}
pub fn exploded(&mut self) -> Option<T> {
let (new_bomb, value) = match self.inner.exploded() {
None => return None,
Some(data) => data.clone()
};
self.inner = new_bomb.inner;
Some(value)
}
pub fn wait_for_explosion(&mut self) -> T {
if let Some(value) = spin(SPIN_ITERATIONS, || self.exploded()) {
return value;
}
let (new_bomb, value) = self.inner.wait_for_explosion().clone();
self.inner = new_bomb.inner;
value
}
}
impl<T: Clone> MultiFuse<T> {
fn new() -> Self {
Self {
inner: Fuse::new(),
}
}
pub fn ignite(&mut self, value: T) -> Flame {
self.light(value)
}
pub fn light(&mut self, value: T) -> Flame {
let (fuse, bomb) = MultiBomb::new();
let old_fuse = std::mem::replace(&mut self.inner, fuse.inner);
old_fuse.light((bomb, value))
}
}