Skip to main content

qubit_lock/lock/
arc_async_mutex.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # Asynchronous Mutex Wrapper
10//!
11//! Provides an Arc-wrapped asynchronous mutex for protecting shared
12//! data in async environments without blocking threads.
13//!
14//! # Author
15//!
16//! Haixing Hu
17use std::sync::Arc;
18
19use tokio::sync::Mutex as AsyncMutex;
20
21use crate::lock::AsyncLock;
22
23/// Asynchronous Mutex Wrapper
24///
25/// Provides an encapsulation of asynchronous mutex for protecting
26/// shared data in asynchronous environments. Supports safe access
27/// and modification of shared data across multiple asynchronous
28/// tasks.
29///
30/// # Features
31///
32/// - Asynchronously acquires locks, does not block threads
33/// - Supports trying to acquire locks (non-blocking)
34/// - Thread-safe, supports multi-threaded sharing
35/// - Automatic lock management through RAII ensures proper lock
36///   release
37///
38/// # Usage Example
39///
40/// ```rust
41/// use qubit_lock::lock::{ArcAsyncMutex, AsyncLock};
42/// use std::sync::Arc;
43///
44/// let rt = tokio::runtime::Builder::new_current_thread()
45///     .enable_all()
46///     .build()
47///     .unwrap();
48/// rt.block_on(async {
49///     let counter = ArcAsyncMutex::new(0);
50///     let counter = Arc::new(counter);
51///
52///     // Asynchronously modify data
53///     counter.write(|c| {
54///         *c += 1;
55///         println!("Counter: {}", *c);
56///     }).await;
57///
58///     // Try to acquire lock
59///     if let Some(value) = counter.try_read(|c| *c) {
60///         println!("Current value: {}", value);
61///     }
62/// });
63/// ```
64///
65/// # Author
66///
67/// Haixing Hu
68///
69pub struct ArcAsyncMutex<T> {
70    /// Shared Tokio mutex protecting the wrapped value.
71    inner: Arc<AsyncMutex<T>>,
72}
73
74impl<T> ArcAsyncMutex<T> {
75    /// Creates a new asynchronous mutex lock
76    ///
77    /// # Arguments
78    ///
79    /// * `data` - The data to be protected
80    ///
81    /// # Returns
82    ///
83    /// Returns a new `ArcAsyncMutex` instance
84    ///
85    /// # Example
86    ///
87    /// ```rust
88    /// use qubit_lock::lock::ArcAsyncMutex;
89    ///
90    /// let lock = ArcAsyncMutex::new(42);
91    /// ```
92    #[inline]
93    pub fn new(data: T) -> Self {
94        Self {
95            inner: Arc::new(AsyncMutex::new(data)),
96        }
97    }
98}
99
100impl<T> AsyncLock<T> for ArcAsyncMutex<T>
101where
102    T: Send,
103{
104    /// Acquires the mutex and executes a read-only operation.
105    ///
106    /// # Arguments
107    ///
108    /// * `f` - Closure receiving immutable access to the protected value.
109    ///
110    /// # Returns
111    ///
112    /// A future resolving to the closure result.
113    #[inline]
114    async fn read<R, F>(&self, f: F) -> R
115    where
116        F: FnOnce(&T) -> R + Send,
117        R: Send,
118    {
119        let guard = self.inner.lock().await;
120        f(&*guard)
121    }
122
123    /// Acquires the mutex and executes a mutable operation.
124    ///
125    /// # Arguments
126    ///
127    /// * `f` - Closure receiving mutable access to the protected value.
128    ///
129    /// # Returns
130    ///
131    /// A future resolving to the closure result.
132    #[inline]
133    async fn write<R, F>(&self, f: F) -> R
134    where
135        F: FnOnce(&mut T) -> R + Send,
136        R: Send,
137    {
138        let mut guard = self.inner.lock().await;
139        f(&mut *guard)
140    }
141
142    /// Attempts to acquire the mutex for a read-only operation without waiting.
143    ///
144    /// # Arguments
145    ///
146    /// * `f` - Closure receiving immutable access when the mutex is available.
147    ///
148    /// # Returns
149    ///
150    /// `Some(result)` if the mutex was acquired, or `None` if it was busy.
151    #[inline]
152    fn try_read<R, F>(&self, f: F) -> Option<R>
153    where
154        F: FnOnce(&T) -> R,
155    {
156        if let Ok(guard) = self.inner.try_lock() {
157            Some(f(&*guard))
158        } else {
159            None
160        }
161    }
162
163    /// Attempts to acquire the mutex for a mutable operation without waiting.
164    ///
165    /// # Arguments
166    ///
167    /// * `f` - Closure receiving mutable access when the mutex is available.
168    ///
169    /// # Returns
170    ///
171    /// `Some(result)` if the mutex was acquired, or `None` if it was busy.
172    #[inline]
173    fn try_write<R, F>(&self, f: F) -> Option<R>
174    where
175        F: FnOnce(&mut T) -> R,
176    {
177        if let Ok(mut guard) = self.inner.try_lock() {
178            Some(f(&mut *guard))
179        } else {
180            None
181        }
182    }
183}
184
185impl<T> Clone for ArcAsyncMutex<T> {
186    /// Clones the asynchronous mutex
187    ///
188    /// Creates a new `ArcAsyncMutex` instance that shares the same
189    /// underlying lock with the original instance. This allows
190    /// multiple tasks to hold references to the same lock
191    /// simultaneously.
192    ///
193    /// # Returns
194    ///
195    /// A new handle sharing the same underlying async mutex and protected
196    /// value.
197    #[inline]
198    fn clone(&self) -> Self {
199        Self {
200            inner: self.inner.clone(),
201        }
202    }
203}