Skip to main content

adze_concurrency_init_bootstrap_core/
lib.rs

1//! Single-responsibility bootstrap for concurrency caps initialization.
2
3#![forbid(unsafe_op_in_unsafe_fn)]
4#![deny(missing_docs)]
5#![cfg_attr(feature = "strict_api", deny(unreachable_pub))]
6#![cfg_attr(not(feature = "strict_api"), warn(unreachable_pub))]
7#![cfg_attr(feature = "strict_docs", deny(missing_docs))]
8#![cfg_attr(not(feature = "strict_docs"), allow(missing_docs))]
9
10use adze_concurrency_env_core::current_caps;
11use adze_concurrency_init_bootstrap_policy_core::bootstrap_caps;
12use adze_concurrency_init_rayon_core::init_rayon_global_once;
13
14pub use adze_concurrency_env_core::{
15    ConcurrencyCaps, DEFAULT_RAYON_NUM_THREADS, DEFAULT_TOKIO_WORKER_THREADS,
16    RAYON_NUM_THREADS_ENV, TOKIO_WORKER_THREADS_ENV,
17};
18
19/// Initialize concurrency caps by reading the current process environment.
20pub fn init_concurrency_caps() {
21    init_concurrency_caps_with_caps(current_caps());
22}
23
24/// Initialize concurrency caps using an explicit configuration.
25pub fn init_concurrency_caps_with_caps(caps: ConcurrencyCaps) {
26    let caps = bootstrap_caps(caps);
27
28    if let Err(message) = init_rayon_global_once(caps.rayon_threads) {
29        panic!("failed to initialize rayon global thread pool: {message}");
30    }
31
32    eprintln!(
33        "Concurrency caps initialized: {RAYON_NUM_THREADS_ENV}={}, {TOKIO_WORKER_THREADS_ENV}={}",
34        caps.rayon_threads, caps.tokio_worker_threads
35    );
36}
37
38#[cfg(test)]
39mod tests {
40    use super::init_concurrency_caps_with_caps;
41    use adze_concurrency_env_core::{
42        ConcurrencyCaps, DEFAULT_RAYON_NUM_THREADS, DEFAULT_TOKIO_WORKER_THREADS,
43        RAYON_NUM_THREADS_ENV, TOKIO_WORKER_THREADS_ENV,
44    };
45    use adze_concurrency_init_bootstrap_policy_core::bootstrap_caps;
46
47    #[test]
48    fn init_with_zero_rayon_threads_normalizes_to_minimum() {
49        let caps = bootstrap_caps(ConcurrencyCaps {
50            rayon_threads: 0,
51            tokio_worker_threads: 2,
52        });
53        assert_eq!(caps.rayon_threads, 1);
54    }
55
56    #[test]
57    fn init_with_zero_is_idempotent() {
58        init_concurrency_caps_with_caps(ConcurrencyCaps {
59            rayon_threads: 0,
60            tokio_worker_threads: 2,
61        });
62        init_concurrency_caps_with_caps(ConcurrencyCaps {
63            rayon_threads: 0,
64            tokio_worker_threads: 2,
65        });
66    }
67
68    #[test]
69    fn init_with_positive_rayon_threads_succeeds() {
70        init_concurrency_caps_with_caps(ConcurrencyCaps {
71            rayon_threads: 4,
72            tokio_worker_threads: 2,
73        });
74    }
75
76    #[test]
77    fn bootstrap_preserves_nonzero_rayon_threads() {
78        let caps = bootstrap_caps(ConcurrencyCaps {
79            rayon_threads: 8,
80            tokio_worker_threads: 3,
81        });
82        assert_eq!(caps.rayon_threads, 8);
83    }
84
85    #[test]
86    fn reexported_defaults_are_accessible() {
87        assert_eq!(DEFAULT_RAYON_NUM_THREADS, 4);
88        assert_eq!(DEFAULT_TOKIO_WORKER_THREADS, 2);
89    }
90
91    #[test]
92    fn reexported_env_var_names_are_correct() {
93        assert_eq!(RAYON_NUM_THREADS_ENV, "RAYON_NUM_THREADS");
94        assert_eq!(TOKIO_WORKER_THREADS_ENV, "TOKIO_WORKER_THREADS");
95    }
96}