singleton_attr_proc_macro/
lib.rs1#![feature(proc_macro_span)]
2extern crate proc_macro;
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, ItemStruct};
6
7#[proc_macro_derive(Singleton)]
8pub fn singleton_derive(item: TokenStream) -> TokenStream {
9 let input = parse_macro_input!(item as ItemStruct);
10 let name = &input.ident;
11
12 TokenStream::from(quote! {
13 const _: () = {
14 static mut __INSTANCE: *mut #name = std::ptr::null_mut();
15
16 impl singleton_attr::traits::Singleton for #name {
17 #[inline]
18 fn init_instance(instance: Self) {
19 unsafe {
20 __INSTANCE = std::alloc::alloc(std::alloc::Layout::new::<Self>()) as *mut Self;
21 std::ptr::write_volatile(__INSTANCE, instance);
22 }
23 }
24
25 #[inline]
26 fn get_instance() -> &'static mut Self {
27 unsafe {
28 if __INSTANCE.is_null() {
29 Self::init_instance(Self::default());
30 }
31 &mut *__INSTANCE
32 }
33 }
34 }
35
36 impl Drop for #name {
37 fn drop(&mut self) {
38 unsafe { std::alloc::dealloc(__INSTANCE as *mut u8, std::alloc::Layout::new::<Self>()); }
39 }
40 }
41 };
42 })
43}
44
45#[proc_macro_derive(SafeSingleton)]
46pub fn singleton_safe_derive(item: TokenStream) -> TokenStream {
47 let input = parse_macro_input!(item as ItemStruct);
48 let name = &input.ident;
49
50 TokenStream::from(quote! {
51 const _: () = {
52 static mut __INSTANCE: Option<std::sync::Arc<std::sync::Mutex<#name>>> = None;
53
54 impl singleton_attr::traits::SafeSingleton for #name {
55 #[inline]
56 fn init_instance(instance: Self) {
57 unsafe {
58 __INSTANCE = Some(std::sync::Arc::new(std::sync::Mutex::new(instance)));
59 }
60 }
61
62 #[inline]
63 fn get_instance() -> std::sync::LockResult<std::sync::MutexGuard<'static, Self>> {
64 unsafe {
65 if let None = __INSTANCE {
66 Self::init_instance(Self::default());
67 }
68
69 __INSTANCE.as_ref().unwrap().lock()
70 }
71 }
72 }
73 };
74 })
75}