use std::thread;
+use std::sync::{Arc, mpsc, Mutex};
+
+type Job = Box<dyn FnOnce() + Send + 'static>;
struct Worker {
id: usize,
- thread: thread::JoinHandle<()>,
+ thread: Option<thread::JoinHandle<()>>,
}
impl Worker {
- fn new(id: usize) -> Worker {
- Worker { id, thread: thread::spawn(|| {}) }
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ let thread = Some(thread::spawn(move || loop {
+ let job = receiver.lock().unwrap().recv().unwrap();
+ println!("Worker {} got a job, executing", id);
+ job();
+ }));
+ Worker { id, thread }
}
}
pub struct ThreadPool {
workers: Vec<Worker>,
+ sender: mpsc::Sender<Job>,
}
impl ThreadPool {
assert!(size > 0);
let mut workers = Vec::with_capacity(size);
+ let (sender, receiver) = mpsc::channel();
+ let receiver = Arc::new(Mutex::new(receiver));
+
for id in 0..size {
- workers.push(Worker::new(id));
+ workers.push(Worker::new(id, Arc::clone(&receiver)));
}
- ThreadPool { workers }
+ ThreadPool { workers, sender }
}
pub fn execute<F>(&self, f: F)
where F: FnOnce() + Send + 'static
{
- thread::spawn(f);
+ self.sender.send(Box::new(f)).unwrap();
+ }
+}
+
+impl Drop for ThreadPool {
+ fn drop(&mut self) {
+ for worker in &mut self.workers {
+ println!("Shutting down worker {}", worker.id);
+
+ if let Some(thread) = worker.thread.take() {
+ thread.join().unwrap();
+ }
+ }
}
}