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.rs130
1 files changed, 130 insertions, 0 deletions
diff --git a/ecs/src/lock.rs b/ecs/src/lock.rs
new file mode 100644
index 0000000..ff46761
--- /dev/null
+++ b/ecs/src/lock.rs
@@ -0,0 +1,130 @@
+use std::ops::{Deref, DerefMut};
+use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError};
+
+use crate::type_name::TypeName;
+
+#[derive(Debug, Default)]
+pub struct Lock<Value>
+where
+ Value: TypeName,
+{
+ inner: RwLock<Value>,
+}
+
+impl<Value> Lock<Value>
+where
+ Value: TypeName,
+{
+ pub fn new(value: Value) -> Self
+ {
+ Self { inner: RwLock::new(value) }
+ }
+
+ pub fn read_nonblock(&self) -> Result<ReadGuard<Value>, Error>
+ {
+ let guard = self.inner.try_read().or_else(|err| match err {
+ TryLockError::WouldBlock => Err(Error::Unavailable),
+ TryLockError::Poisoned(poison_err) => Ok(poison_err.into_inner()),
+ })?;
+
+ #[cfg(feature = "debug")]
+ tracing::trace!("Acquired lock to value of type {}", guard.type_name());
+
+ Ok(ReadGuard { inner: guard })
+ }
+
+ pub fn write_nonblock(&self) -> Result<WriteGuard<Value>, Error>
+ {
+ let guard = self.inner.try_write().or_else(|err| match err {
+ TryLockError::WouldBlock => Err(Error::Unavailable),
+ TryLockError::Poisoned(poison_err) => Ok(poison_err.into_inner()),
+ })?;
+
+ #[cfg(feature = "debug")]
+ tracing::trace!(
+ "Acquired mutable lock to value of type {}",
+ guard.type_name()
+ );
+
+ Ok(WriteGuard { inner: guard })
+ }
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error
+{
+ #[error("Lock is unavailable")]
+ Unavailable,
+}
+
+#[derive(Debug)]
+pub struct ReadGuard<'guard, Value>
+where
+ Value: TypeName,
+{
+ inner: RwLockReadGuard<'guard, Value>,
+}
+
+impl<'guard, Value> Deref for ReadGuard<'guard, Value>
+where
+ Value: TypeName,
+{
+ type Target = Value;
+
+ fn deref(&self) -> &Self::Target
+ {
+ &self.inner
+ }
+}
+
+impl<'guard, Value> Drop for ReadGuard<'guard, Value>
+where
+ Value: TypeName,
+{
+ fn drop(&mut self)
+ {
+ #[cfg(feature = "debug")]
+ tracing::trace!("Dropped lock to value of type {}", self.type_name());
+ }
+}
+
+#[derive(Debug)]
+pub struct WriteGuard<'guard, Value>
+where
+ Value: TypeName,
+{
+ inner: RwLockWriteGuard<'guard, Value>,
+}
+
+impl<'guard, Value> Deref for WriteGuard<'guard, Value>
+where
+ Value: TypeName,
+{
+ type Target = Value;
+
+ fn deref(&self) -> &Self::Target
+ {
+ &self.inner
+ }
+}
+
+impl<'guard, Value> DerefMut for WriteGuard<'guard, Value>
+where
+ Value: TypeName,
+{
+ fn deref_mut(&mut self) -> &mut Self::Target
+ {
+ &mut self.inner
+ }
+}
+
+impl<'guard, Value> Drop for WriteGuard<'guard, Value>
+where
+ Value: TypeName,
+{
+ fn drop(&mut self)
+ {
+ #[cfg(feature = "debug")]
+ tracing::trace!("Dropped mutable lock to value of type {}", self.type_name());
+ }
+}