quick_cache/rw_lock.rs
1use std::ops::{Deref, DerefMut};
2
3#[cfg(feature = "parking_lot")]
4type InnerRwLock<T> = parking_lot::RwLock<T>;
5#[cfg(all(not(feature = "parking_lot"), feature = "sharded-lock"))]
6type InnerRwLock<T> = crossbeam_utils::sync::ShardedLock<T>;
7#[cfg(all(not(feature = "parking_lot"), not(feature = "sharded-lock")))]
8type InnerRwLock<T> = std::sync::RwLock<T>;
9
10#[cfg(feature = "parking_lot")]
11type InnerRwLockReadGuard<'rwlock, T> = parking_lot::RwLockReadGuard<'rwlock, T>;
12#[cfg(all(not(feature = "parking_lot"), feature = "sharded-lock"))]
13type InnerRwLockReadGuard<'rwlock, T> = crossbeam_utils::sync::ShardedLockReadGuard<'rwlock, T>;
14#[cfg(all(not(feature = "parking_lot"), not(feature = "sharded-lock")))]
15type InnerRwLockReadGuard<'rwlock, T> = std::sync::RwLockReadGuard<'rwlock, T>;
16
17#[cfg(feature = "parking_lot")]
18type InnerRwLockWriteGuard<'rwlock, T> = parking_lot::RwLockWriteGuard<'rwlock, T>;
19#[cfg(all(not(feature = "parking_lot"), feature = "sharded-lock"))]
20type InnerRwLockWriteGuard<'rwlock, T> = crossbeam_utils::sync::ShardedLockWriteGuard<'rwlock, T>;
21#[cfg(all(not(feature = "parking_lot"), not(feature = "sharded-lock")))]
22type InnerRwLockWriteGuard<'rwlock, T> = std::sync::RwLockWriteGuard<'rwlock, T>;
23
24/// A reader-writer lock.
25///
26/// This type of lock allows a number of readers or at most one writer at any
27/// point in time. The write portion of this lock typically allows modification
28/// of the underlying data (exclusive access) and the read portion of this lock
29/// typically allows for read-only access (shared access).
30///
31/// In comparison, a [`Mutex`] does not distinguish between readers or writers
32/// that acquire the lock, therefore blocking any threads waiting for the lock to
33/// become available. An `RwLock` will allow any number of readers to acquire the
34/// lock as long as a writer is not holding the lock.
35///
36/// The type parameter `T` represents the data that this lock protects. It is
37/// required that `T` satisfies [`Send`] to be shared across threads and
38/// [`Sync`] to allow concurrent access through readers. The RAII guards
39/// returned from the locking methods implement [`Deref`] (and [`DerefMut`]
40/// for the `write` methods) to allow access to the content of the lock.
41///
42/// # Poisoning
43///
44/// An `RwLock` might become poisoned on a panic. Note, however, that an `RwLock`
45/// may only be poisoned if a panic occurs while it is locked exclusively (write
46/// mode). If a panic occurs in any reader, then the lock will not be poisoned.
47#[derive(Default, Debug)]
48#[repr(transparent)]
49pub struct RwLock<T: ?Sized>(InnerRwLock<T>);
50
51/// RAII structure used to release the shared read access of a lock when dropped.
52#[repr(transparent)]
53#[must_use = "if unused the RwLock will immediately unlock"]
54pub struct RwLockReadGuard<'rwlock, T: ?Sized>(InnerRwLockReadGuard<'rwlock, T>);
55
56/// RAII structure used to release the exclusive write access of a lock when dropped.
57#[repr(transparent)]
58#[must_use = "if unused the RwLock will immediately unlock"]
59pub struct RwLockWriteGuard<'rwlock, T: ?Sized>(InnerRwLockWriteGuard<'rwlock, T>);
60
61#[cfg(not(feature = "sharded-lock"))]
62impl<T> RwLock<T> {
63 /// Creates a new instance of an `RwLock<T>` which is unlocked.
64 pub const fn new(t: T) -> Self {
65 Self(InnerRwLock::new(t))
66 }
67}
68
69#[cfg(feature = "sharded-lock")]
70impl<T> RwLock<T> {
71 /// Creates a new instance of an `RwLock<T>` which is unlocked.
72 pub fn new(t: T) -> Self {
73 Self(InnerRwLock::new(t))
74 }
75}
76
77impl<T: ?Sized> RwLock<T> {
78 /// Locks this `RwLock` with shared read access, blocking the current thread
79 /// until it can be acquired.
80 ///
81 /// The calling thread will be blocked until there are no more writers which
82 /// hold the lock. There may be other readers currently inside the lock when
83 /// this method returns. This method does not provide any guarantees with
84 /// respect to the ordering of whether contentious readers or writers will
85 /// acquire the lock first.
86 ///
87 /// Returns an RAII guard which will release this thread's shared access
88 /// once it is dropped.
89 ///
90 /// # Panics
91 ///
92 /// This function might panic when called if the lock is already held by the
93 /// current thread, or if the `RwLock` is poisoned. An `RwLock` might be
94 /// poisoned whenever a writer panics while holding an exclusive lock.
95 /// Implementations are not required to implement poisoning.
96 #[inline]
97 pub fn read(&self) -> RwLockReadGuard<'_, T> {
98 RwLockReadGuard({
99 #[cfg(feature = "parking_lot")]
100 {
101 self.0.read()
102 }
103 #[cfg(not(feature = "parking_lot"))]
104 self.0.read().unwrap()
105 })
106 }
107
108 /// Locks this `RwLock` with exclusive write access, blocking the current
109 /// thread until it can be acquired.
110 ///
111 /// This function will not return while other writers or other readers
112 /// currently have access to the lock.
113 ///
114 /// Returns an RAII guard which will drop the write access of this `RwLock`
115 /// when dropped.
116 ///
117 /// # Panics
118 ///
119 /// This function might panic when called if the lock is already held by the
120 /// current thread, or if the `RwLock` is poisoned. An `RwLock` might be
121 /// poisoned whenever a writer panics while holding an exclusive lock.
122 /// Implementations are not required to implement poisoning.
123 #[inline]
124 pub fn write(&self) -> RwLockWriteGuard<'_, T> {
125 RwLockWriteGuard({
126 #[cfg(feature = "parking_lot")]
127 {
128 self.0.write()
129 }
130 #[cfg(not(feature = "parking_lot"))]
131 self.0.write().unwrap()
132 })
133 }
134}
135
136impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
137 type Target = T;
138
139 fn deref(&self) -> &Self::Target {
140 &self.0
141 }
142}
143
144impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
145 type Target = T;
146
147 fn deref(&self) -> &Self::Target {
148 &self.0
149 }
150}
151
152impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
153 fn deref_mut(&mut self) -> &mut Self::Target {
154 &mut self.0
155 }
156}