diff options
Diffstat (limited to 'ecs/src/lock.rs')
-rw-r--r-- | ecs/src/lock.rs | 161 |
1 files changed, 74 insertions, 87 deletions
diff --git a/ecs/src/lock.rs b/ecs/src/lock.rs index 1ce13fc..fe4e08b 100644 --- a/ecs/src/lock.rs +++ b/ecs/src/lock.rs @@ -1,4 +1,5 @@ -use std::mem::{forget, transmute}; +use std::any::type_name; +use std::mem::forget; use std::ops::{Deref, DerefMut}; use parking_lot::{ @@ -9,57 +10,64 @@ use parking_lot::{ RwLockWriteGuard, }; -use crate::type_name::TypeName; - -#[derive(Debug, Default)] +#[derive(Debug)] pub struct Lock<Value> -where - Value: TypeName, { inner: RwLock<Value>, + value_type_name: &'static str, } impl<Value> Lock<Value> -where - Value: TypeName, { - pub fn new(value: Value) -> Self + pub fn new(value: Value, value_type_name: &'static str) -> Self { - Self { inner: RwLock::new(value) } + Self { + inner: RwLock::new(value), + value_type_name, + } } /// 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<ReadGuard<Value>, Error> + pub fn read_nonblock(&self) -> Result<ReadGuard<'_, Value>, Error> { let guard = self.inner.try_read().ok_or(Error::ReadUnavailable)?; - tracing::trace!("Acquired lock to value of type {}", guard.type_name()); + tracing::trace!("Acquired lock to value of type {}", self.value_type_name); - Ok(ReadGuard { inner: guard }) + Ok(ReadGuard { + inner: guard, + value_type_name: self.value_type_name, + }) } /// 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<WriteGuard<Value>, Error> + pub fn write_nonblock(&self) -> Result<WriteGuard<'_, Value>, Error> { let guard = self.inner.try_write().ok_or(Error::WriteUnavailable)?; tracing::trace!( "Acquired mutable lock to value of type {}", - guard.type_name() + self.value_type_name ); - Ok(WriteGuard { inner: guard }) + Ok(WriteGuard { + inner: guard, + value_type_name: self.value_type_name, + }) } +} - pub fn into_inner(self) -> Value +impl<Value: Default + 'static> Default for Lock<Value> +{ + fn default() -> Self { - self.inner.into_inner() + Self::new(Value::default(), type_name::<Value>()) } } @@ -75,48 +83,38 @@ pub enum Error #[derive(Debug)] pub struct ReadGuard<'guard, Value> -where - Value: TypeName, { inner: RwLockReadGuard<'guard, Value>, + value_type_name: &'static str, } impl<'guard, Value> ReadGuard<'guard, Value> -where - Value: TypeName, { - pub fn map<NewValue>( - self, - func: impl FnOnce(&Value) -> &NewValue, - ) -> MappedReadGuard<'guard, NewValue> - where - NewValue: TypeName, + pub fn try_map<NewValue>( + this: Self, + func: impl FnOnce(&Value) -> Option<&NewValue>, + ) -> Result<MappedReadGuard<'guard, NewValue>, Self> { + let value_type_name = this.value_type_name; + // 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), + let inner = unsafe { std::ptr::read(&raw const this.inner) }; + forget(this); + + match RwLockReadGuard::try_map(inner, func) { + Ok(mapped_guard) => { + Ok(MappedReadGuard { inner: mapped_guard, value_type_name }) + } + Err(unmapped_guard) => Err(Self { + inner: unmapped_guard, + value_type_name, + }), } } - - /// 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<Value> Deref for ReadGuard<'_, Value> -where - Value: TypeName, { type Target = Value; @@ -127,26 +125,21 @@ where } impl<Value> Drop for ReadGuard<'_, Value> -where - Value: TypeName, { fn drop(&mut self) { - tracing::trace!("Dropped lock to value of type {}", self.type_name()); + tracing::trace!("Dropped lock to value of type {}", self.value_type_name); } } #[derive(Debug)] pub struct MappedReadGuard<'guard, Value> -where - Value: TypeName, { inner: MappedRwLockReadGuard<'guard, Value>, + value_type_name: &'static str, } impl<Value> Deref for MappedReadGuard<'_, Value> -where - Value: TypeName, { type Target = Value; @@ -157,48 +150,50 @@ where } impl<Value> Drop for MappedReadGuard<'_, Value> -where - Value: TypeName, { fn drop(&mut self) { - tracing::trace!("Dropped mapped lock to value of type {}", self.type_name()); + tracing::trace!( + "Dropped mapped lock to value of type {}", + self.value_type_name + ); } } #[derive(Debug)] pub struct WriteGuard<'guard, Value> -where - Value: TypeName, { inner: RwLockWriteGuard<'guard, Value>, + value_type_name: &'static str, } impl<'guard, Value> WriteGuard<'guard, Value> -where - Value: TypeName, { - pub fn map<NewValue>( - self, - func: impl FnOnce(&mut Value) -> &mut NewValue, - ) -> MappedWriteGuard<'guard, NewValue> - where - NewValue: TypeName, + pub fn try_map<NewValue>( + this: Self, + func: impl FnOnce(&mut Value) -> Option<&mut NewValue>, + ) -> Result<MappedWriteGuard<'guard, NewValue>, Self> { + let value_type_name = this.value_type_name; + // 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), + let inner = unsafe { std::ptr::read(&raw const this.inner) }; + forget(this); + + match RwLockWriteGuard::try_map(inner, func) { + Ok(mapped_guard) => { + Ok(MappedWriteGuard { inner: mapped_guard, value_type_name }) + } + Err(unmapped_guard) => Err(Self { + inner: unmapped_guard, + value_type_name, + }), } } } impl<Value> Deref for WriteGuard<'_, Value> -where - Value: TypeName, { type Target = Value; @@ -209,8 +204,6 @@ where } impl<Value> DerefMut for WriteGuard<'_, Value> -where - Value: TypeName, { fn deref_mut(&mut self) -> &mut Self::Target { @@ -219,26 +212,24 @@ where } impl<Value> Drop for WriteGuard<'_, Value> -where - Value: TypeName, { fn drop(&mut self) { - tracing::trace!("Dropped mutable lock to value of type {}", self.type_name()); + tracing::trace!( + "Dropped mutable lock to value of type {}", + self.value_type_name + ); } } #[derive(Debug)] pub struct MappedWriteGuard<'guard, Value> -where - Value: TypeName, { inner: MappedRwLockWriteGuard<'guard, Value>, + value_type_name: &'static str, } impl<Value> Deref for MappedWriteGuard<'_, Value> -where - Value: TypeName, { type Target = Value; @@ -249,8 +240,6 @@ where } impl<Value> DerefMut for MappedWriteGuard<'_, Value> -where - Value: TypeName, { fn deref_mut(&mut self) -> &mut Self::Target { @@ -259,14 +248,12 @@ where } impl<Value> Drop for MappedWriteGuard<'_, Value> -where - Value: TypeName, { fn drop(&mut self) { tracing::trace!( "Dropped mapped mutable lock to value of type {}", - self.type_name() + self.value_type_name ); } } |