qubit_lock/lock/arc_std_rw_lock.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # Standard Read-Write Lock Wrapper
11//!
12//! Provides an Arc-wrapped standard-library read-write lock for callers that
13//! need `std::sync::RwLock` poisoning semantics.
14//!
15
16use std::ops::Deref;
17use std::sync::{
18 Arc,
19 RwLock,
20};
21
22use crate::lock::{
23 Lock,
24 TryLockError,
25};
26
27/// Standard-library read-write lock wrapper.
28///
29/// Provides an Arc-wrapped [`std::sync::RwLock`] for synchronous shared state.
30/// Read operations can execute concurrently, while write operations have
31/// exclusive access. Unlike [`ArcRwLock`](crate::ArcRwLock), this type
32/// preserves standard-library poison behavior.
33///
34/// # Type Parameters
35///
36/// * `T` - The type protected by this lock.
37pub struct ArcStdRwLock<T> {
38 /// Shared standard read-write lock protecting the wrapped value.
39 inner: Arc<RwLock<T>>,
40}
41
42impl<T> ArcStdRwLock<T> {
43 /// Creates a new standard read-write lock.
44 ///
45 /// # Arguments
46 ///
47 /// * `data` - The data to be protected.
48 ///
49 /// # Returns
50 ///
51 /// A new [`ArcStdRwLock`] protecting `data`.
52 ///
53 /// # Example
54 ///
55 /// ```rust
56 /// use qubit_lock::ArcStdRwLock;
57 ///
58 /// let lock = ArcStdRwLock::new(vec![1, 2, 3]);
59 /// ```
60 #[inline]
61 pub fn new(data: T) -> Self {
62 Self {
63 inner: Arc::new(RwLock::new(data)),
64 }
65 }
66}
67
68impl<T> AsRef<RwLock<T>> for ArcStdRwLock<T> {
69 /// Returns a reference to the underlying standard read-write lock.
70 ///
71 /// This is useful when callers need guard-based APIs such as
72 /// [`RwLock::read`] or [`RwLock::write`] instead of the closure-based
73 /// [`Lock`] methods.
74 #[inline]
75 fn as_ref(&self) -> &RwLock<T> {
76 self.inner.as_ref()
77 }
78}
79
80impl<T> Deref for ArcStdRwLock<T> {
81 type Target = RwLock<T>;
82
83 /// Dereferences this wrapper to the underlying standard read-write lock.
84 ///
85 /// When [`Lock`] is in scope, `read` and `write` with closure arguments
86 /// still call the trait methods on this wrapper. Use explicit
87 /// dereferencing or [`AsRef::as_ref`] when you want the native guard-based
88 /// [`RwLock`] methods.
89 #[inline]
90 fn deref(&self) -> &Self::Target {
91 self.inner.as_ref()
92 }
93}
94
95impl<T> Lock<T> for ArcStdRwLock<T> {
96 /// Acquires a shared read lock and executes a closure.
97 ///
98 /// # Arguments
99 ///
100 /// * `f` - Closure receiving immutable access to the protected value.
101 ///
102 /// # Returns
103 ///
104 /// The value returned by `f`.
105 ///
106 /// # Panics
107 ///
108 /// Panics if the underlying standard read-write lock is poisoned.
109 #[inline]
110 fn read<R, F>(&self, f: F) -> R
111 where
112 F: FnOnce(&T) -> R,
113 {
114 let guard = self.inner.read().unwrap();
115 f(&*guard)
116 }
117
118 /// Acquires an exclusive write lock and executes a closure.
119 ///
120 /// # Arguments
121 ///
122 /// * `f` - Closure receiving mutable access to the protected value.
123 ///
124 /// # Returns
125 ///
126 /// The value returned by `f`.
127 ///
128 /// # Panics
129 ///
130 /// Panics if the underlying standard read-write lock is poisoned.
131 #[inline]
132 fn write<R, F>(&self, f: F) -> R
133 where
134 F: FnOnce(&mut T) -> R,
135 {
136 let mut guard = self.inner.write().unwrap();
137 f(&mut *guard)
138 }
139
140 /// Attempts to acquire a shared read lock without blocking.
141 ///
142 /// # Arguments
143 ///
144 /// * `f` - Closure receiving immutable access when a read lock is acquired.
145 ///
146 /// # Returns
147 ///
148 /// `Ok(result)` if a read lock is acquired.
149 ///
150 /// # Errors
151 ///
152 /// Returns [`TryLockError::WouldBlock`] when the lock is unavailable, or
153 /// [`TryLockError::Poisoned`] when the lock is poisoned.
154 #[inline]
155 fn try_read<R, F>(&self, f: F) -> Result<R, TryLockError>
156 where
157 F: FnOnce(&T) -> R,
158 {
159 match self.inner.try_read() {
160 Ok(guard) => Ok(f(&*guard)),
161 Err(std::sync::TryLockError::WouldBlock) => Err(TryLockError::WouldBlock),
162 Err(std::sync::TryLockError::Poisoned(_)) => Err(TryLockError::Poisoned),
163 }
164 }
165
166 /// Attempts to acquire an exclusive write lock without blocking.
167 ///
168 /// # Arguments
169 ///
170 /// * `f` - Closure receiving mutable access when a write lock is acquired.
171 ///
172 /// # Returns
173 ///
174 /// `Ok(result)` if a write lock is acquired.
175 ///
176 /// # Errors
177 ///
178 /// Returns [`TryLockError::WouldBlock`] when the lock is unavailable, or
179 /// [`TryLockError::Poisoned`] when the lock is poisoned.
180 #[inline]
181 fn try_write<R, F>(&self, f: F) -> Result<R, TryLockError>
182 where
183 F: FnOnce(&mut T) -> R,
184 {
185 match self.inner.try_write() {
186 Ok(mut guard) => Ok(f(&mut *guard)),
187 Err(std::sync::TryLockError::WouldBlock) => Err(TryLockError::WouldBlock),
188 Err(std::sync::TryLockError::Poisoned(_)) => Err(TryLockError::Poisoned),
189 }
190 }
191}
192
193impl<T> From<T> for ArcStdRwLock<T> {
194 /// Creates an Arc-wrapped standard read-write lock from a value.
195 ///
196 /// # Arguments
197 ///
198 /// * `value` - The value to protect.
199 ///
200 /// # Returns
201 ///
202 /// A new [`ArcStdRwLock`] protecting `value`.
203 #[inline]
204 fn from(value: T) -> Self {
205 Self::new(value)
206 }
207}
208
209impl<T: Default> Default for ArcStdRwLock<T> {
210 /// Creates an Arc-wrapped standard read-write lock containing
211 /// `T::default()`.
212 ///
213 /// # Returns
214 ///
215 /// A new [`ArcStdRwLock`] protecting the default value for `T`.
216 #[inline]
217 fn default() -> Self {
218 Self::new(T::default())
219 }
220}
221
222impl<T> Clone for ArcStdRwLock<T> {
223 /// Clones this standard read-write lock handle.
224 ///
225 /// # Returns
226 ///
227 /// A new handle sharing the same underlying read-write lock and protected
228 /// value.
229 #[inline]
230 fn clone(&self) -> Self {
231 Self {
232 inner: self.inner.clone(),
233 }
234 }
235}