async_global_executor/
config.rs1use std::{
2 fmt,
3 sync::{
4 atomic::{AtomicUsize, Ordering},
5 OnceLock,
6 },
7};
8
9pub(crate) static GLOBAL_EXECUTOR_CONFIG: OnceLock<Config> = OnceLock::new();
10
11#[derive(Default)]
13pub struct GlobalExecutorConfig {
14 env_var: Option<&'static str>,
16 min_threads: Option<usize>,
18 max_threads: Option<usize>,
20 thread_name_fn: Option<Box<dyn Fn() -> String + Send + Sync>>,
22}
23
24impl fmt::Debug for GlobalExecutorConfig {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 f.debug_struct("GlobalExecutorConfig")
27 .field("env_var", &self.env_var)
28 .field("min_threads", &self.min_threads)
29 .field("max_threads", &self.max_threads)
30 .finish()
31 }
32}
33
34impl GlobalExecutorConfig {
35 pub fn with_env_var(mut self, env_var: &'static str) -> Self {
37 self.env_var = Some(env_var);
38 self
39 }
40
41 pub fn with_min_threads(mut self, min_threads: usize) -> Self {
43 self.min_threads = Some(min_threads);
44 self
45 }
46
47 pub fn with_max_threads(mut self, max_threads: usize) -> Self {
51 self.max_threads = Some(max_threads);
52 self
53 }
54
55 pub fn with_thread_name_fn(
57 mut self,
58 thread_name_fn: impl Fn() -> String + Send + Sync + 'static,
59 ) -> Self {
60 self.thread_name_fn = Some(Box::new(thread_name_fn));
61 self
62 }
63
64 pub(crate) fn seal(self) -> Config {
65 let min_threads = std::env::var(self.env_var.unwrap_or("ASYNC_GLOBAL_EXECUTOR_THREADS"))
66 .ok()
67 .and_then(|threads| threads.parse().ok())
68 .or(self.min_threads)
69 .unwrap_or_else(|| std::thread::available_parallelism().map_or(1, usize::from))
70 .max(1);
71 let max_threads = self.max_threads.unwrap_or(min_threads * 4).max(min_threads);
72 Config {
73 min_threads,
74 max_threads,
75 thread_name_fn: self.thread_name_fn.unwrap_or_else(|| {
76 Box::new(|| {
77 static GLOBAL_EXECUTOR_NEXT_THREAD: AtomicUsize = AtomicUsize::new(1);
78 format!(
79 "async-global-executor-{}",
80 GLOBAL_EXECUTOR_NEXT_THREAD.fetch_add(1, Ordering::SeqCst)
81 )
82 })
83 }),
84 }
85 }
86}
87
88pub(crate) struct Config {
90 pub(crate) min_threads: usize,
91 pub(crate) max_threads: usize,
92 pub(crate) thread_name_fn: Box<dyn Fn() -> String + Send + Sync>,
93}
94
95impl Default for Config {
96 fn default() -> Self {
97 GlobalExecutorConfig::default().seal()
98 }
99}