use std::sync::Arc;
use std::sync::atomic::{AtomicU8, Ordering};
#[cfg(feature = "debug_mode")]
use cbsk_base::log;
use rayon::{ThreadPool, ThreadPoolBuilder};
#[derive(Clone)]
pub struct PoolDetail {
pub thread_pool: Arc<ThreadPool>,
pub used: Arc<AtomicU8>,
pub max: u8,
}
impl PoolDetail {
pub fn build() -> Self {
Self::try_build().expect("build thread pool fail")
}
pub fn try_build() -> Result<Self, rayon::ThreadPoolBuildError> {
Ok(Self {
thread_pool: ThreadPoolBuilder::new().num_threads(10).build()?.into(),
used: Arc::new(AtomicU8::new(0)),
max: 10,
})
}
pub fn spawn(&self, f: impl FnOnce() + Send + 'static) {
if self.used.fetch_add(1, Ordering::Release) == u8::MAX {
self.used.store(u8::MAX, Ordering::Release)
}
#[cfg(feature = "debug_mode")] {
let used = self.used.load(Ordering::Acquire);
log::info!("run thread, used is {used}");
}
let pool = self.clone();
self.thread_pool.spawn(move || {
f();
if pool.used.fetch_sub(1, Ordering::Release) == u8::MIN {
pool.used.store(u8::MIN, Ordering::Release)
}
#[cfg(feature = "debug_mode")] {
let used = pool.used.load(Ordering::Acquire);
log::info!("thread release, used is {used}");
}
})
}
pub fn is_idle(&self) -> bool {
self.used.load(Ordering::Acquire) < self.max
}
}