hojicha_runtime/
shared_runtime.rs1use std::sync::{Arc, OnceLock};
7use tokio::runtime::{Builder, Runtime};
8
9static SHARED_RUNTIME: OnceLock<Arc<Runtime>> = OnceLock::new();
10
11pub fn shared_runtime() -> Arc<Runtime> {
13 SHARED_RUNTIME
14 .get_or_init(|| {
15 Arc::new(
16 Builder::new_multi_thread()
17 .worker_threads(get_cpu_count())
18 .thread_name("hojicha-async")
19 .enable_all()
20 .build()
21 .expect("Failed to create Tokio runtime"),
22 )
23 })
24 .clone()
25}
26
27#[derive(Debug, Clone)]
29pub struct RuntimeConfig {
30 pub worker_threads: Option<usize>,
32 pub thread_name_prefix: String,
34 pub enable_io: bool,
36 pub enable_time: bool,
38}
39
40impl Default for RuntimeConfig {
41 fn default() -> Self {
42 Self {
43 worker_threads: None,
44 thread_name_prefix: "hojicha-async".to_string(),
45 enable_io: true,
46 enable_time: true,
47 }
48 }
49}
50
51pub fn initialize_runtime(config: RuntimeConfig) -> Result<(), std::io::Error> {
53 if SHARED_RUNTIME.get().is_some() {
54 return Ok(()); }
56
57 let mut builder = Builder::new_multi_thread();
58
59 if let Some(threads) = config.worker_threads {
60 builder.worker_threads(threads);
61 } else {
62 builder.worker_threads(get_cpu_count());
63 }
64
65 builder.thread_name(&config.thread_name_prefix);
66
67 if config.enable_io && config.enable_time {
68 builder.enable_all();
69 } else {
70 if config.enable_io {
71 builder.enable_io();
72 }
73 if config.enable_time {
74 builder.enable_time();
75 }
76 }
77
78 let runtime = Arc::new(builder.build()?);
79 let _ = SHARED_RUNTIME.set(runtime);
80 Ok(())
81}
82
83fn get_cpu_count() -> usize {
85 std::thread::available_parallelism()
86 .map(|n| n.get())
87 .unwrap_or(4)
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_shared_runtime_singleton() {
96 let rt1 = shared_runtime();
97 let rt2 = shared_runtime();
98 assert!(Arc::ptr_eq(&rt1, &rt2));
99 }
100}