use std::thread;
use super::fixed_thread_pool::FixedThreadPool;
use crate::{
ExecutorServiceBuilderError,
ThreadPoolHooks,
};
const DEFAULT_FIXED_THREAD_NAME_PREFIX: &str = "qubit-fixed-thread-pool";
#[derive(Debug, Clone)]
pub struct FixedThreadPoolBuilder {
pub(crate) pool_size: usize,
pub(crate) queue_capacity: Option<usize>,
pub(crate) thread_name_prefix: String,
pub(crate) stack_size: Option<usize>,
pub(crate) hooks: ThreadPoolHooks,
}
impl FixedThreadPoolBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn pool_size(mut self, pool_size: usize) -> Self {
self.pool_size = pool_size;
self
}
pub fn queue_capacity(mut self, capacity: usize) -> Self {
self.queue_capacity = Some(capacity);
self
}
pub fn unbounded_queue(mut self) -> Self {
self.queue_capacity = None;
self
}
pub fn thread_name_prefix(mut self, prefix: &str) -> Self {
self.thread_name_prefix = prefix.to_owned();
self
}
pub fn stack_size(mut self, stack_size: usize) -> Self {
self.stack_size = Some(stack_size);
self
}
pub fn before_worker_start<F>(mut self, hook: F) -> Self
where
F: Fn(usize) + Send + Sync + 'static,
{
self.hooks = self.hooks.before_worker_start(hook);
self
}
pub fn after_worker_stop<F>(mut self, hook: F) -> Self
where
F: Fn(usize) + Send + Sync + 'static,
{
self.hooks = self.hooks.after_worker_stop(hook);
self
}
pub fn before_task<F>(mut self, hook: F) -> Self
where
F: Fn(usize) + Send + Sync + 'static,
{
self.hooks = self.hooks.before_task(hook);
self
}
pub fn after_task<F>(mut self, hook: F) -> Self
where
F: Fn(usize) + Send + Sync + 'static,
{
self.hooks = self.hooks.after_task(hook);
self
}
pub fn build(self) -> Result<FixedThreadPool, ExecutorServiceBuilderError> {
self.validate()?;
FixedThreadPool::new_with_builder(self)
}
fn validate(&self) -> Result<(), ExecutorServiceBuilderError> {
if self.pool_size == 0 {
return Err(ExecutorServiceBuilderError::ZeroPoolSize);
}
if self.queue_capacity == Some(0) {
return Err(ExecutorServiceBuilderError::ZeroQueueCapacity);
}
if self.stack_size == Some(0) {
return Err(ExecutorServiceBuilderError::ZeroStackSize);
}
Ok(())
}
}
impl Default for FixedThreadPoolBuilder {
fn default() -> Self {
Self {
pool_size: default_fixed_pool_size(),
queue_capacity: None,
thread_name_prefix: DEFAULT_FIXED_THREAD_NAME_PREFIX.to_owned(),
stack_size: None,
hooks: ThreadPoolHooks::default(),
}
}
}
fn default_fixed_pool_size() -> usize {
thread::available_parallelism()
.map(usize::from)
.unwrap_or(1)
}