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