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}