Skip to main content

hashtree_cli/
runtime_config.rs

1use std::sync::OnceLock;
2
3pub const DEFAULT_MAX_BLOCKING_THREADS: usize = 64;
4const MIN_MAX_BLOCKING_THREADS: usize = 8;
5const MAX_MAX_BLOCKING_THREADS: usize = 512;
6const MAX_BLOCKING_THREADS_ENV: &str = "HTREE_MAX_BLOCKING_THREADS";
7
8const _: () = {
9    assert!(MIN_MAX_BLOCKING_THREADS >= 4);
10    assert!(DEFAULT_MAX_BLOCKING_THREADS >= MIN_MAX_BLOCKING_THREADS);
11    assert!(DEFAULT_MAX_BLOCKING_THREADS <= MAX_MAX_BLOCKING_THREADS);
12};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct RuntimeCapacity {
16    pub max_blocking_threads: usize,
17    pub cpu_parallelism: usize,
18}
19
20impl RuntimeCapacity {
21    fn from_process() -> Self {
22        let requested = std::env::var(MAX_BLOCKING_THREADS_ENV)
23            .ok()
24            .and_then(|value| value.parse::<usize>().ok())
25            .filter(|value| *value > 0)
26            .unwrap_or(DEFAULT_MAX_BLOCKING_THREADS);
27        let max_blocking_threads =
28            requested.clamp(MIN_MAX_BLOCKING_THREADS, MAX_MAX_BLOCKING_THREADS);
29        if requested != max_blocking_threads {
30            eprintln!(
31                "{MAX_BLOCKING_THREADS_ENV}={requested} is outside the safe range; \
32                 using {max_blocking_threads}"
33            );
34        }
35
36        Self {
37            max_blocking_threads,
38            cpu_parallelism: std::thread::available_parallelism()
39                .map(usize::from)
40                .unwrap_or(4)
41                .max(1),
42        }
43    }
44}
45
46pub fn runtime_capacity() -> &'static RuntimeCapacity {
47    static CAPACITY: OnceLock<RuntimeCapacity> = OnceLock::new();
48    CAPACITY.get_or_init(RuntimeCapacity::from_process)
49}