#[must_use]
pub fn available_threads() -> usize {
#[cfg(windows)]
if let Some(n) = windows_affinity() {
return n;
}
std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
}
#[cfg(windows)]
fn windows_affinity() -> Option<usize> {
use windows_sys::Win32::System::Threading::{GetCurrentProcess, GetProcessAffinityMask};
let (mut process, mut system) = (0usize, 0usize);
#[allow(unsafe_code)]
let ok = unsafe { GetProcessAffinityMask(GetCurrentProcess(), &raw mut process, &raw mut system) };
(ok != 0 && process != 0).then(|| process.count_ones() as usize)
}
pub fn affinity_pool() -> Result<rayon::ThreadPool, rayon::ThreadPoolBuildError> {
rayon::ThreadPoolBuilder::new().num_threads(available_threads()).build()
}
#[cfg(test)]
mod tests {
#[test]
fn at_least_one_and_at_most_the_machine() {
let n = super::available_threads();
assert!(n >= 1);
#[cfg(windows)]
assert!(n <= std::thread::available_parallelism().map_or(usize::MAX, std::num::NonZeroUsize::get));
}
}