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