open_coroutine_core/common/
beans.rs1use dashmap::DashMap;
2use std::ffi::c_void;
3use std::sync::atomic::{AtomicUsize, Ordering};
4
5#[repr(C)]
7#[derive(Debug, Default)]
8pub struct BeanFactory<'b>(DashMap<&'b str, usize>);
9
10impl BeanFactory<'_> {
11 fn get_instance<'i>() -> &'i BeanFactory<'i> {
12 static INSTANCE: AtomicUsize = AtomicUsize::new(0);
13 let mut ret = INSTANCE.load(Ordering::Relaxed);
14 if ret == 0 {
15 let ptr: &'i mut BeanFactory = Box::leak(Box::default());
16 ret = std::ptr::from_mut(ptr) as usize;
17 INSTANCE.store(ret, Ordering::Relaxed);
18 }
19 unsafe { &*(ret as *mut BeanFactory) }
20 }
21
22 pub fn init_bean<B>(bean_name: &str, bean: B) {
24 let factory = Self::get_instance();
25 if factory.0.get(bean_name).is_none() {
26 let bean: &B = Box::leak(Box::new(bean));
27 assert!(factory
28 .0
29 .insert(
30 Box::leak(Box::from(bean_name)),
31 std::ptr::from_ref(bean) as usize,
32 )
33 .is_none());
34 }
35 }
36
37 #[must_use]
39 pub fn remove_bean<B>(bean_name: &str) -> Option<B> {
40 Self::get_instance()
41 .0
42 .remove(bean_name)
43 .map(|(_, ptr)| unsafe { *Box::from_raw((ptr as *mut c_void).cast::<B>()) })
44 }
45
46 #[must_use]
48 pub fn get_bean<B>(bean_name: &str) -> Option<&B> {
49 Self::get_instance()
50 .0
51 .get(bean_name)
52 .map(|ptr| unsafe { &*(*ptr as *mut c_void).cast::<B>() })
53 }
54
55 #[allow(clippy::mut_from_ref)]
60 #[must_use]
61 pub unsafe fn get_mut_bean<B>(bean_name: &str) -> Option<&mut B> {
62 Self::get_instance()
63 .0
64 .get_mut(bean_name)
65 .map(|ptr| &mut *(*ptr as *mut c_void).cast::<B>())
66 }
67
68 #[must_use]
70 pub fn get_or_default<B: Default>(bean_name: &str) -> &B {
71 let factory = Self::get_instance();
72 factory.0.get(bean_name).map_or_else(
73 || {
74 let bean: &B = Box::leak(Box::default());
75 _ = factory.0.insert(
76 Box::leak(Box::from(bean_name)),
77 std::ptr::from_ref(bean) as usize,
78 );
79 bean
80 },
81 |ptr| unsafe { &*(*ptr as *mut c_void).cast::<B>() },
82 )
83 }
84
85 #[must_use]
90 #[allow(clippy::mut_from_ref)]
91 pub unsafe fn get_mut_or_default<B: Default>(bean_name: &str) -> &mut B {
92 let factory = Self::get_instance();
93 factory.0.get_mut(bean_name).map_or_else(
94 || {
95 let bean: &mut B = Box::leak(Box::default());
96 _ = factory.0.insert(
97 Box::leak(Box::from(bean_name)),
98 std::ptr::from_ref(bean) as usize,
99 );
100 bean
101 },
102 |ptr| &mut *(*ptr as *mut c_void).cast::<B>(),
103 )
104 }
105}