use super::{guards::WriteGuard, ArcWriteSignal};
use crate::{
owner::{Storage, StoredValue, SyncStorage},
traits::{
DefinedAt, Dispose, IsDisposed, Trigger, UntrackableGuard, Writeable,
},
};
use core::fmt::Debug;
use guardian::ArcRwLockWriteGuardian;
use std::{hash::Hash, ops::DerefMut, panic::Location, sync::Arc};
pub struct WriteSignal<T, S = SyncStorage> {
#[cfg(debug_assertions)]
pub(crate) defined_at: &'static Location<'static>,
pub(crate) inner: StoredValue<ArcWriteSignal<T>, S>,
}
impl<T, S> Dispose for WriteSignal<T, S> {
fn dispose(self) {
self.inner.dispose()
}
}
impl<T, S> Copy for WriteSignal<T, S> {}
impl<T, S> Clone for WriteSignal<T, S> {
fn clone(&self) -> Self {
*self
}
}
impl<T, S> Debug for WriteSignal<T, S>
where
S: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WriteSignal")
.field("type", &std::any::type_name::<T>())
.field("store", &self.inner)
.finish()
}
}
impl<T, S> PartialEq for WriteSignal<T, S> {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl<T, S> Eq for WriteSignal<T, S> {}
impl<T, S> Hash for WriteSignal<T, S> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inner.hash(state);
}
}
impl<T, S> DefinedAt for WriteSignal<T, S> {
fn defined_at(&self) -> Option<&'static Location<'static>> {
#[cfg(debug_assertions)]
{
Some(self.defined_at)
}
#[cfg(not(debug_assertions))]
{
None
}
}
}
impl<T, S> IsDisposed for WriteSignal<T, S> {
fn is_disposed(&self) -> bool {
self.inner.is_disposed()
}
}
impl<T, S> Trigger for WriteSignal<T, S>
where
T: 'static,
S: Storage<ArcWriteSignal<T>>,
{
fn trigger(&self) {
if let Some(inner) = self.inner.try_get_value() {
inner.trigger();
}
}
}
impl<T, S> Writeable for WriteSignal<T, S>
where
T: 'static,
S: Storage<ArcWriteSignal<T>>,
{
type Value = T;
fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
let guard = self.inner.try_with_value(|n| {
ArcRwLockWriteGuardian::take(Arc::clone(&n.value)).ok()
})??;
Some(WriteGuard::new(*self, guard))
}
fn try_write_untracked(
&self,
) -> Option<impl DerefMut<Target = Self::Value>> {
self.inner.with_value(|n| n.try_write_untracked())
}
}