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.rs122
1 files changed, 120 insertions, 2 deletions
diff --git a/ecs/src/lock.rs b/ecs/src/lock.rs
index 74b0415..c700098 100644
--- a/ecs/src/lock.rs
+++ b/ecs/src/lock.rs
@@ -1,7 +1,13 @@
-use std::mem::transmute;
+use std::mem::{forget, transmute};
use std::ops::{Deref, DerefMut};
-use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
+use parking_lot::{
+ MappedRwLockReadGuard,
+ MappedRwLockWriteGuard,
+ RwLock,
+ RwLockReadGuard,
+ RwLockWriteGuard,
+};
use crate::type_name::TypeName;
@@ -79,6 +85,23 @@ 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,
+ {
+ // 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
@@ -114,6 +137,36 @@ where
}
#[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,
@@ -121,6 +174,28 @@ where
inner: RwLockWriteGuard<'guard, Value>,
}
+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,
+ {
+ // 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,
@@ -152,3 +227,46 @@ where
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()
+ );
+ }
+}