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