static_instance/
lib.rs

1/// # static-instance
2///
3/// The `static-instance` crate provides a macro used to create safe
4/// static instances of objects. This was created in order to replicate
5/// the behavior of a static class member used frequently in C++. This
6/// allows exporting of rust to C via FFI a whole lot easier when the
7/// library needs to keep track of states.
8///
9/// #### NOTE
10/// It is still up to you to use the data inside the instance safely. The
11/// data inside the instance is not thread safe unless you make it thread
12/// safe.
13///
14///
15/// ```rust
16/// extern crate static_instance;
17///
18/// #[macro_use]
19/// use static_instance::{Instance, New};
20/// use std::sync::{Arc, Mutex};
21///
22/// #[derive(Clone)]
23/// struct SimpleCounter {
24///     counter: Arc<Mutex<Box<i32>>>
25/// }
26///
27/// impl SimpleCounter {
28///
29///     fn add(&mut self, value: i32) {
30///         let mut data = self.count.lock().unwrap();
31///         *data += 1;
32///     }
33///
34///     fn get_value(&self) -> i32 {
35///         let data: Box<i32> = self.count.lock().unwrap();
36///         return (*data).clone();
37///     }
38///
39///     fn print(&self) {
40///         let data: Box<i32> = self.count.lock().unwrap();
41///         println!("{}", *data);
42///     }
43/// }
44///
45/// impl New for SimpleCounter {
46///     fn new() -> SimpleCounter {
47///         SimpleCounter {
48///             counter: Arc::new(Mutex::new(Box::new(0)))
49///     }
50/// }
51/// 
52/// CreateInstance!(SimpleCounter);
53///
54/// fn main() {
55///     SimpleCounter::instance().add(30);
56///     SimpleCounter::instance().print();
57/// }
58/// ```
59
60#[allow(unused_imports)]
61use std::sync::Once;
62
63pub trait New {
64    fn new() -> Self;
65}
66
67pub trait Instance: New + Clone {
68    fn instance() -> Self;
69}
70
71#[macro_export]
72macro_rules! CreateInstance {
73    ($name:ident) => {
74        impl Instance for $name {
75            fn instance() -> $name {
76                static mut INSTANCE: *mut $name = 0 as *mut $name;
77                static ONCE: Once = Once::new();
78
79                unsafe {
80                    ONCE.call_once(|| {
81                        let instance = $name::new();
82                        INSTANCE = std::mem::transmute(Box::new(instance));
83                    });
84
85                    (*INSTANCE).clone()
86                }
87            }
88        }
89    };
90}