1#[cfg(not(feature = "concurrent"))]
37use std::cell::{RefCell as InnerRwLock, RefCell as InnerLock};
38use std::{
39 cmp::Ordering,
40 collections::HashMap,
41 fmt,
42 fmt::{Debug, Formatter},
43 hash::{BuildHasher, Hash},
44};
45
46#[cfg(feature = "concurrent")]
47use parking_lot::{Mutex as InnerLock, RwLock as InnerRwLock};
48
49#[cfg(feature = "concurrent")]
50pub use self::concurrent::*;
51#[cfg(not(feature = "concurrent"))]
52pub use self::single::*;
53
54#[cfg(feature = "concurrent")]
55mod concurrent {
56 pub use std::{
57 marker::{Send, Sync},
58 sync::Arc as Lrc,
59 };
60
61 pub use once_cell::sync::{Lazy, OnceCell};
62 pub use parking_lot::{
63 MappedMutexGuard as MappedLockGuard, MappedRwLockReadGuard as MappedReadGuard,
64 MappedRwLockWriteGuard as MappedWriteGuard, MutexGuard as LockGuard,
65 RwLockReadGuard as ReadGuard, RwLockWriteGuard as WriteGuard,
66 };
67}
68
69#[cfg(not(feature = "concurrent"))]
70mod single {
71 pub use once_cell::unsync::{Lazy, OnceCell};
72 pub trait Send {}
74 pub trait Sync {}
76
77 impl<T> Send for T where T: ?Sized {}
78 impl<T> Sync for T where T: ?Sized {}
79
80 pub use std::{
81 cell::{
82 Ref as ReadGuard, RefMut as WriteGuard, RefMut as MappedWriteGuard,
83 RefMut as LockGuard, RefMut as MappedLockGuard,
84 },
85 rc::{Rc as Lrc, Weak},
86 };
87}
88
89#[derive(Debug)]
90pub struct Lock<T>(InnerLock<T>);
91
92impl<T> Lock<T> {
93 #[inline(always)]
94 pub fn new(inner: T) -> Self {
95 Lock(InnerLock::new(inner))
96 }
97
98 #[cfg(feature = "concurrent")]
121 #[inline(always)]
122 pub fn lock(&self) -> LockGuard<'_, T> {
123 self.0.lock()
124 }
125
126 #[cfg(not(feature = "concurrent"))]
127 #[inline(always)]
128 pub fn lock(&self) -> LockGuard<'_, T> {
129 self.0.borrow_mut()
130 }
131
132 #[inline(always)]
138 pub fn borrow(&self) -> LockGuard<'_, T> {
139 self.lock()
140 }
141
142 #[inline(always)]
143 pub fn borrow_mut(&self) -> LockGuard<'_, T> {
144 self.lock()
145 }
146}
147
148impl<T: Default> Default for Lock<T> {
149 #[inline]
150 fn default() -> Self {
151 Lock::new(T::default())
152 }
153}
154
155impl<T> LockCell<T> {
156 #[inline(always)]
157 pub fn new(inner: T) -> Self {
158 LockCell(Lock::new(inner))
159 }
160
161 #[inline(always)]
162 pub fn set(&self, new_inner: T) {
163 *self.0.lock() = new_inner;
164 }
165
166 #[inline(always)]
167 pub fn get(&self) -> T
168 where
169 T: Copy,
170 {
171 *self.0.lock()
172 }
173}
174
175pub trait HashMapExt<K, V> {
176 fn insert_same(&mut self, key: K, value: V);
179}
180
181impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S> {
182 fn insert_same(&mut self, key: K, value: V) {
183 self.entry(key)
184 .and_modify(|old| assert!(*old == value))
185 .or_insert(value);
186 }
187}
188
189impl<T: Copy + Debug> Debug for LockCell<T> {
190 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
191 f.debug_struct("LockCell")
192 .field("value", &self.get())
193 .finish()
194 }
195}
196
197impl<T: Default> Default for LockCell<T> {
198 #[inline]
200 fn default() -> LockCell<T> {
201 LockCell::new(Default::default())
202 }
203}
204
205impl<T: PartialEq + Copy> PartialEq for LockCell<T> {
206 #[inline]
207 fn eq(&self, other: &LockCell<T>) -> bool {
208 self.get() == other.get()
209 }
210}
211
212impl<T: Eq + Copy> Eq for LockCell<T> {}
213
214impl<T: PartialOrd + Copy> PartialOrd for LockCell<T> {
215 #[inline]
216 fn partial_cmp(&self, other: &LockCell<T>) -> Option<Ordering> {
217 self.get().partial_cmp(&other.get())
218 }
219
220 #[inline]
221 fn lt(&self, other: &LockCell<T>) -> bool {
222 self.get() < other.get()
223 }
224
225 #[inline]
226 fn le(&self, other: &LockCell<T>) -> bool {
227 self.get() <= other.get()
228 }
229
230 #[inline]
231 fn gt(&self, other: &LockCell<T>) -> bool {
232 self.get() > other.get()
233 }
234
235 #[inline]
236 fn ge(&self, other: &LockCell<T>) -> bool {
237 self.get() >= other.get()
238 }
239}
240
241impl<T: Ord + Copy> Ord for LockCell<T> {
242 #[inline]
243 fn cmp(&self, other: &LockCell<T>) -> Ordering {
244 self.get().cmp(&other.get())
245 }
246}
247
248#[derive(Debug, Default)]
249pub struct RwLock<T>(InnerRwLock<T>);
250
251impl<T> RwLock<T> {
252 #[inline(always)]
253 pub fn new(inner: T) -> Self {
254 RwLock(InnerRwLock::new(inner))
255 }
256
257 #[cfg(not(feature = "concurrent"))]
258 #[inline(always)]
259 pub fn read(&self) -> ReadGuard<'_, T> {
260 self.0.borrow()
261 }
262
263 #[cfg(feature = "concurrent")]
264 #[inline(always)]
265 pub fn read(&self) -> ReadGuard<'_, T> {
266 self.0.read()
267 }
268
269 #[inline(always)]
270 pub fn borrow(&self) -> ReadGuard<'_, T> {
271 self.read()
272 }
273
274 #[inline(always)]
275 pub fn get_mut(&mut self) -> &mut T {
276 self.0.get_mut()
277 }
278
279 #[inline(always)]
280 pub fn with_read_lock<F: FnOnce(&T) -> R, R>(&self, f: F) -> R {
281 f(&*self.read())
282 }
283
284 #[allow(clippy::result_unit_err)]
285 #[cfg(not(feature = "concurrent"))]
286 #[inline(always)]
287 pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
288 self.0.try_borrow_mut().map_err(|_| ())
289 }
290
291 #[allow(clippy::result_unit_err)]
292 #[cfg(feature = "concurrent")]
293 #[inline(always)]
294 pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
295 self.0.try_write().ok_or(())
296 }
297
298 #[cfg(not(feature = "concurrent"))]
299 #[inline(always)]
300 pub fn write(&self) -> WriteGuard<'_, T> {
301 self.0.borrow_mut()
302 }
303
304 #[cfg(feature = "concurrent")]
305 #[inline(always)]
306 pub fn write(&self) -> WriteGuard<'_, T> {
307 self.0.write()
308 }
309
310 #[inline(always)]
311 pub fn with_write_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R {
312 f(&mut *self.write())
313 }
314
315 #[inline(always)]
316 pub fn borrow_mut(&self) -> WriteGuard<'_, T> {
317 self.write()
318 }
319}
320
321impl<T: Clone> Clone for RwLock<T> {
323 #[inline]
324 fn clone(&self) -> Self {
325 RwLock::new(self.borrow().clone())
326 }
327}
328
329pub struct LockCell<T>(Lock<T>);