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