use super::guards::{UntrackedWriteGuard, WriteGuard};
use crate::{
graph::{ReactiveNode, SubscriberSet},
prelude::{IsDisposed, Notify},
traits::{DefinedAt, IntoInner, UntrackableGuard, Write},
};
use core::fmt::{Debug, Formatter, Result};
use std::{
hash::Hash,
panic::Location,
sync::{Arc, RwLock},
};
pub struct ArcWriteSignal<T> {
#[cfg(any(debug_assertions, leptos_debuginfo))]
pub(crate) defined_at: &'static Location<'static>,
pub(crate) value: Arc<RwLock<T>>,
pub(crate) inner: Arc<RwLock<SubscriberSet>>,
}
impl<T> Clone for ArcWriteSignal<T> {
#[track_caller]
fn clone(&self) -> Self {
Self {
#[cfg(any(debug_assertions, leptos_debuginfo))]
defined_at: self.defined_at,
value: Arc::clone(&self.value),
inner: Arc::clone(&self.inner),
}
}
}
impl<T> Debug for ArcWriteSignal<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.debug_struct("ArcWriteSignal")
.field("type", &std::any::type_name::<T>())
.field("value", &Arc::as_ptr(&self.value))
.finish()
}
}
impl<T> PartialEq for ArcWriteSignal<T> {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.value, &other.value)
}
}
impl<T> Eq for ArcWriteSignal<T> {}
impl<T> Hash for ArcWriteSignal<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
std::ptr::hash(&Arc::as_ptr(&self.value), state);
}
}
impl<T> DefinedAt for ArcWriteSignal<T> {
#[inline(always)]
fn defined_at(&self) -> Option<&'static Location<'static>> {
#[cfg(any(debug_assertions, leptos_debuginfo))]
{
Some(self.defined_at)
}
#[cfg(not(any(debug_assertions, leptos_debuginfo)))]
{
None
}
}
}
impl<T> IsDisposed for ArcWriteSignal<T> {
#[inline(always)]
fn is_disposed(&self) -> bool {
false
}
}
impl<T> IntoInner for ArcWriteSignal<T> {
type Value = T;
#[inline(always)]
fn into_inner(self) -> Option<Self::Value> {
Some(Arc::into_inner(self.value)?.into_inner().unwrap())
}
}
impl<T> Notify for ArcWriteSignal<T> {
fn notify(&self) {
self.inner.mark_dirty();
}
}
impl<T: 'static> Write for ArcWriteSignal<T> {
type Value = T;
fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
self.value
.write()
.ok()
.map(|guard| WriteGuard::new(self.clone(), guard))
}
#[allow(refining_impl_trait)]
fn try_write_untracked(&self) -> Option<UntrackedWriteGuard<Self::Value>> {
UntrackedWriteGuard::try_new(Arc::clone(&self.value))
}
}