use std::{num::NonZeroUsize, sync::Arc};
use crate::{YdbError, YdbResult};
pub trait Executor: Send + Sync {
fn available_parallelism(&self) -> NonZeroUsize;
fn spawn(&self, task: Box<dyn FnOnce() + Send + 'static>);
}
pub(crate) struct RayonExecutor {
pool: rayon::ThreadPool,
}
impl RayonExecutor {
pub(crate) fn new(num_threads: usize) -> YdbResult<Self> {
let pool = rayon::ThreadPoolBuilder::new()
.num_threads(num_threads)
.build()
.map_err(|err| YdbError::custom(format!("thread pool did not build: {err}")))?;
Ok(Self { pool })
}
}
const DEFAULT_THREAD_COUNT: usize = 4;
impl Executor for RayonExecutor {
fn available_parallelism(&self) -> NonZeroUsize {
NonZeroUsize::new(self.pool.current_num_threads())
.unwrap_or(const { NonZeroUsize::new(1).unwrap() })
}
fn spawn(&self, task: Box<dyn FnOnce() + Send + 'static>) {
self.pool.spawn(task);
}
}
pub(crate) fn default_executor() -> YdbResult<Arc<dyn Executor>> {
let executor = RayonExecutor::new(DEFAULT_THREAD_COUNT)?;
Ok(Arc::new(executor))
}