lib.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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. #[cfg(feature = "tokio")]
  65. #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
  66. pub mod tokio;
  67. use std::ops::{Deref, DerefMut};
  68. #[cfg(feature = "stdsync")]
  69. use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard, Mutex, MutexGuard};
  70. pub enum GOption<T> {
  71. None,
  72. Some(T)
  73. }
  74. impl<T> Deref for GOption<T> {
  75. type Target = T;
  76. fn deref(&self) -> &Self::Target {
  77. match self {
  78. GOption::None => { panic!("operate on empty GlobalContainer"); },
  79. GOption::Some(t) => t,
  80. }
  81. }
  82. }
  83. impl<T> DerefMut for GOption<T> {
  84. fn deref_mut(&mut self) -> &mut Self::Target {
  85. match self {
  86. GOption::None => { panic!("operate on empty GlobalContainer"); },
  87. GOption::Some(t) => t,
  88. }
  89. }
  90. }
  91. #[cfg(feature = "stdsync")]
  92. pub struct GlobalContainer<T>
  93. {
  94. content: RwLock<GOption<T>>,
  95. }
  96. #[cfg(feature = "stdsync")]
  97. impl<T> GlobalContainer<T> {
  98. pub const fn new() -> GlobalContainer<T> {
  99. GlobalContainer::<T>{
  100. content: RwLock::new(GOption::None),
  101. }
  102. }
  103. pub fn set(&self, obj: T) {
  104. *self.content.write().unwrap() = GOption::Some(obj);
  105. }
  106. pub fn is_empty(&self) -> bool {
  107. let v = self.content.read().unwrap();
  108. match v.deref() {
  109. GOption::None => true,
  110. GOption::Some(_) => false,
  111. }
  112. }
  113. pub fn manual_drop(&self) {
  114. *self.content.write().unwrap() = GOption::None;
  115. }
  116. pub fn get(&self) -> RwLockReadGuard<GOption<T>> {
  117. self.content.read().unwrap()
  118. }
  119. pub fn get_mut(&self) -> RwLockWriteGuard<GOption<T>> {
  120. self.content.write().unwrap()
  121. }
  122. }
  123. #[cfg(feature = "stdsync")]
  124. impl<T> Drop for GlobalContainer<T> {
  125. fn drop(&mut self) {
  126. self.manual_drop();
  127. }
  128. }
  129. #[cfg(feature = "stdsync")]
  130. pub struct GlobalMutexContainer<T>
  131. {
  132. content: Mutex<GOption<T>>,
  133. }
  134. #[cfg(feature = "stdsync")]
  135. impl<T> GlobalMutexContainer<T> {
  136. pub const fn new() -> GlobalMutexContainer<T> {
  137. GlobalMutexContainer::<T>{
  138. content: Mutex::new(GOption::None),
  139. }
  140. }
  141. pub fn set(&self, obj: T) {
  142. *self.content.lock().unwrap() = GOption::Some(obj);
  143. }
  144. pub fn is_empty(&self) -> bool {
  145. let v = self.content.lock().unwrap();
  146. match v.deref() {
  147. GOption::None => true,
  148. GOption::Some(_) => false,
  149. }
  150. }
  151. pub fn manual_drop(&self) {
  152. *self.content.lock().unwrap() = GOption::None;
  153. }
  154. pub fn get(&self) -> MutexGuard<GOption<T>> {
  155. self.content.lock().unwrap()
  156. }
  157. pub fn get_mut(&self) -> MutexGuard<GOption<T>> {
  158. self.content.lock().unwrap()
  159. }
  160. }
  161. #[cfg(feature = "stdsync")]
  162. impl<T> Drop for GlobalMutexContainer<T> {
  163. fn drop(&mut self) {
  164. self.manual_drop();
  165. }
  166. }