diff options
Diffstat (limited to 'ecs/src/lock.rs')
-rw-r--r-- | ecs/src/lock.rs | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/ecs/src/lock.rs b/ecs/src/lock.rs index 0b36922..fe4e08b 100644 --- a/ecs/src/lock.rs +++ b/ecs/src/lock.rs @@ -1,3 +1,4 @@ +use std::any::type_name; use std::mem::forget; use std::ops::{Deref, DerefMut}; @@ -30,7 +31,7 @@ impl<Value> Lock<Value> /// /// # 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)?; @@ -46,7 +47,7 @@ impl<Value> Lock<Value> /// /// # 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)?; @@ -62,6 +63,14 @@ impl<Value> Lock<Value> } } +impl<Value: Default + 'static> Default for Lock<Value> +{ + fn default() -> Self + { + Self::new(Value::default(), type_name::<Value>()) + } +} + #[derive(Debug, thiserror::Error)] pub enum Error { @@ -81,21 +90,26 @@ pub struct ReadGuard<'guard, Value> impl<'guard, Value> ReadGuard<'guard, Value> { - pub fn map<NewValue>( - self, - func: impl FnOnce(&Value) -> &NewValue, - ) -> MappedReadGuard<'guard, NewValue> + pub fn try_map<NewValue>( + this: Self, + func: impl FnOnce(&Value) -> Option<&NewValue>, + ) -> Result<MappedReadGuard<'guard, NewValue>, Self> { - let value_type_name = self.value_type_name; + 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), - value_type_name, + 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, + }), } } } @@ -155,21 +169,26 @@ pub struct WriteGuard<'guard, Value> impl<'guard, Value> WriteGuard<'guard, Value> { - pub fn map<NewValue>( - self, - func: impl FnOnce(&mut Value) -> &mut NewValue, - ) -> MappedWriteGuard<'guard, NewValue> + pub fn try_map<NewValue>( + this: Self, + func: impl FnOnce(&mut Value) -> Option<&mut NewValue>, + ) -> Result<MappedWriteGuard<'guard, NewValue>, Self> { - let value_type_name = self.value_type_name; + 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), - value_type_name, + 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, + }), } } } |