use std::mem::{forget, transmute}; use std::ops::{Deref, DerefMut}; use parking_lot::{ MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard, }; use crate::type_name::TypeName; #[derive(Debug, Default)] pub struct Lock where Value: TypeName, { inner: RwLock, } impl Lock where Value: TypeName, { pub fn new(value: Value) -> Self { Self { inner: RwLock::new(value) } } /// Tries to a acquire a handle to the resource with read access. /// /// # Errors /// Returns `Err` if unavailable (A mutable handle is hold). pub fn read_nonblock(&self) -> Result, Error> { let guard = self.inner.try_read().ok_or(Error::ReadUnavailable)?; tracing::trace!("Acquired lock to value of type {}", guard.type_name()); Ok(ReadGuard { inner: guard }) } /// Tries to a acquire a handle to the resource with mutable access. /// /// # Errors /// Returns `Err` if unavailable (A mutable or immutable handle is hold). pub fn write_nonblock(&self) -> Result, Error> { let guard = self.inner.try_write().ok_or(Error::WriteUnavailable)?; tracing::trace!( "Acquired mutable lock to value of type {}", guard.type_name() ); Ok(WriteGuard { inner: guard }) } pub fn into_inner(self) -> Value { self.inner.into_inner() } } #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Lock is unavailable for reading")] ReadUnavailable, #[error("Lock is unavailable for writing")] WriteUnavailable, } #[derive(Debug)] pub struct ReadGuard<'guard, Value> where Value: TypeName, { inner: RwLockReadGuard<'guard, Value>, } impl<'guard, Value> ReadGuard<'guard, Value> where Value: TypeName, { pub fn map( self, func: impl FnOnce(&Value) -> &NewValue, ) -> MappedReadGuard<'guard, NewValue> where NewValue: TypeName, { // The 'inner' field cannot be moved out of ReadGuard in a normal way since // ReadGuard implements Drop let inner = unsafe { std::ptr::read(&self.inner) }; forget(self); MappedReadGuard { inner: RwLockReadGuard::map(inner, func), } } /// Converts the `ReadGuard` to a `ReadGuard` with a possibly longer lifetime. /// /// # Safety /// The returned `ReadGuard` must **NOT** be used for longer than the original /// lifetime. #[must_use] pub unsafe fn upgrade_lifetime<'new>(self) -> ReadGuard<'new, Value> { unsafe { transmute(self) } } } impl<'guard, Value> Deref for ReadGuard<'guard, Value> where Value: TypeName, { type Target = Value; fn deref(&self) -> &Self::Target { &self.inner } } impl<'guard, Value> Drop for ReadGuard<'guard, Value> where Value: TypeName, { fn drop(&mut self) { tracing::trace!("Dropped lock to value of type {}", self.type_name()); } } #[derive(Debug)] pub struct MappedReadGuard<'guard, Value> where Value: TypeName, { inner: MappedRwLockReadGuard<'guard, Value>, } impl<'guard, Value> Deref for MappedReadGuard<'guard, Value> where Value: TypeName, { type Target = Value; fn deref(&self) -> &Self::Target { &self.inner } } impl<'guard, Value> Drop for MappedReadGuard<'guard, Value> where Value: TypeName, { fn drop(&mut self) { tracing::trace!("Dropped mapped lock to value of type {}", self.type_name()); } } #[derive(Debug)] pub struct WriteGuard<'guard, Value> where Value: TypeName, { inner: RwLockWriteGuard<'guard, Value>, } impl<'guard, Value> WriteGuard<'guard, Value> where Value: TypeName, { pub fn map( self, func: impl FnOnce(&mut Value) -> &mut NewValue, ) -> MappedWriteGuard<'guard, NewValue> where NewValue: TypeName, { // The 'inner' field cannot be moved out of ReadGuard in a normal way since // ReadGuard implements Drop let inner = unsafe { std::ptr::read(&self.inner) }; forget(self); MappedWriteGuard { inner: RwLockWriteGuard::map(inner, func), } } } impl<'guard, Value> Deref for WriteGuard<'guard, Value> where Value: TypeName, { type Target = Value; fn deref(&self) -> &Self::Target { &self.inner } } impl<'guard, Value> DerefMut for WriteGuard<'guard, Value> where Value: TypeName, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } impl<'guard, Value> Drop for WriteGuard<'guard, Value> where Value: TypeName, { fn drop(&mut self) { tracing::trace!("Dropped mutable lock to value of type {}", self.type_name()); } } #[derive(Debug)] pub struct MappedWriteGuard<'guard, Value> where Value: TypeName, { inner: MappedRwLockWriteGuard<'guard, Value>, } impl<'guard, Value> Deref for MappedWriteGuard<'guard, Value> where Value: TypeName, { type Target = Value; fn deref(&self) -> &Self::Target { &self.inner } } impl<'guard, Value> DerefMut for MappedWriteGuard<'guard, Value> where Value: TypeName, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } impl<'guard, Value> Drop for MappedWriteGuard<'guard, Value> where Value: TypeName, { fn drop(&mut self) { tracing::trace!( "Dropped mapped mutable lock to value of type {}", self.type_name() ); } }