adze_concurrency_init_rayon_core/
lib.rs1#![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 std::sync::OnceLock;
11
12pub use adze_concurrency_init_classifier_core::is_already_initialized_error;
13
14pub fn init_rayon_global_once(num_threads: usize) -> Result<(), String> {
21 RAYON_INIT_RESULT
22 .get_or_init(|| init_rayon_global(num_threads.max(1)))
23 .clone()
24}
25
26static RAYON_INIT_RESULT: OnceLock<Result<(), String>> = OnceLock::new();
27
28fn init_rayon_global(num_threads: usize) -> Result<(), String> {
29 match rayon::ThreadPoolBuilder::new()
30 .num_threads(num_threads)
31 .build_global()
32 {
33 Ok(()) => Ok(()),
34 Err(error) => {
35 let message = error.to_string();
36 if is_already_initialized_error(&message) {
37 Ok(())
38 } else {
39 Err(message)
40 }
41 }
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::{init_rayon_global_once, is_already_initialized_error};
48
49 #[test]
50 fn init_is_idempotent() {
51 assert!(init_rayon_global_once(1).is_ok());
52 assert!(init_rayon_global_once(8).is_ok());
53 }
54
55 #[test]
56 fn already_initialized_error_classifier_is_case_insensitive() {
57 assert!(is_already_initialized_error(
58 "The GlObAl thread pool has AlReAdY been initialized"
59 ));
60 }
61
62 #[test]
63 fn already_initialized_error_classifier_requires_both_tokens() {
64 assert!(!is_already_initialized_error(
65 "thread pool already initialized"
66 ));
67 assert!(!is_already_initialized_error(
68 "global thread pool initialized"
69 ));
70 }
71
72 #[test]
73 fn init_with_zero_threads_normalizes_and_succeeds() {
74 assert!(init_rayon_global_once(0).is_ok());
75 }
76
77 #[test]
78 fn init_result_is_stable_across_different_thread_counts() {
79 let first = init_rayon_global_once(2);
80 let second = init_rayon_global_once(64);
81 assert_eq!(first, second);
82 }
83
84 #[test]
85 fn init_with_one_thread_succeeds() {
86 assert!(init_rayon_global_once(1).is_ok());
87 }
88
89 #[test]
90 fn init_with_large_thread_count_succeeds() {
91 assert!(init_rayon_global_once(1024).is_ok());
92 }
93}