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}