make_singleton_derive/
lib.rs1extern crate proc_macro;
2extern crate syn;
3#[macro_use]
4extern crate quote;
5
6use proc_macro::TokenStream;
7
8#[proc_macro_derive(MakeSingleton)]
9pub fn hello_world(input: TokenStream) -> TokenStream {
10 let s = input.to_string();
12
13 let ast = syn::parse_derive_input(&s).unwrap();
15
16 let gen = impl_make_singelton(&ast);
18
19 gen.parse().unwrap()
21}
22
23fn impl_make_singelton(ast: &syn::DeriveInput) -> quote::Tokens {
24 let name = &ast.ident;
25 quote! {
26
27 pub trait MakeSingletonTrait<T> {
28 fn instance_thread_safe() -> Arc<Mutex<T>>;
29 fn instance_ptr() -> *const T;
30 }
31
32
33 impl MakeSingletonTrait<#name> for #name {
34 fn instance_thread_safe() -> Arc<Mutex<#name>> {
35 unsafe {
36 static mut INSTANCE: *const Arc<Mutex<#name>> = 0 as *const Arc<Mutex<#name>>;
37 static ONCE: Once = Once::new();
38
39 ONCE.call_once(||{
40 let tmp_instance = Arc::new(Mutex::new(#name{}));
41 INSTANCE = mem::transmute(#name::instance_ptr());
42 });
43
44 (*INSTANCE).clone()
45 }
46 }
47
48 fn instance_ptr() -> *const #name {
49 unsafe {
50 static mut INSTANCE: *const #name = 0 as *const #name;
51 static ONCE: Once = Once::new();
52
53 ONCE.call_once(||{
54 let tmp_instance = #name{};
55 INSTANCE = mem::transmute(Box::new(tmp_instance));
56 });
57 INSTANCE
58 }
59 }
60 }
61 }
62}