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/// use std::sync::Arc;
47///
48/// let counter = ArcStdMutex::new(0);
49/// let counter = Arc::new(counter);
50///
51/// // Synchronously modify data
52/// counter.write(|c| {
53///     *c += 1;
54///     println!("Counter: {}", *c);
55/// });
56///
57/// // Try to acquire lock
58/// if let Ok(value) = counter.try_read(|c| *c) {
59///     println!("Current value: {}", value);
60/// }
61/// ```
62///
63/// # Author
64///
65/// Haixing Hu
66///
67pub struct ArcStdMutex<T> {
68    /// Shared standard mutex protecting the wrapped value.
69    inner: Arc<Mutex<T>>,
70}
71
72impl<T> ArcStdMutex<T> {
73    /// Creates a new synchronous mutex lock
74    ///
75    /// # Arguments
76    ///
77    /// * `data` - The data to be protected
78    ///
79    /// # Returns
80    ///
81    /// Returns a new `ArcStdMutex` instance
82    ///
83    /// # Example
84    ///
85    /// ```rust
86    /// use qubit_lock::lock::ArcStdMutex;
87    ///
88    /// let lock = ArcStdMutex::new(42);
89    /// ```
90    #[inline]
91    pub fn new(data: T) -> Self {
92        Self {
93            inner: Arc::new(Mutex::new(data)),
94        }
95    }
96}
97
98impl<T> Lock<T> for ArcStdMutex<T> {
99    /// Acquires a read lock and executes an operation
100    ///
101    /// For ArcStdMutex, this acquires the same exclusive lock as write
102    /// operations, but provides immutable access to the data. This
103    /// ensures thread safety while allowing read-only operations.
104    ///
105    /// # Arguments
106    ///
107    /// * `f` - The closure to be executed while holding the read lock
108    ///
109    /// # Returns
110    ///
111    /// Returns the result of executing the closure
112    ///
113    /// # Panics
114    ///
115    /// Panics if the underlying standard mutex is poisoned.
116    ///
117    /// # Example
118    ///
119    /// ```rust
120    /// use qubit_lock::lock::{ArcStdMutex, Lock};
121    ///
122    /// let counter = ArcStdMutex::new(42);
123    ///
124    /// let value = counter.read(|c| *c);
125    /// println!("Current value: {}", value);
126    /// ```
127    #[inline]
128    fn read<R, F>(&self, f: F) -> R
129    where
130        F: FnOnce(&T) -> R,
131    {
132        let guard = self.inner.lock().unwrap();
133        f(&*guard)
134    }
135
136    /// Acquires a write lock and executes an operation
137    ///
138    /// Synchronously acquires the exclusive lock, executes the provided
139    /// closure with mutable access, and then automatically releases
140    /// the lock. This is the recommended usage pattern for modifications.
141    ///
142    /// # Arguments
143    ///
144    /// * `f` - The closure to be executed while holding the write lock
145    ///
146    /// # Returns
147    ///
148    /// Returns the result of executing the closure
149    ///
150    /// # Panics
151    ///
152    /// Panics if the underlying standard mutex is poisoned.
153    ///
154    /// # Example
155    ///
156    /// ```rust
157    /// use qubit_lock::lock::{ArcStdMutex, Lock};
158    ///
159    /// let counter = ArcStdMutex::new(0);
160    ///
161    /// let result = counter.write(|c| {
162    ///     *c += 1;
163    ///     *c
164    /// });
165    ///
166    /// println!("Counter value: {}", result);
167    /// ```
168    #[inline]
169    fn write<R, F>(&self, f: F) -> R
170    where
171        F: FnOnce(&mut T) -> R,
172    {
173        let mut guard = self.inner.lock().unwrap();
174        f(&mut *guard)
175    }
176
177    /// Attempts to acquire a read lock without blocking
178    ///
179    /// Attempts to immediately acquire the read lock. If the lock is
180    /// unavailable, returns a detailed error. This is a non-blocking operation.
181    ///
182    /// # Arguments
183    ///
184    /// * `f` - The closure to be executed while holding the read lock
185    ///
186    /// # Returns
187    ///
188    /// * `Ok(R)` - If the lock was successfully acquired and the closure executed
189    /// * `Err(TryLockError::WouldBlock)` - If the lock is already held by another thread
190    /// * `Err(TryLockError::Poisoned)` - If the lock is poisoned
191    ///
192    /// # Example
193    ///
194    /// ```rust
195    /// use qubit_lock::lock::{ArcStdMutex, Lock};
196    ///
197    /// let counter = ArcStdMutex::new(42);
198    ///
199    /// if let Ok(value) = counter.try_read(|c| *c) {
200    ///     println!("Current value: {}", value);
201    /// } else {
202    ///     println!("Lock is unavailable");
203    /// }
204    /// ```
205    #[inline]
206    fn try_read<R, F>(&self, f: F) -> Result<R, TryLockError>
207    where
208        F: FnOnce(&T) -> R,
209    {
210        match self.inner.try_lock() {
211            Ok(guard) => Ok(f(&*guard)),
212            Err(std::sync::TryLockError::WouldBlock) => Err(TryLockError::WouldBlock),
213            Err(std::sync::TryLockError::Poisoned(_)) => Err(TryLockError::Poisoned),
214        }
215    }
216
217    /// Attempts to acquire a write lock without blocking
218    ///
219    /// Attempts to immediately acquire the write lock. If the lock is
220    /// unavailable, returns a detailed error. This is a non-blocking operation.
221    ///
222    /// # Arguments
223    ///
224    /// * `f` - The closure to be executed while holding the write lock
225    ///
226    /// # Returns
227    ///
228    /// * `Ok(R)` - If the lock was successfully acquired and the closure executed
229    /// * `Err(TryLockError::WouldBlock)` - If the lock is already held by another thread
230    /// * `Err(TryLockError::Poisoned)` - If the lock is poisoned
231    ///
232    /// # Example
233    ///
234    /// ```rust
235    /// use qubit_lock::lock::{ArcStdMutex, Lock};
236    ///
237    /// let counter = ArcStdMutex::new(0);
238    ///
239    /// if let Ok(result) = counter.try_write(|c| {
240    ///     *c += 1;
241    ///     *c
242    /// }) {
243    ///     println!("New value: {}", result);
244    /// } else {
245    ///     println!("Lock is unavailable");
246    /// }
247    /// ```
248    #[inline]
249    fn try_write<R, F>(&self, f: F) -> Result<R, TryLockError>
250    where
251        F: FnOnce(&mut T) -> R,
252    {
253        match self.inner.try_lock() {
254            Ok(mut guard) => Ok(f(&mut *guard)),
255            Err(std::sync::TryLockError::WouldBlock) => Err(TryLockError::WouldBlock),
256            Err(std::sync::TryLockError::Poisoned(_)) => Err(TryLockError::Poisoned),
257        }
258    }
259}
260
261impl<T> Clone for ArcStdMutex<T> {
262    /// Clones the synchronous mutex
263    ///
264    /// Creates a new `ArcStdMutex` instance that shares the same
265    /// underlying lock with the original instance. This allows
266    /// multiple threads to hold references to the same lock
267    /// simultaneously.
268    ///
269    /// # Returns
270    ///
271    /// A new handle sharing the same underlying mutex and protected value.
272    #[inline]
273    fn clone(&self) -> Self {
274        Self {
275            inner: self.inner.clone(),
276        }
277    }
278}