use std::ops::{Deref, DerefMut}; use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError}; 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) } } pub fn read_nonblock(&self) -> Result, Error> { let guard = self.inner.try_read().or_else(|err| match err { TryLockError::WouldBlock => Err(Error::Unavailable), TryLockError::Poisoned(poison_err) => Ok(poison_err.into_inner()), })?; #[cfg(feature = "debug")] tracing::trace!("Acquired lock to value of type {}", guard.type_name()); Ok(ReadGuard { inner: guard }) } pub fn write_nonblock(&self) -> Result, Error> { let guard = self.inner.try_write().or_else(|err| match err { TryLockError::WouldBlock => Err(Error::Unavailable), TryLockError::Poisoned(poison_err) => Ok(poison_err.into_inner()), })?; #[cfg(feature = "debug")] tracing::trace!( "Acquired mutable lock to value of type {}", guard.type_name() ); Ok(WriteGuard { inner: guard }) } } #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Lock is unavailable")] Unavailable, } #[derive(Debug)] pub struct ReadGuard<'guard, Value> where Value: TypeName, { inner: RwLockReadGuard<'guard, Value>, } 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) { #[cfg(feature = "debug")] tracing::trace!("Dropped 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> 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) { #[cfg(feature = "debug")] tracing::trace!("Dropped mutable lock to value of type {}", self.type_name()); } }