threadpool_simple/
lib.rs

1//! # ThreadPool
2//! A thread pool for working with tasks.
3//! 
4//! Features:
5//! * Bug fixes
6//! * Optimization
7//! 
8//! # Attention
9//! The `ThreadPool` is under development.
10
11use std::thread;
12use std::sync::{Mutex, Arc, mpsc};
13use std::time::Duration;
14/// Alias for the type of a job, representing a closure or function that takes no arguments and does not return a value.
15type Job = Box<dyn FnOnce() + Send + 'static>;
16
17/// # ThreadPool
18/// [`ThreadPool`] - Struct representing a thread pool.
19/// # Example
20/// Create an instance of `ThreadPool`:
21/// ```
22/// 
23/// let pool = ThreadPool::new(10);
24/// ```
25/// 
26/// This will create `10` workers (threads).  
27/// 
28/// Than you will able to use `execute` method, which will start task execution.
29/// 
30/// And since this method gets a closure or a regular function in the parameter:
31/// ## #1
32/// ```
33/// pool.execute(|| { 
34///     println!("Yoo!"); 
35/// });
36///  
37/// ```
38/// ## #2
39/// ```
40/// pool.execute(some_function);
41/// ```
42pub struct ThreadPool {
43    pub workers: Vec<Worker>,
44    pub sender: mpsc::Sender<Job>,
45}
46
47impl ThreadPool {
48    /// Creates a new thread pool with the specified size.
49    ///
50    /// # Arguments
51    ///
52    /// * `size` - The number of threads in the thread pool.
53    ///
54    /// # Panics
55    ///
56    /// Panics if the `size` is 0.
57    pub fn new(size: usize) -> Self {
58        assert!(size > 0);
59
60        let (sender, receiver) = mpsc::channel();
61        let receiver = Arc::new(Mutex::new(receiver));
62        let mut workers = Vec::with_capacity(size);
63
64        for id in 0..size {
65            workers.push(
66                Worker::new(
67                    id,
68                    Arc::clone(&receiver)));
69        }
70
71        ThreadPool {
72            workers, 
73            sender
74        }
75    }
76
77    /// Executes a job in the thread pool.
78    ///
79    /// # Arguments
80    ///
81    /// * `f` - The closure or function representing the job to be executed.
82    ///
83    /// # Example
84    ///
85    /// ```
86    /// let pool = ThreadPool::new(4);
87    ///
88    /// pool.execute(move || {
89    ///     println!("Working on a job");
90    /// });
91    /// ```
92    pub fn execute<F>(&self, f: F)
93        where
94            F: FnOnce() + Send + 'static,
95    {
96        let job = Box::new(f);
97        self.sender
98            .send(job)
99            .expect("Error while sending job to pool");
100    }
101}
102
103/// Struct representing a worker in the thread pool.
104pub struct Worker {
105    id: usize,
106    thread: thread::JoinHandle<()>,
107}
108
109impl Worker {
110    /// Creates a new worker associated with the given ID and the receiver for job messages.
111    ///
112    ///! # Arguments
113    ///!
114    ///! * `id` - The ID of the worker.
115    ///! * `receiver` - The receiver for job messages.
116    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
117        let thread = thread::spawn(move || loop {
118            let job = receiver
119                .lock()
120                .unwrap()
121                .recv()
122                .unwrap();
123            println!("[thread{}] STARTED WORKING", id);
124            job();
125        });
126
127        Worker { id, thread }
128    }
129}