|
@@ -0,0 +1,109 @@
|
|
|
+//! Async version for `tokio`, need feature `tokio`.
|
|
|
+//!
|
|
|
+//! `lazy_static!` should be used for `AsyncGlobalContainer::new()`,
|
|
|
+//! because of `tokio::sync::RwLock::new()` is not a constant function.
|
|
|
+//!
|
|
|
+//! # Example
|
|
|
+//!
|
|
|
+//! ```rust
|
|
|
+//!
|
|
|
+//! use std::time::Duration;
|
|
|
+//! use lazy_static::lazy_static;
|
|
|
+//! use simple_rw_global::tokio::AsyncGlobalContainer;
|
|
|
+//! use tokio::task::JoinSet;
|
|
|
+//!
|
|
|
+//! lazy_static! {
|
|
|
+//! static ref GLOBAL : AsyncGlobalContainer<GlobalObject> = AsyncGlobalContainer::<GlobalObject>::new();
|
|
|
+//! }
|
|
|
+//!
|
|
|
+//! pub struct GlobalObject {
|
|
|
+//! log_prefix: String,
|
|
|
+//! }
|
|
|
+//!
|
|
|
+//! impl GlobalObject {
|
|
|
+//! pub fn new(prefix: &str) -> GlobalObject {
|
|
|
+//! GlobalObject{log_prefix: String::from(prefix)}
|
|
|
+//! }
|
|
|
+//!
|
|
|
+//! pub fn log(&self, msg: &str) {
|
|
|
+//! println!("[{}] {}", self.log_prefix.as_str(), msg);
|
|
|
+//! }
|
|
|
+//!
|
|
|
+//! pub fn change_prefix(&mut self, prefix: &str) {
|
|
|
+//! self.log_prefix = String::from(prefix);
|
|
|
+//! }
|
|
|
+//! }
|
|
|
+//!
|
|
|
+//! #[tokio::main]
|
|
|
+//! async fn main() {
|
|
|
+//! println!("before init, is empty: {}", GLOBAL.is_empty().await);
|
|
|
+//! GLOBAL.set(GlobalObject::new("log-test1")).await;
|
|
|
+//! println!("after init, is empty: {}", GLOBAL.is_empty().await);
|
|
|
+//! println!("init ok.");
|
|
|
+//!
|
|
|
+//! let mut task_set = JoinSet::new();
|
|
|
+//! task_set.spawn(async {
|
|
|
+//! loop {
|
|
|
+//! GLOBAL.get().await.log("task1");
|
|
|
+//! tokio::time::sleep(Duration::from_millis(500)).await;
|
|
|
+//! }
|
|
|
+//! });
|
|
|
+//!
|
|
|
+//! task_set.spawn(async {
|
|
|
+//! loop {
|
|
|
+//! GLOBAL.get().await.log("task2");
|
|
|
+//! tokio::time::sleep(Duration::from_millis(500)).await;
|
|
|
+//! }
|
|
|
+//! });
|
|
|
+//!
|
|
|
+//! task_set.join_next().await;
|
|
|
+//! println!("Program is quitting, aborting all task...");
|
|
|
+//! task_set.abort_all();
|
|
|
+//! println!("Program quit.");
|
|
|
+//! }
|
|
|
+//! ```
|
|
|
+
|
|
|
+use std::ops::Deref;
|
|
|
+#[cfg(feature = "tokio")]
|
|
|
+use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
|
|
+use crate::GOption;
|
|
|
+
|
|
|
+
|
|
|
+#[cfg(feature = "tokio")]
|
|
|
+pub struct AsyncGlobalContainer<T>
|
|
|
+{
|
|
|
+ content: RwLock<GOption<T>>,
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg(feature = "tokio")]
|
|
|
+impl<T> AsyncGlobalContainer<T> {
|
|
|
+ pub fn new() -> AsyncGlobalContainer<T> {
|
|
|
+ AsyncGlobalContainer::<T>{
|
|
|
+ content: RwLock::new(GOption::None),
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn set(&self, obj: T) {
|
|
|
+ *self.content.write().await = GOption::Some(obj);
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn is_empty(&self) -> bool {
|
|
|
+ let v = self.content.read().await;
|
|
|
+ match v.deref() {
|
|
|
+ GOption::None => true,
|
|
|
+ GOption::Some(_) => false,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn manual_drop(&self) {
|
|
|
+ *self.content.write().await = GOption::None;
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn get(&self) -> RwLockReadGuard<GOption<T>> {
|
|
|
+ self.content.read().await
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn get_mut(&self) -> RwLockWriteGuard<GOption<T>> {
|
|
|
+ self.content.write().await
|
|
|
+ }
|
|
|
+}
|