use std::sync::{Arc, Mutex}; use std::sync::mpsc; use std::thread; trait FnBox { fn call_box(self: Box); } impl FnBox for F { fn call_box(self: Box) { (*self)(); } } type Job = Box; struct Worker { id: usize, thread: Option>, } enum Message { NewJob(Job), Terminate, } impl Worker { pub fn new(id: usize, receiver: Arc>>) -> Worker { Worker { id, thread: Some(thread::spawn(move || { loop { if let Ok(job) = receiver.lock().expect("unrecoverable poisened panicked thread state").recv() { match job { Message::NewJob(job) => { println!("such busy, so worker #{}!", id); job.call_box(); } Message::Terminate => { println!("such sad, so dead #{}!", id); break; } } } else { // TODO respawn? (unless in terminate mode) // or why would the recv fail? already terminated? // thread panic not handled? break; } } })), } } } pub struct ThreadPool { workers: Vec, sender: mpsc::Sender, } impl Drop for ThreadPool { fn drop(&mut self) { // Each worker will only receive Terminate once for _ in &mut self.workers { self.sender.send(Message::Terminate).unwrap(); } // Each worker will join once complete for worker in &mut self.workers { println!("Shutting down worker {} ...", worker.id); if let Some(thread) = worker.thread.take() { thread.join().unwrap(); println!("Killed {}!", worker.id); } } } } impl ThreadPool { pub fn new(size: usize) -> ThreadPool { assert!(size > 0); let (sender, receiver) = mpsc::channel(); let receiver = Arc::new(Mutex::new(receiver)); let mut workers = Vec::with_capacity(size); for id in 0..size { workers.push(Worker::new(id, Arc::clone(&receiver))) } //ThreadPool.max = size; ThreadPool { workers, sender, } } pub fn run(&self, task: F) { let task = Box::new(task); self.sender.send(Message::NewJob(task)).unwrap(); } }