qubit_lock/lock/arc_mutex.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9
10//! # Synchronous Mutex Wrapper (Parking Lot)
11//!
12//! Provides an Arc-wrapped synchronous mutex using parking_lot::Mutex
13//! for protecting shared data in multi-threaded environments.
14//!
15//! # Author
16//!
17//! Haixing Hu
18
19use std::sync::Arc;
20
21use parking_lot::Mutex;
22
23use crate::lock::{
24 Lock,
25 TryLockError,
26};
27
28/// Synchronous Mutex Wrapper (Parking Lot)
29///
30/// Provides an encapsulation of synchronous mutex using parking_lot::Mutex
31/// for protecting shared data in synchronous environments. Supports safe
32/// access and modification of shared data across multiple threads.
33/// Compared to std::sync::Mutex, parking_lot::Mutex provides better
34/// performance and more ergonomic API.
35///
36/// # Features
37///
38/// - Synchronously acquires locks, may block threads
39/// - Supports trying to acquire locks (non-blocking)
40/// - Thread-safe, supports multi-threaded sharing
41/// - Automatic lock management through RAII ensures proper lock
42/// release
43/// - Better performance compared to std::sync::Mutex
44/// - More ergonomic API with no unwrap() calls
45///
46/// # Usage Example
47///
48/// ```rust
49/// use qubit_lock::lock::{ArcMutex, Lock};
50///
51/// let counter = ArcMutex::new(0);
52///
53/// // Synchronously modify data
54/// counter.write(|c| {
55/// *c += 1;
56/// println!("Counter: {}", *c);
57/// });
58///
59/// // Try to acquire lock
60/// if let Ok(value) = counter.try_read(|c| *c) {
61/// println!("Current value: {}", value);
62/// }
63/// ```
64///
65/// # Author
66///
67/// Haixing Hu
68///
69pub struct ArcMutex<T> {
70 /// Shared parking_lot mutex protecting the wrapped value.
71 inner: Arc<Mutex<T>>,
72}
73
74impl<T> ArcMutex<T> {
75 /// Creates a new synchronous mutex lock
76 ///
77 /// # Arguments
78 ///
79 /// * `data` - The data to be protected
80 ///
81 /// # Returns
82 ///
83 /// Returns a new `ArcMutex` instance
84 ///
85 /// # Example
86 ///
87 /// ```rust
88 /// use qubit_lock::lock::ArcMutex;
89 ///
90 /// let lock = ArcMutex::new(42);
91 /// ```
92 #[inline]
93 pub fn new(data: T) -> Self {
94 Self {
95 inner: Arc::new(Mutex::new(data)),
96 }
97 }
98}
99
100impl<T> Lock<T> for ArcMutex<T> {
101 /// Acquires a read lock and executes an operation
102 ///
103 /// For ArcMutex, this acquires the same exclusive lock as write
104 /// operations, but provides immutable access to the data. This
105 /// ensures thread safety while allowing read-only operations.
106 ///
107 /// # Arguments
108 ///
109 /// * `f` - The closure to be executed while holding the read lock
110 ///
111 /// # Returns
112 ///
113 /// Returns the result of executing the closure
114 ///
115 /// # Example
116 ///
117 /// ```rust
118 /// use qubit_lock::lock::{ArcMutex, Lock};
119 ///
120 /// let counter = ArcMutex::new(42);
121 ///
122 /// let value = counter.read(|c| *c);
123 /// println!("Current value: {}", value);
124 /// ```
125 #[inline]
126 fn read<R, F>(&self, f: F) -> R
127 where
128 F: FnOnce(&T) -> R,
129 {
130 let guard = self.inner.lock();
131 f(&*guard)
132 }
133
134 /// Acquires a write lock and executes an operation
135 ///
136 /// Synchronously acquires the exclusive lock, executes the provided
137 /// closure with mutable access, and then automatically releases
138 /// the lock. This is the recommended usage pattern for modifications.
139 ///
140 /// # Arguments
141 ///
142 /// * `f` - The closure to be executed while holding the write lock
143 ///
144 /// # Returns
145 ///
146 /// Returns the result of executing the closure
147 ///
148 /// # Example
149 ///
150 /// ```rust
151 /// use qubit_lock::lock::{ArcMutex, Lock};
152 ///
153 /// let counter = ArcMutex::new(0);
154 ///
155 /// let result = counter.write(|c| {
156 /// *c += 1;
157 /// *c
158 /// });
159 ///
160 /// println!("Counter value: {}", result);
161 /// ```
162 #[inline]
163 fn write<R, F>(&self, f: F) -> R
164 where
165 F: FnOnce(&mut T) -> R,
166 {
167 let mut guard = self.inner.lock();
168 f(&mut *guard)
169 }
170
171 /// Attempts to acquire a read lock without blocking
172 ///
173 /// Attempts to immediately acquire the read lock. If the lock is
174 /// unavailable, returns a detailed error. This is a non-blocking operation.
175 ///
176 /// # Arguments
177 ///
178 /// * `f` - The closure to be executed while holding the read lock
179 ///
180 /// # Returns
181 ///
182 /// * `Ok(R)` - If the lock was successfully acquired and the closure executed
183 /// * `Err(TryLockError::WouldBlock)` - If the lock is already held by another thread
184 ///
185 /// # Example
186 ///
187 /// ```rust
188 /// use qubit_lock::lock::{ArcMutex, Lock};
189 ///
190 /// let counter = ArcMutex::new(42);
191 ///
192 /// if let Ok(value) = counter.try_read(|c| *c) {
193 /// println!("Current value: {}", value);
194 /// } else {
195 /// println!("Lock is unavailable");
196 /// }
197 /// ```
198 #[inline]
199 fn try_read<R, F>(&self, f: F) -> Result<R, TryLockError>
200 where
201 F: FnOnce(&T) -> R,
202 {
203 self.inner
204 .try_lock()
205 .map(|guard| f(&*guard))
206 .ok_or(TryLockError::WouldBlock)
207 }
208
209 /// Attempts to acquire a write lock without blocking
210 ///
211 /// Attempts to immediately acquire the write lock. If the lock is
212 /// unavailable, returns a detailed error. This is a non-blocking operation.
213 ///
214 /// # Arguments
215 ///
216 /// * `f` - The closure to be executed while holding the write lock
217 ///
218 /// # Returns
219 ///
220 /// * `Ok(R)` - If the lock was successfully acquired and the closure executed
221 /// * `Err(TryLockError::WouldBlock)` - If the lock is already held by another thread
222 ///
223 /// # Example
224 ///
225 /// ```rust
226 /// use qubit_lock::lock::{ArcMutex, Lock};
227 ///
228 /// let counter = ArcMutex::new(0);
229 ///
230 /// if let Ok(result) = counter.try_write(|c| {
231 /// *c += 1;
232 /// *c
233 /// }) {
234 /// println!("New value: {}", result);
235 /// } else {
236 /// println!("Lock is unavailable");
237 /// }
238 /// ```
239 #[inline]
240 fn try_write<R, F>(&self, f: F) -> Result<R, TryLockError>
241 where
242 F: FnOnce(&mut T) -> R,
243 {
244 self.inner
245 .try_lock()
246 .map(|mut guard| f(&mut *guard))
247 .ok_or(TryLockError::WouldBlock)
248 }
249}
250
251impl<T> Clone for ArcMutex<T> {
252 /// Clones the synchronous mutex
253 ///
254 /// Creates a new `ArcMutex` instance that shares the same
255 /// underlying lock with the original instance. This allows
256 /// multiple threads to hold references to the same lock
257 /// simultaneously.
258 ///
259 /// # Returns
260 ///
261 /// A new handle sharing the same underlying mutex and protected value.
262 #[inline]
263 fn clone(&self) -> Self {
264 Self {
265 inner: self.inner.clone(),
266 }
267 }
268}