summaryrefslogtreecommitdiff
path: root/ecs/src/lock.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/lock.rs')
-rw-r--r--ecs/src/lock.rs67
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,
+ }),
}
}
}