1use std::num::NonZero;
4use std::thread;
5
6pub const AVAILABLE_PARALLELISM_FALLBACK: usize = 4;
8
9pub const DEBUG_STACK_SIZE: usize = 8 * 1024 * 1024;
11
12#[must_use]
14pub fn available_worker_threads() -> usize {
15 thread::available_parallelism().map_or(AVAILABLE_PARALLELISM_FALLBACK, NonZero::get)
16}
17
18#[must_use]
21pub fn worker_threads_for_available(
22 configured_threads: Option<usize>,
23 available_threads: usize,
24) -> usize {
25 let available_threads = available_threads.max(1);
26 if let Some(configured_threads) = configured_threads.filter(|&threads| threads > 0) {
27 return configured_threads.min(available_threads);
28 }
29
30 ((available_threads / 2).max(2)).min(available_threads)
31}
32
33#[cfg(test)]
34mod tests {
35 use super::worker_threads_for_available;
36
37 #[test]
38 fn explicit_worker_count_is_capped_to_available_threads() {
39 assert_eq!(worker_threads_for_available(Some(16), 8), 8);
40 assert_eq!(worker_threads_for_available(Some(4), 8), 4);
41 }
42
43 #[test]
44 fn zero_or_missing_worker_count_uses_auto_default() {
45 assert_eq!(worker_threads_for_available(Some(0), 8), 4);
46 assert_eq!(worker_threads_for_available(None, 8), 4);
47 assert_eq!(worker_threads_for_available(None, 1), 1);
48 }
49}