use std::sync::{Arc, PoisonError, RwLockReadGuard, RwLockWriteGuard, Weak};
pub(crate) type ArcLock<T> = std::sync::Arc<std::sync::RwLock<T>>;
pub(crate) type WeakLock<T> = std::sync::Weak<std::sync::RwLock<T>>;
#[derive(Debug)]
#[repr(transparent)]
pub struct ErroredRead<T>(pub T);
pub(crate) trait ArcRW: Sized {
type Target;
fn mread(&self) -> Result<RwLockReadGuard<'_, Self::Target>, PoisonError<ErroredRead<Self>>>;
fn mwrite(&self)
-> Result<RwLockWriteGuard<'_, Self::Target>, PoisonError<ErroredWrite<Self>>>;
}
impl<T> ArcRW for ArcLock<T> {
type Target = T;
#[inline]
fn mread(&self) -> Result<RwLockReadGuard<'_, Self::Target>, PoisonError<ErroredRead<Self>>> {
self.read().map_err(|_| errored_read_lock(self))
}
#[inline]
fn mwrite(
&self,
) -> Result<RwLockWriteGuard<'_, Self::Target>, PoisonError<ErroredWrite<Self>>> {
self.write().map_err(|_| errored_write_lock(self))
}
}
#[inline]
pub(crate) fn errored_read_lock<T>(
errored_lock: &ArcLock<T>,
) -> PoisonError<ErroredRead<ArcLock<T>>> {
PoisonError::new(ErroredRead(Arc::clone(errored_lock)))
}
impl<T> PartialEq for ErroredRead<Arc<T>> {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
impl<T> PartialEq for ErroredRead<Weak<T>> {
fn eq(&self, other: &Self) -> bool {
Weak::ptr_eq(&self.0, &other.0)
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct ErroredWrite<T>(pub T);
#[inline]
pub(crate) fn errored_write_lock<T>(
errored_lock: &ArcLock<T>,
) -> PoisonError<ErroredWrite<ArcLock<T>>> {
PoisonError::new(ErroredWrite(Arc::clone(errored_lock)))
}
impl<T> PartialEq for ErroredWrite<Arc<T>> {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
impl<T> PartialEq for ErroredWrite<Weak<T>> {
fn eq(&self, other: &Self) -> bool {
Weak::ptr_eq(&self.0, &other.0)
}
}