simple_rw_global/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2//! Simple GlobalContainer based on std::sync::RwLock.
3//!
4//! This crate is AS IS.
5//!
6//! NOTE: `GlobalContainer` use `RWLock`, `GlobalMutexContainer` use `Mutex`.
7//!
8//! By ZRY.
9//!
10//! # Features
11//!
12//! ## `tokio`
13//!
14//! For tokio, use feature `tokio`
15//!
16//! ```toml
17//! [dependency]
18//! simple-rw-global = { version="0.3.0", feature=["tokio"] }
19//! ```
20//!
21//! With this feature, module `tokio` is available.
22//!
23//! # Example
24//!
25//! ```
26//! use simple_rw_global::GlobalContainer;
27//!
28//! static GLOBAL : GlobalContainer<GlobalObject> = GlobalContainer::<GlobalObject>::new();
29//!
30//! pub struct GlobalObject {
31//!     log_prefix: String,
32//! }
33//!
34//! impl GlobalObject {
35//!     pub fn new(prefix: &str) -> GlobalObject {
36//!         GlobalObject{log_prefix: String::from(prefix)}
37//!     }
38//!
39//!     pub fn log(&self, msg: &str) {
40//!         println!("[{}] {}", self.log_prefix.as_str(), msg);
41//!     }
42//!
43//!     pub fn change_prefix(&mut self, prefix: &str) {
44//!         self.log_prefix = String::from(prefix);
45//!     }
46//! }
47//!
48//! fn main() {
49//!     println!("before init, is empty: {}", GLOBAL.is_empty());
50//!     GLOBAL.set(GlobalObject::new("log-test1"));
51//!     println!("after init, is empty: {}", GLOBAL.is_empty());
52//!     println!("init ok.");
53//!     GLOBAL.get().log("hello 1");
54//!     GLOBAL.get_mut().change_prefix("log-test2");
55//!     GLOBAL.get().log("hello 2");
56//!     GLOBAL.manual_drop();
57//!     println!("dropped manually. will panic then.");
58//!     GLOBAL.get().log("test after drop.");
59//! }
60//!
61//! ```
62//!
63//!
64
65
66#[cfg(feature = "tokio")]
67#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
68pub mod tokio;
69
70use std::ops::{Deref, DerefMut};
71#[cfg(feature = "stdsync")]
72use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard, Mutex, MutexGuard};
73
74pub enum GOption<T> {
75    None,
76    Some(T)
77}
78
79impl<T> Deref for GOption<T> {
80    type Target = T;
81
82    fn deref(&self) -> &Self::Target {
83        match self {
84            GOption::None => { panic!("operate on empty GlobalContainer"); },
85            GOption::Some(t) => t,
86        }
87    }
88}
89
90impl<T> DerefMut for GOption<T> {
91
92    fn deref_mut(&mut self) -> &mut Self::Target {
93        match self {
94            GOption::None => { panic!("operate on empty GlobalContainer"); },
95            GOption::Some(t) => t,
96        }
97    }
98}
99
100#[cfg(feature = "stdsync")]
101pub struct GlobalContainer<T>
102{
103    content: RwLock<GOption<T>>,
104}
105
106#[cfg(feature = "stdsync")]
107impl<T> GlobalContainer<T> {
108    pub const fn new() -> GlobalContainer<T> {
109        GlobalContainer::<T>{
110            content: RwLock::new(GOption::None),
111        }
112    }
113
114    pub fn set(&self, obj: T) {
115        *self.content.write().unwrap() = GOption::Some(obj);
116    }
117
118    pub fn is_empty(&self) -> bool {
119        let v = self.content.read().unwrap();
120        match v.deref() {
121            GOption::None => true,
122            GOption::Some(_) => false,
123        }
124    }
125
126    pub fn manual_drop(&self) {
127        *self.content.write().unwrap() = GOption::None;
128    }
129
130    pub fn get(&self) -> RwLockReadGuard<GOption<T>> {
131        self.content.read().unwrap()
132    }
133
134    pub fn get_mut(&self) -> RwLockWriteGuard<GOption<T>> {
135        self.content.write().unwrap()
136    }
137}
138
139#[cfg(feature = "stdsync")]
140impl<T> Drop for GlobalContainer<T> {
141    fn drop(&mut self) {
142        self.manual_drop();
143    }
144}
145
146#[cfg(feature = "stdsync")]
147pub struct GlobalMutexContainer<T>
148{
149    content: Mutex<GOption<T>>,
150}
151
152#[cfg(feature = "stdsync")]
153impl<T> GlobalMutexContainer<T> {
154    pub const fn new() -> GlobalMutexContainer<T> {
155        GlobalMutexContainer::<T>{
156            content: Mutex::new(GOption::None),
157        }
158    }
159
160    pub fn set(&self, obj: T) {
161        *self.content.lock().unwrap() = GOption::Some(obj);
162    }
163
164    pub fn is_empty(&self) -> bool {
165        let v = self.content.lock().unwrap();
166        match v.deref() {
167            GOption::None => true,
168            GOption::Some(_) => false,
169        }
170    }
171
172    pub fn manual_drop(&self) {
173        *self.content.lock().unwrap() = GOption::None;
174    }
175
176    pub fn get(&self) -> MutexGuard<GOption<T>> {
177        self.content.lock().unwrap()
178    }
179
180    pub fn get_mut(&self) -> MutexGuard<GOption<T>> {
181        self.content.lock().unwrap()
182    }
183}
184
185#[cfg(feature = "stdsync")]
186impl<T> Drop for GlobalMutexContainer<T> {
187    fn drop(&mut self) {
188        self.manual_drop();
189    }
190}