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}