1use std::{
7 sync::{mpsc, Arc, Mutex},
8 thread,
9};
10
11pub struct ThreadPool {
12 workers: Vec<Worker>,
13 sender: Option<mpsc::Sender<Job>>,
14}
15
16impl ThreadPool {
17 pub fn new(size: usize) -> ThreadPool {
25 assert!(size > 0);
26
27 let (sender, receiver) = mpsc::channel();
28
29 let receiver = Arc::new(Mutex::new(receiver));
30
31 let mut workers = Vec::with_capacity(size);
32
33 for id in 0..size {
34 workers.push(Worker::new(id, Arc::clone(&receiver)));
35 }
36
37 ThreadPool {
38 workers,
39 sender: Some(sender),
40 }
41 }
42
43 pub fn execute<F>(&self, f: F)
44 where
45 F: FnOnce() + Send + 'static,
46 {
47 let job = Box::new(f);
48
49 self.sender.as_ref().unwrap().send(job).unwrap();
50 }
51}
52
53impl Drop for ThreadPool {
54 fn drop(&mut self) {
55 drop(self.sender.take());
57
58 for worker in &mut self.workers {
60 println!("main: Shutting down worker {}", worker.id);
61
62 if let Some(thread) = worker.thread.take() {
63 thread.join().unwrap();
65 }
66 }
67 }
68}
69struct Worker {
70 id: usize,
71 thread: Option<thread::JoinHandle<()>>,
72}
73
74impl Worker {
75 fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
76 let thread = thread::spawn(move || loop {
77 let message = receiver.lock().unwrap().recv();
78
79 match message {
80 Ok(job) => {
81 println!("Thread: Worker {id} got a job; executing.");
82
83 job();
84 }
85 Err(_) => {
86 println!("Thread: Worker {id} disconnected; shutting down.");
87 break;
88 }
89 }
90 });
91
92 Worker {
93 id,
94 thread: Some(thread),
95 }
96 }
97}
98
99type Job = Box<dyn FnOnce() + Send + 'static>;