use std::sync::Arc; use tokio::sync::{Mutex, MutexGuard}; use tokio::time::{timeout, Duration}; // #[derive(Clone)] See issue #2 pub struct Shared { pub data: Arc>, /// Number of seconds to consider a dead lock pub lock_timeout: u64, } impl Clone for Shared { fn clone(&self) -> Self { Self { data: self.data.clone(), lock_timeout: self.lock_timeout, } } } impl Shared { /// Creates a new Shared of data T /// /// A lock timeout of 30 seconds is assigned by default (Use Shared::with_timeout to set the timeout yourself, or just edit the field as it is public) /// /// > Want to see a complete example, look at doc_example in the examples directory /// /// Example: /// ``` /// use shared::Shared; /// /// // #[derive(Clone)] /// // Clone is no longer needed as of v0.2.0 /// struct Person { /// pub name: String, /// pub age: u16 /// } /// /// #[tokio::main] /// async fn main() { /// let shared_data = Shared::new(Person{ /// name: "Test Dummy".to_string(), /// age: 30 /// }); /// /// // See Shared::lock for using it /// } /// ``` pub fn new(data: T) -> Self { Shared { data: Arc::new(Mutex::new(data)), lock_timeout: 30_u64, } } /// Creates a new Shared of data T with a given timeout in seconds pub fn with_timeout(data: T, timeout: u64) -> Self { Shared { data: Arc::new(Mutex::new(data)), lock_timeout: timeout } } /// Acquire lock /// /// Will wait so many seconds as defined by lock_timeout (This will panic once the timeout is reached) /// /// > Want to see a complete example, look at doc_example in the examples directory /// /// Using: /// ``` /// // See Shared::new for creating a Shared /// /// { // Direct access /// let person = shared_data.lock().await; /// println!("Person{{name: {}, age: {}}}", person.name, person.age); /// } /// /// // Using it as a parameter /// async fn get_older(shared: Shared) { /// let mut person = shared.lock().await; /// person.age += 1; /// } /// /// // Calling /// get_older(shared_data.clone()).await; /// ``` pub async fn lock(&self) -> MutexGuard<'_, T> { let result = timeout(Duration::from_secs(self.lock_timeout), self.data.lock()).await; if let Ok(guard) = result { return guard; } panic!( "Failed to acquire lock in {} seconds. Deadlock?", self.lock_timeout ); // self.data.lock().await } }