Skip to main content

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}