use std::sync::Arc;
#[cfg(feature = "python")]
use std::sync::Weak;
pub(crate) type ThreadMain = fn(rayon::ThreadBuilder);
const THREAD_STACK_SIZE: usize = 8 << 20;
pub(super) struct LoaderPool {
pool: Arc<rayon::ThreadPool>,
threads: usize,
thread_main: Option<ThreadMain>,
pid: u32,
}
impl LoaderPool {
pub(super) fn new(threads: usize, thread_main: Option<ThreadMain>) -> Self {
let pool = rayon::ThreadPoolBuilder::new()
.num_threads(threads)
.thread_name(|i| format!("dataloader-{i}"))
.stack_size(THREAD_STACK_SIZE)
.spawn_handler(move |thread| {
let mut builder = std::thread::Builder::new();
if let Some(name) = thread.name() {
builder = builder.name(name.to_owned());
}
if let Some(size) = thread.stack_size() {
builder = builder.stack_size(size);
}
builder.spawn(move || match thread_main {
Some(main) => main(thread),
None => thread.run(),
})?;
Ok(())
})
.build()
.expect("failed to build rayon thread pool");
Self {
pool: Arc::new(pool),
threads,
thread_main,
pid: std::process::id(),
}
}
#[cfg(test)]
pub(super) fn threads(&self) -> usize {
self.threads
}
pub(super) fn get(&mut self) -> &Arc<rayon::ThreadPool> {
if self.pid != std::process::id() {
let fresh = Self::new(self.threads, self.thread_main);
std::mem::forget(std::mem::replace(self, fresh));
}
&self.pool
}
#[cfg(feature = "python")]
pub(super) fn handle(&self) -> Weak<rayon::ThreadPool> {
Arc::downgrade(&self.pool)
}
}