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.rs161
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
);
}
}