use std::ops::{Deref, DerefMut};
use std::sync::{Arc, LockResult, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
pub(crate) fn read_owned<T>(lock: &Arc<RwLock<T>>) -> LockResult<OwnedRwLockReadGuard<T>> {
OwnedRwLockReadGuard::new(lock)
}
pub(crate) fn write_owned<T>(lock: &Arc<RwLock<T>>) -> LockResult<OwnedRwLockWriteGuard<T>> {
OwnedRwLockWriteGuard::new(lock)
}
pub(crate) struct OwnedRwLockReadGuard<T: 'static> {
guard: Option<RwLockReadGuard<'static, T>>,
#[allow(unused)]
ownership: Arc<RwLock<T>>,
}
unsafe impl<T> Send for OwnedRwLockReadGuard<T> where T: Send {}
impl<T> Drop for OwnedRwLockReadGuard<T>
where
T: Sized,
{
fn drop(&mut self) {
self.guard.take();
}
}
impl<T> std::fmt::Debug for OwnedRwLockReadGuard<T>
where
T: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(guard) = self.guard.as_ref() {
write!(f, "{guard:?}")
} else {
write!(f, "none")
}
}
}
impl<T> std::fmt::Display for OwnedRwLockReadGuard<T>
where
T: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(guard) = self.guard.as_ref() {
write!(f, "{guard}")
} else {
write!(f, "none")
}
}
}
impl<T> OwnedRwLockReadGuard<T> {
fn new(lock: &Arc<RwLock<T>>) -> LockResult<Self> {
let conv = |guard: RwLockReadGuard<'_, T>| {
let guard: RwLockReadGuard<'static, T> = unsafe { std::mem::transmute(guard) };
Self {
ownership: lock.clone(),
guard: Some(guard),
}
};
let guard = lock.read().map_err(|err| {
let guard = err.into_inner();
PoisonError::new(conv(guard))
})?;
Ok(conv(guard))
}
#[allow(dead_code)]
pub fn into_inner(self) -> Arc<RwLock<T>> {
self.ownership.clone()
}
}
impl<T> Deref for OwnedRwLockReadGuard<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.guard.as_ref().unwrap()
}
}
pub(crate) struct OwnedRwLockWriteGuard<T: 'static> {
guard: Option<RwLockWriteGuard<'static, T>>,
#[allow(unused)]
ownership: Arc<RwLock<T>>,
}
unsafe impl<T> Send for OwnedRwLockWriteGuard<T> where T: Send {}
impl<T> Drop for OwnedRwLockWriteGuard<T>
where
T: Sized,
{
fn drop(&mut self) {
self.guard.take();
}
}
impl<T> std::fmt::Debug for OwnedRwLockWriteGuard<T>
where
T: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(guard) = self.guard.as_ref() {
write!(f, "{guard:?}")
} else {
write!(f, "none")
}
}
}
impl<T> std::fmt::Display for OwnedRwLockWriteGuard<T>
where
T: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(guard) = self.guard.as_ref() {
write!(f, "{guard}")
} else {
write!(f, "none")
}
}
}
impl<T> OwnedRwLockWriteGuard<T> {
fn new(lock: &Arc<RwLock<T>>) -> LockResult<Self> {
let conv = |guard: RwLockWriteGuard<'_, T>| {
let guard: RwLockWriteGuard<'static, T> = unsafe { std::mem::transmute(guard) };
Self {
ownership: lock.clone(),
guard: Some(guard),
}
};
let guard = lock.write().map_err(|err| {
let guard = err.into_inner();
PoisonError::new(conv(guard))
})?;
Ok(conv(guard))
}
#[allow(dead_code)]
pub fn into_inner(self) -> Arc<RwLock<T>> {
self.ownership.clone()
}
}
impl<T> Deref for OwnedRwLockWriteGuard<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.guard.as_ref().unwrap()
}
}
impl<T> DerefMut for OwnedRwLockWriteGuard<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.guard.as_mut().unwrap()
}
}