From 8022e8998290b067b8aa0cb9cba8ba410826bdab Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 21 May 2026 17:55:20 +0200 Subject: chore: rename ecs* crates to engine-ecs* --- engine-ecs/src/lock.rs | 259 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 engine-ecs/src/lock.rs (limited to 'engine-ecs/src/lock.rs') diff --git a/engine-ecs/src/lock.rs b/engine-ecs/src/lock.rs new file mode 100644 index 0000000..fe4e08b --- /dev/null +++ b/engine-ecs/src/lock.rs @@ -0,0 +1,259 @@ +use std::any::type_name; +use std::mem::forget; +use std::ops::{Deref, DerefMut}; + +use parking_lot::{ + MappedRwLockReadGuard, + MappedRwLockWriteGuard, + RwLock, + RwLockReadGuard, + RwLockWriteGuard, +}; + +#[derive(Debug)] +pub struct Lock +{ + inner: RwLock, + value_type_name: &'static str, +} + +impl Lock +{ + pub fn new(value: Value, value_type_name: &'static str) -> Self + { + 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, Error> + { + let guard = self.inner.try_read().ok_or(Error::ReadUnavailable)?; + + tracing::trace!("Acquired lock to value of type {}", self.value_type_name); + + 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, Error> + { + let guard = self.inner.try_write().ok_or(Error::WriteUnavailable)?; + + tracing::trace!( + "Acquired mutable lock to value of type {}", + self.value_type_name + ); + + Ok(WriteGuard { + inner: guard, + value_type_name: self.value_type_name, + }) + } +} + +impl Default for Lock +{ + fn default() -> Self + { + Self::new(Value::default(), type_name::()) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum Error +{ + #[error("Lock is unavailable for reading")] + ReadUnavailable, + + #[error("Lock is unavailable for writing")] + WriteUnavailable, +} + +#[derive(Debug)] +pub struct ReadGuard<'guard, Value> +{ + inner: RwLockReadGuard<'guard, Value>, + value_type_name: &'static str, +} + +impl<'guard, Value> ReadGuard<'guard, Value> +{ + pub fn try_map( + this: Self, + func: impl FnOnce(&Value) -> Option<&NewValue>, + ) -> Result, 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(&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, + }), + } + } +} + +impl Deref for ReadGuard<'_, Value> +{ + type Target = Value; + + fn deref(&self) -> &Self::Target + { + &self.inner + } +} + +impl Drop for ReadGuard<'_, Value> +{ + fn drop(&mut self) + { + tracing::trace!("Dropped lock to value of type {}", self.value_type_name); + } +} + +#[derive(Debug)] +pub struct MappedReadGuard<'guard, Value> +{ + inner: MappedRwLockReadGuard<'guard, Value>, + value_type_name: &'static str, +} + +impl Deref for MappedReadGuard<'_, Value> +{ + type Target = Value; + + fn deref(&self) -> &Self::Target + { + &self.inner + } +} + +impl Drop for MappedReadGuard<'_, Value> +{ + fn drop(&mut self) + { + tracing::trace!( + "Dropped mapped lock to value of type {}", + self.value_type_name + ); + } +} + +#[derive(Debug)] +pub struct WriteGuard<'guard, Value> +{ + inner: RwLockWriteGuard<'guard, Value>, + value_type_name: &'static str, +} + +impl<'guard, Value> WriteGuard<'guard, Value> +{ + pub fn try_map( + this: Self, + func: impl FnOnce(&mut Value) -> Option<&mut NewValue>, + ) -> Result, 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(&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 Deref for WriteGuard<'_, Value> +{ + type Target = Value; + + fn deref(&self) -> &Self::Target + { + &self.inner + } +} + +impl DerefMut for WriteGuard<'_, Value> +{ + fn deref_mut(&mut self) -> &mut Self::Target + { + &mut self.inner + } +} + +impl Drop for WriteGuard<'_, Value> +{ + fn drop(&mut self) + { + tracing::trace!( + "Dropped mutable lock to value of type {}", + self.value_type_name + ); + } +} + +#[derive(Debug)] +pub struct MappedWriteGuard<'guard, Value> +{ + inner: MappedRwLockWriteGuard<'guard, Value>, + value_type_name: &'static str, +} + +impl Deref for MappedWriteGuard<'_, Value> +{ + type Target = Value; + + fn deref(&self) -> &Self::Target + { + &self.inner + } +} + +impl DerefMut for MappedWriteGuard<'_, Value> +{ + fn deref_mut(&mut self) -> &mut Self::Target + { + &mut self.inner + } +} + +impl Drop for MappedWriteGuard<'_, Value> +{ + fn drop(&mut self) + { + tracing::trace!( + "Dropped mapped mutable lock to value of type {}", + self.value_type_name + ); + } +} -- cgit v1.2.3-18-g5258