reactive_graph/signal/
arc_write.rs1use super::guards::{UntrackedWriteGuard, WriteGuard};
2use crate::{
3 graph::{ReactiveNode, SubscriberSet},
4 prelude::{IsDisposed, Notify},
5 traits::{DefinedAt, IntoInner, UntrackableGuard, Write},
6};
7use core::fmt::{Debug, Formatter, Result};
8use std::{
9 hash::Hash,
10 panic::Location,
11 sync::{Arc, RwLock},
12};
13
14pub struct ArcWriteSignal<T> {
57 #[cfg(any(debug_assertions, leptos_debuginfo))]
58 pub(crate) defined_at: &'static Location<'static>,
59 pub(crate) value: Arc<RwLock<T>>,
60 pub(crate) inner: Arc<RwLock<SubscriberSet>>,
61}
62
63impl<T> Clone for ArcWriteSignal<T> {
64 #[track_caller]
65 fn clone(&self) -> Self {
66 Self {
67 #[cfg(any(debug_assertions, leptos_debuginfo))]
68 defined_at: self.defined_at,
69 value: Arc::clone(&self.value),
70 inner: Arc::clone(&self.inner),
71 }
72 }
73}
74
75impl<T> Debug for ArcWriteSignal<T> {
76 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
77 f.debug_struct("ArcWriteSignal")
78 .field("type", &std::any::type_name::<T>())
79 .field("value", &Arc::as_ptr(&self.value))
80 .finish()
81 }
82}
83
84impl<T> PartialEq for ArcWriteSignal<T> {
85 fn eq(&self, other: &Self) -> bool {
86 Arc::ptr_eq(&self.value, &other.value)
87 }
88}
89
90impl<T> Eq for ArcWriteSignal<T> {}
91
92impl<T> Hash for ArcWriteSignal<T> {
93 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
94 std::ptr::hash(&Arc::as_ptr(&self.value), state);
95 }
96}
97
98impl<T> DefinedAt for ArcWriteSignal<T> {
99 #[inline(always)]
100 fn defined_at(&self) -> Option<&'static Location<'static>> {
101 #[cfg(any(debug_assertions, leptos_debuginfo))]
102 {
103 Some(self.defined_at)
104 }
105 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
106 {
107 None
108 }
109 }
110}
111
112impl<T> IsDisposed for ArcWriteSignal<T> {
113 #[inline(always)]
114 fn is_disposed(&self) -> bool {
115 false
116 }
117}
118
119impl<T> IntoInner for ArcWriteSignal<T> {
120 type Value = T;
121
122 #[inline(always)]
123 fn into_inner(self) -> Option<Self::Value> {
124 Some(Arc::into_inner(self.value)?.into_inner().unwrap())
125 }
126}
127
128impl<T> Notify for ArcWriteSignal<T> {
129 fn notify(&self) {
130 self.inner.mark_dirty();
131 }
132}
133
134impl<T: 'static> Write for ArcWriteSignal<T> {
135 type Value = T;
136
137 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
138 self.value
139 .write()
140 .ok()
141 .map(|guard| WriteGuard::new(self.clone(), guard))
142 }
143
144 #[allow(refining_impl_trait)]
145 fn try_write_untracked(&self) -> Option<UntrackedWriteGuard<Self::Value>> {
146 UntrackedWriteGuard::try_new(Arc::clone(&self.value))
147 }
148}