std_threadpool/
lib.rs

1//!Basic thread pool implementation using some code from the rust book.
2//!
3//!Basic usage:
4//!```
5//!//create a new thread pool with the specified number of threads
6//!let workers: ThreadPool = ThreadPool::new(4);
7//!
8//!//execute a closure from the thread pool
9//!workers.execute(|| {
10//!    println!("Hello from a worker thread!");
11//!});
12//!```
13
14use std::{
15    sync::{mpsc, Arc, Mutex},
16    thread,
17};
18
19type Res<T> = Result<T, Box<dyn std::error::Error>>;
20
21type Job = Box<dyn FnOnce() + Send + 'static>;
22
23#[allow(dead_code)]
24pub struct ThreadPool {
25    workers: Vec<Worker>,
26    sender: mpsc::Sender<Job>,
27}
28
29#[allow(dead_code)]
30struct Worker {
31    id: usize,
32    thread: thread::JoinHandle<()>,
33}
34
35impl ThreadPool {
36    pub fn new(size: usize) -> ThreadPool {
37        assert!(size > 0);
38
39        let (sender, receiver) = mpsc::channel();
40
41        let receiver = Arc::new(Mutex::new(receiver));
42
43        let mut workers = Vec::with_capacity(size);
44
45        for id in 0..size {
46            workers.push(Worker::new(id, Arc::clone(&receiver)));
47        }
48
49        ThreadPool { workers, sender }
50    }
51
52    pub fn execute<F>(&self, f: F) -> Res<()>
53    where
54        F: FnOnce() + Send + 'static,
55    {
56        let job = Box::new(f);
57
58        self.sender.send(job)?;
59
60        Ok(())
61    }
62}
63
64impl Worker {
65    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
66        let thread = thread::spawn(move || loop {
67            if let Ok(reciever_channel) = receiver.lock() {
68                if let Ok(job) = reciever_channel.recv() {
69                    job();
70                }
71            }
72        });
73
74        Worker { id, thread }
75    }
76}