use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use crate::engine::error::AttributeError;
use crate::engine::error::AttributeInvariantViolation;
use crate::engine::storage::type_erased_attribute::TypeErasedAttribute;
type AttributeReadGuard<'a> = RwLockReadGuard<'a, Box<dyn TypeErasedAttribute>>;
type AttributeWriteGuard<'a> = RwLockWriteGuard<'a, Box<dyn TypeErasedAttribute>>;
type TryAttributeReadError<'a> = std::sync::TryLockError<AttributeReadGuard<'a>>;
#[derive(Clone)]
pub struct LockedAttribute {
inner: Arc<RwLock<Box<dyn TypeErasedAttribute>>>,
}
impl LockedAttribute {
pub fn new(attribute: Box<dyn TypeErasedAttribute>) -> Self {
Self {
inner: Arc::new(RwLock::new(attribute)),
}
}
#[inline]
pub fn read(&self) -> Result<AttributeReadGuard<'_>, AttributeError> {
self.inner.read().map_err(|_| {
AttributeError::InternalInvariant(AttributeInvariantViolation::LockPoisoned)
})
}
#[inline]
pub fn write(&self) -> Result<AttributeWriteGuard<'_>, AttributeError> {
self.inner.write().map_err(|_| {
AttributeError::InternalInvariant(AttributeInvariantViolation::LockPoisoned)
})
}
#[inline]
pub fn arc(&self) -> Arc<RwLock<Box<dyn TypeErasedAttribute>>> {
self.inner.clone()
}
pub fn into_inner(self) -> Result<Box<dyn TypeErasedAttribute>, AttributeError> {
match Arc::try_unwrap(self.inner) {
Ok(lock) => lock.into_inner().map_err(|_| {
AttributeError::InternalInvariant(AttributeInvariantViolation::LockPoisoned)
}),
Err(_) => Err(AttributeError::InternalInvariant(
AttributeInvariantViolation::StillShared,
)),
}
}
#[inline]
pub fn try_read(&self) -> Result<AttributeReadGuard<'_>, TryAttributeReadError<'_>> {
self.inner.try_read()
}
}