• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Abstracts over sync primitive implementations.
2 //!
3 //! Optionally, we allow the Rust standard library's `RwLock` to be replaced
4 //! with the `parking_lot` crate's implementation. This may provide improved
5 //! performance in some cases. However, the `parking_lot` dependency is an
6 //! opt-in feature flag. Because `parking_lot::RwLock` has a slightly different
7 //! API than `std::sync::RwLock` (it does not support poisoning on panics), we
8 //! wrap the `std::sync` version to ignore poisoning.
9 
10 #[allow(unused_imports)] // may be used later;
11 #[cfg(feature = "parking_lot")]
12 pub(crate) use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
13 
14 #[cfg(not(feature = "parking_lot"))]
15 pub(crate) use self::std_impl::*;
16 
17 #[cfg(not(feature = "parking_lot"))]
18 mod std_impl {
19     use std::sync::{self, PoisonError, TryLockError};
20     pub(crate) use std::sync::{RwLockReadGuard, RwLockWriteGuard};
21 
22     #[derive(Debug)]
23     pub(crate) struct RwLock<T> {
24         inner: sync::RwLock<T>,
25     }
26 
27     impl<T> RwLock<T> {
new(val: T) -> Self28         pub(crate) fn new(val: T) -> Self {
29             Self {
30                 inner: sync::RwLock::new(val),
31             }
32         }
33 
34         #[inline]
get_mut(&mut self) -> &mut T35         pub(crate) fn get_mut(&mut self) -> &mut T {
36             self.inner.get_mut().unwrap_or_else(PoisonError::into_inner)
37         }
38 
39         #[inline]
read(&self) -> RwLockReadGuard<'_, T>40         pub(crate) fn read(&self) -> RwLockReadGuard<'_, T> {
41             self.inner.read().unwrap_or_else(PoisonError::into_inner)
42         }
43 
44         #[inline]
45         #[allow(dead_code)] // may be used later;
try_read(&self) -> Option<RwLockReadGuard<'_, T>>46         pub(crate) fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
47             match self.inner.try_read() {
48                 Ok(guard) => Some(guard),
49                 Err(TryLockError::Poisoned(e)) => Some(e.into_inner()),
50                 Err(TryLockError::WouldBlock) => None,
51             }
52         }
53 
54         #[inline]
write(&self) -> RwLockWriteGuard<'_, T>55         pub(crate) fn write(&self) -> RwLockWriteGuard<'_, T> {
56             self.inner.write().unwrap_or_else(PoisonError::into_inner)
57         }
58 
59         #[inline]
60         #[allow(dead_code)] // may be used later;
try_write(&self) -> Option<RwLockWriteGuard<'_, T>>61         pub(crate) fn try_write(&self) -> Option<RwLockWriteGuard<'_, T>> {
62             match self.inner.try_write() {
63                 Ok(guard) => Some(guard),
64                 Err(TryLockError::Poisoned(e)) => Some(e.into_inner()),
65                 Err(TryLockError::WouldBlock) => None,
66             }
67         }
68     }
69 }
70