libpool/
lib.rs

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}