threadpool-simple 0.1.12

Simple Threadpool for working with many tasks easily
Documentation
//! # ThreadPool
//! A thread pool for working with tasks.
//! 
//! Features:
//! * Bug fixes
//! * Optimization
//! 
//! # Attention
//! The `ThreadPool` is under development.

use std::thread;
use std::sync::{Mutex, Arc, mpsc};
use std::time::Duration;
/// Alias for the type of a job, representing a closure or function that takes no arguments and does not return a value.
type Job = Box<dyn FnOnce() + Send + 'static>;

/// # ThreadPool
/// [`ThreadPool`] - Struct representing a thread pool.
/// # Example
/// Create an instance of `ThreadPool`:
/// ```
/// 
/// let pool = ThreadPool::new(10);
/// ```
/// 
/// This will create `10` workers (threads).  
/// 
/// Than you will able to use `execute` method, which will start task execution.
/// 
/// And since this method gets a closure or a regular function in the parameter:
/// ## #1
/// ```
/// pool.execute(|| { 
///     println!("Yoo!"); 
/// });
///  
/// ```
/// ## #2
/// ```
/// pool.execute(some_function);
/// ```
pub struct ThreadPool {
    pub workers: Vec<Worker>,
    pub sender: mpsc::Sender<Job>,
}

impl ThreadPool {
    /// Creates a new thread pool with the specified size.
    ///
    /// # Arguments
    ///
    /// * `size` - The number of threads in the thread pool.
    ///
    /// # Panics
    ///
    /// Panics if the `size` is 0.
    pub fn new(size: usize) -> Self {
        assert!(size > 0);

        let (sender, receiver) = mpsc::channel();
        let receiver = Arc::new(Mutex::new(receiver));
        let mut workers = Vec::with_capacity(size);

        for id in 0..size {
            workers.push(
                Worker::new(
                    id,
                    Arc::clone(&receiver)));
        }

        ThreadPool {
            workers, 
            sender
        }
    }

    /// Executes a job in the thread pool.
    ///
    /// # Arguments
    ///
    /// * `f` - The closure or function representing the job to be executed.
    ///
    /// # Example
    ///
    /// ```
    /// let pool = ThreadPool::new(4);
    ///
    /// pool.execute(move || {
    ///     println!("Working on a job");
    /// });
    /// ```
    pub fn execute<F>(&self, f: F)
        where
            F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);
        self.sender
            .send(job)
            .expect("Error while sending job to pool");
    }
}

/// Struct representing a worker in the thread pool.
pub struct Worker {
    id: usize,
    thread: thread::JoinHandle<()>,
}

impl Worker {
    /// Creates a new worker associated with the given ID and the receiver for job messages.
    ///
    ///! # Arguments
    ///!
    ///! * `id` - The ID of the worker.
    ///! * `receiver` - The receiver for job messages.
    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
        let thread = thread::spawn(move || loop {
            let job = receiver
                .lock()
                .unwrap()
                .recv()
                .unwrap();
            println!("[thread{}] STARTED WORKING", id);
            job();
        });

        Worker { id, thread }
    }
}