hashtree_cli/
runtime_config.rs1use 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}