Skip to main content

qubit_lock/lock/
arc_std_mutex.rs

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