diff --git a/src/multithreading/mod.rs b/src/multithreading/mod.rs index 5c3ed53..71dabb6 100644 --- a/src/multithreading/mod.rs +++ b/src/multithreading/mod.rs @@ -4,24 +4,24 @@ //! threads are available. If so the pool will directly launch a new thread to run the supplied function. //! In case no threads are available the job will be stalled for execution until a thread is free to run the first //! stalled job. -//! +//! //! The pool will also keep track of all the handles that [`std::thread::spawn`] returns. Hence after executing a job //! the pool still queries the result of the function which can be retrieved any time after the submission. //! After retrieving the result of the function the handle is discarded and cannot be accessed again through the thread pool. -//! +//! //! # Threads //! The maximum number of threads to be used can be specified when creating a new thread pool. //! Alternatively the thread pool can be advised to automatically determine the recommend amount of threads to use. //! Note that this has its limitations due to possible side effects of sandboxing, containerization or vms. //! For further information see: [`thread::available_parallelism`] -//! +//! //! # Memory consumption over time //! The pool will store the handle for every thread launched constantly increasing the memory consumption. //! It should be noted that the pool won't perform any kind of cleanup of the stored handles, meaning it is recommended to either make regular calls to //! `join_all` or `get_finished` in order to clear the vector of handles to avoid endless memory consumption. //! Alternatively, you can use the function `with_threads_and_drop_handles` to create a new pool that discard all thread //! handles after the threads are finished. This will automatically reduce the memory consumption of the pool over time. -//! +//! //! # Portability //! This implementation is not fully platform independent. This is due to the usage of [`std::sync::atomic::AtomicUsize`]. //! This type is used to remove some locks from otherwise used [`std::sync::Mutex`] wrapping a [`usize`]. @@ -36,7 +36,7 @@ use std::{ collections::VecDeque, num::NonZeroUsize, sync::{ - atomic::{AtomicUsize, Ordering, AtomicBool}, + atomic::{AtomicBool, AtomicUsize, Ordering}, Arc, Mutex, }, thread::{self, JoinHandle}, @@ -90,13 +90,13 @@ fn get_default_thread_count() -> usize { /// Additionally this implementation relies on using the `load` and `store` operations /// instead of using more comfortable one like `fetch_add` in order to avoid unnecessary calls /// to `unwrap` or `expected` from [`std::sync::MutexGuard`]. -/// +/// /// # Memory consumption over time /// The pool will store the handle for every thread launched constantly increasing the memory consumption. /// It should be noted that the pool won't perform any kind of cleanup of the stored handles, meaning it is recommended to either make regular calls to /// `join_all` or `get_finished` in order to clear the vector of handles to avoid endless memory consumption. /// Alternatively, you can use the function `with_threads_and_drop_handles` to create a new pool that discard all thread -/// handles after the threads are finished. This will automatically reduce the memory consumption of the pool over time. +/// handles after the threads are finished. This will automatically reduce the memory consumption of the pool over time. #[allow(dead_code)] #[derive(Debug)] pub struct ThreadPool @@ -132,7 +132,7 @@ where // will be initialized to 0 threads: Arc::new(AtomicUsize::new(0)), // do not drop handles by default - drop_handles: Arc::new(AtomicBool::new(false)) + drop_handles: Arc::new(AtomicBool::new(false)), } } } @@ -173,10 +173,13 @@ where /// supplying a number of threads to great may negatively impact performance as the system may not /// be able to full fill the required needs /// # Memory usage - /// if `drop_handles` is set to [`Bool::false`] the pool will continue to store the handles of + /// if `drop_handles` is set to [`Bool::false`] the pool will continue to store the handles of /// launched threads. This causes memory consumption to rise over time as more and more /// threads are launched. - pub fn with_threads_and_drop_handles(max_thread_count: NonZeroUsize, drop_handles: bool) -> Self { + pub fn with_threads_and_drop_handles( + max_thread_count: NonZeroUsize, + drop_handles: bool, + ) -> Self { Self { max_thread_count: max_thread_count.get(), drop_handles: Arc::new(AtomicBool::new(drop_handles)), @@ -318,7 +321,13 @@ fn execute( let next = queue.lock().unwrap().pop_front(); if let Some(next_closure) = next { // if we have sth. to execute, spawn a new thread - execute(queue, handles_copy.clone(), threads, drop.clone(), next_closure); + execute( + queue, + handles_copy.clone(), + threads, + drop.clone(), + next_closure, + ); } else { // nothing to execute this thread will run out without any work to do // decrement the amount of used threads