1pub fn default_worker_threads() -> usize {
15 if let Some(n) = std::env::var("ATD_WORKER_THREADS")
16 .ok()
17 .and_then(|s| s.parse::<usize>().ok())
18 .filter(|n| *n > 0)
19 {
20 return n;
21 }
22 std::thread::available_parallelism()
23 .map(|n| n.get().min(4))
24 .unwrap_or(2)
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30
31 fn env_lock() -> std::sync::MutexGuard<'static, ()> {
35 static LOCK: std::sync::OnceLock<std::sync::Mutex<()>> = std::sync::OnceLock::new();
36 LOCK.get_or_init(|| std::sync::Mutex::new(()))
37 .lock()
38 .unwrap_or_else(|p| p.into_inner())
39 }
40
41 #[test]
42 fn defaults_to_at_most_four() {
43 let _g = env_lock();
44 unsafe { std::env::remove_var("ATD_WORKER_THREADS") };
46 let n = default_worker_threads();
47 assert!((1..=4).contains(&n), "default {n} outside [1,4]");
48 }
49
50 #[test]
51 fn env_override_respected() {
52 let _g = env_lock();
53 unsafe { std::env::set_var("ATD_WORKER_THREADS", "8") };
54 let n = default_worker_threads();
55 unsafe { std::env::remove_var("ATD_WORKER_THREADS") };
56 assert_eq!(n, 8);
57 }
58
59 #[test]
60 fn env_zero_falls_back_to_default() {
61 let _g = env_lock();
62 unsafe { std::env::set_var("ATD_WORKER_THREADS", "0") };
63 let n = default_worker_threads();
64 unsafe { std::env::remove_var("ATD_WORKER_THREADS") };
65 assert!((1..=4).contains(&n), "fallback {n} outside [1,4]");
67 }
68
69 #[test]
70 fn env_garbage_falls_back_to_default() {
71 let _g = env_lock();
72 unsafe { std::env::set_var("ATD_WORKER_THREADS", "not-a-number") };
73 let n = default_worker_threads();
74 unsafe { std::env::remove_var("ATD_WORKER_THREADS") };
75 assert!((1..=4).contains(&n), "garbage fallback {n} outside [1,4]");
76 }
77}