dead_pool/
threadpool.rs

1use std::sync::{mpsc, Arc, Mutex};
2
3use crate::worker::Worker;
4
5pub type Job = Box<dyn FnOnce() + Send + 'static>;
6
7pub struct ThreadPool {
8    workers: Vec<Worker>,
9    sender: Option<mpsc::Sender<Job>>,
10}
11
12impl ThreadPool {
13    /// Creates a new thread pool with given number of threads.
14    ///
15    /// * Sets up a communication channel, and sends the receiver end to every thread.
16    /// * Jobs will be sent to threads via this communication channel.
17    pub fn new(size: usize) -> Self {
18        assert!(size != 0);
19
20        let (sender, receiver) = mpsc::channel();
21        let receiver = Arc::new(Mutex::new(receiver));
22
23        let mut workers = Vec::with_capacity(size);
24
25        for id in 0..size {
26            workers.push(Worker::new(id, Arc::clone(&receiver)));
27        }
28
29        Self {
30            workers,
31            sender: Some(sender),
32        }
33    }
34
35    /// Sends a Job to the thread pool.
36    ///
37    /// * Any one free thread picks up the Job and executes it.
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// let pool = ThreadPool::new(4);
43    /// for _ in 0..100 {
44    ///     pool.execute(|| {println!("Working");});
45    /// }
46    /// ```
47    pub fn execute<F>(&self, f: F)
48    where
49        F: FnOnce() + Send + 'static,
50    {
51        let job = Box::new(f);
52        self.sender.as_ref().unwrap().send(job).unwrap();
53    }
54}
55
56impl Drop for ThreadPool {
57    fn drop(&mut self) {
58        drop(self.sender.take());
59
60        for worker in &mut self.workers {
61            if let Some(thread) = worker.thread.take() {
62                thread.join().unwrap();
63            }
64        }
65    }
66}