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}