#![forbid(unsafe_code)]
use rayon::ThreadPool;
#[cfg(not(target_arch = "wasm32"))]
use std::num::NonZeroUsize;
#[cfg(not(target_arch = "wasm32"))]
use std::thread::available_parallelism;
use crate::ImageSize;
#[repr(C)]
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Default)]
pub enum ThreadingPolicy {
#[default]
Single,
Fixed(usize),
Adaptive,
}
impl ThreadingPolicy {
#[cfg(not(target_arch = "wasm32"))]
pub fn thread_count(&self, for_size: ImageSize) -> usize {
match self {
ThreadingPolicy::Single => 1,
ThreadingPolicy::Fixed(thread_count) => (*thread_count).max(1),
ThreadingPolicy::Adaptive => (for_size.width * for_size.height / (256 * 256))
.clamp(1, Self::available_parallelism()),
}
}
#[cfg(not(target_arch = "wasm32"))]
fn available_parallelism() -> usize {
available_parallelism()
.unwrap_or_else(|_| NonZeroUsize::new(1).unwrap())
.get()
}
#[cfg(target_arch = "wasm32")]
pub fn thread_count(&self, _: ImageSize) -> usize {
1
}
}
impl ThreadingPolicy {
#[cfg(not(target_arch = "wasm32"))]
pub fn get_pool(&self, for_size: ImageSize) -> Option<ThreadPool> {
if *self == ThreadingPolicy::Single {
return None;
}
let thread_count = self.thread_count(for_size);
rayon::ThreadPoolBuilder::new()
.num_threads(thread_count)
.build()
.ok()
}
pub(crate) fn get_nova_pool(&self, for_size: ImageSize) -> novtb::ThreadPool {
if *self == ThreadingPolicy::Single {
return novtb::ThreadPool::new(1);
}
let thread_count = self.thread_count(for_size);
novtb::ThreadPool::new(thread_count)
}
#[cfg(target_arch = "wasm32")]
pub fn get_pool(&self, _: ImageSize) -> Option<ThreadPool> {
None
}
}