use std::sync::{
Arc, Mutex,
mpsc,
mpsc::Sender
};
use crate::{
Bottle,
Heater,
Ice, IceBox,
};
pub struct Melter {
heaters: Vec<Heater>,
ice_boxes: Sender<IceBox>
}
impl Melter {
pub fn new(count: usize) -> Melter {
assert!(count > 0, "ice_threads::Melter::new -> Heater count must be greater than 0!");
let mut heaters = Vec::with_capacity(count);
let (sender, receiver) = mpsc::channel();
let receiver = Arc::new(Mutex::new(receiver));
for _ in 0..count {
heaters.push(Heater::new(receiver.clone()));
}
Melter {
heaters,
ice_boxes: sender
}
}
#[must_use]
pub fn melt<I, W>(&self, ice: I) -> Bottle<W>
where
I: FnOnce() -> W + Send + 'static,
W: Send + 'static
{
let (sender, receiver) = mpsc::channel::<W>();
let ice_box = IceBox::Some(
Ice::new(move || {
sender.send(ice()).ok();
})
);
self.ice_boxes
.send(ice_box)
.expect("ice_threads::Melter::melt -> Failed to send Ice box to a Heater group");
Bottle::new(receiver)
}
}
impl Drop for Melter {
fn drop(&mut self) {
for _ in &self.heaters {
if self.ice_boxes.send(IceBox::None).is_err() {
break;
}
}
for heater in &mut self.heaters {
if let Some(core) = heater.take_core() {
core.join().ok();
}
}
}
}