singleton_attr/
manual.rs

1#[macro_export]
2macro_rules! singleton_manual {
3    (
4        $([$($trait_bound:tt)+])?
5        $type:ident$(<$($inner_gen:ty),+>)?
6        $([$($outer_gen:ty),+])?
7        $(where [$($where_bound:tt)+])?
8        $(with [$($param_gen:ty),+])?
9    ) => {
10        static mut __INSTANCE: *mut $type$(<$($param_gen),+>)? = std::ptr::null_mut();
11
12        impl$(<$($trait_bound)+>)? singleton_attr::traits::Singleton for $type$(<$($outer_gen),+>)?
13        $(where $($where_bound)+)? {
14            #[inline]
15            fn init_instance(instance: Self) {
16                unsafe {
17                    __INSTANCE = std::alloc::alloc(std::alloc::Layout::new::<Self>()) as *mut Self;
18                    std::ptr::write_volatile(__INSTANCE, instance);
19                }
20            }
21
22            #[inline]
23            fn get_instance() -> &'static mut Self {
24                unsafe {
25                    if __INSTANCE.is_null() {
26                        Self::init_instance(Self::default());
27                    }
28                    &mut *__INSTANCE
29                }
30            }
31        }
32
33        impl$(<$($trait_bound)+>)? Drop for $type$(<$($outer_gen),+>)?
34        $(where $($where_bound)+)? {
35            fn drop(&mut self) {
36                unsafe { std::alloc::dealloc(__INSTANCE as *mut u8, std::alloc::Layout::new::<Self>()); }
37            }
38        }
39    };
40}
41
42#[macro_export]
43macro_rules! singleton_safe_manual {
44    (
45        $([$($trait_bound:tt)+])?
46        $type:ident$(<$($inner_gen:ty),+>)?
47        $([$($outer_gen:ty),+])?
48        $(where [$($where_bound:tt)+])?
49        $(with [$($param_gen:ty),+])?
50    ) => {
51        const _: () = {
52            static mut __INSTANCE: Option<std::sync::Arc<std::sync::Mutex<$type$(<$($param_gen),+>)?>>> = None;
53
54            impl$(<$($trait_bound)+>)? singleton_attr::traits::SafeSingleton for $type$(<$($outer_gen),+>)?
55            $(where $($where_bound)+)? {
56                #[inline]
57                fn init_instance(instance: Self) {
58                    unsafe {
59                        __INSTANCE = Some(std::sync::Arc::new(std::sync::Mutex::new(instance)));
60                    }
61                }
62
63                #[inline]
64                fn get_instance() -> std::sync::LockResult<std::sync::MutexGuard<'static, Self>> {
65                    unsafe {
66                        if let None = __INSTANCE {
67                            Self::init_instance(Self::default());
68                        }
69
70                        __INSTANCE.as_ref().unwrap().lock()
71                    }
72                }
73            }
74        };
75    };
76}