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}