use core::fmt::{Debug, Formatter, Result as FmtResult};
use std::sync::{
mpsc::{channel, Sender},
Arc,
};
use crate::builder::Builder;
use crate::pool_inner::{Job, ThreadPoolInner};
pub struct ThreadPool {
tx: Sender<Job>,
inner: Arc<ThreadPoolInner>,
}
impl ThreadPool {
pub fn builder() -> Builder {
Default::default()
}
pub fn execute<F>(&self, job: F)
where
F: FnOnce() + Send + 'static,
{
let inner = &self.inner;
self.tx.send(Box::new(job)).unwrap();
if inner.inc_work_count() {
inner.spawn_thread(inner);
}
}
pub fn state(&self) -> ThreadPoolState {
let name = self.inner.name();
let (active_threads, max_threads) = self.inner.thread_count();
ThreadPoolState {
name,
active_threads,
max_threads,
}
}
}
impl From<Builder> for ThreadPool {
fn from(builder: Builder) -> Self {
let (tx, rx) = channel();
let inner = ThreadPoolInner::new(builder, rx);
let pool = ThreadPool {
tx,
inner: Arc::new(inner),
};
let inner = &pool.inner;
let min_idle = inner.min_idle_count();
(0..min_idle).for_each(|_| {
inner.spawn_thread(&inner);
});
pool
}
}
impl Clone for ThreadPool {
fn clone(&self) -> ThreadPool {
ThreadPool {
tx: self.tx.clone(),
inner: self.inner.clone(),
}
}
}
pub struct ThreadPoolState<'a> {
pub name: Option<&'a str>,
pub active_threads: usize,
pub max_threads: usize,
}
impl Debug for ThreadPool {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
self.state().fmt(f)
}
}
impl Debug for ThreadPoolState<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
f.debug_struct("ThreadPoolState")
.field("name", &self.name)
.field("active_threads", &self.active_threads)
.field("max_threads", &self.max_threads)
.finish()
}
}