reactive_graph/signal/
write.rs1use super::{guards::WriteGuard, ArcWriteSignal};
2use crate::{
3 owner::{ArenaItem, FromLocal, LocalStorage, Storage, SyncStorage},
4 traits::{
5 DefinedAt, Dispose, IntoInner, IsDisposed, Notify, UntrackableGuard,
6 Write,
7 },
8};
9use core::fmt::Debug;
10use guardian::ArcRwLockWriteGuardian;
11use std::{hash::Hash, ops::DerefMut, panic::Location, sync::Arc};
12
13pub struct WriteSignal<T, S = SyncStorage> {
56 #[cfg(any(debug_assertions, leptos_debuginfo))]
57 pub(crate) defined_at: &'static Location<'static>,
58 pub(crate) inner: ArenaItem<ArcWriteSignal<T>, S>,
59}
60
61impl<T, S> Dispose for WriteSignal<T, S> {
62 fn dispose(self) {
63 self.inner.dispose()
64 }
65}
66
67impl<T, S> Copy for WriteSignal<T, S> {}
68
69impl<T, S> Clone for WriteSignal<T, S> {
70 fn clone(&self) -> Self {
71 *self
72 }
73}
74
75impl<T, S> Debug for WriteSignal<T, S>
76where
77 S: Debug,
78{
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 f.debug_struct("WriteSignal")
81 .field("type", &std::any::type_name::<T>())
82 .field("store", &self.inner)
83 .finish()
84 }
85}
86
87impl<T, S> PartialEq for WriteSignal<T, S> {
88 fn eq(&self, other: &Self) -> bool {
89 self.inner == other.inner
90 }
91}
92
93impl<T, S> Eq for WriteSignal<T, S> {}
94
95impl<T, S> Hash for WriteSignal<T, S> {
96 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
97 self.inner.hash(state);
98 }
99}
100
101impl<T, S> DefinedAt for WriteSignal<T, S> {
102 fn defined_at(&self) -> Option<&'static Location<'static>> {
103 #[cfg(any(debug_assertions, leptos_debuginfo))]
104 {
105 Some(self.defined_at)
106 }
107 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
108 {
109 None
110 }
111 }
112}
113
114impl<T> From<ArcWriteSignal<T>> for WriteSignal<T>
115where
116 T: Send + Sync + 'static,
117{
118 #[track_caller]
119 fn from(value: ArcWriteSignal<T>) -> Self {
120 WriteSignal {
121 #[cfg(any(debug_assertions, leptos_debuginfo))]
122 defined_at: Location::caller(),
123 inner: ArenaItem::new_with_storage(value),
124 }
125 }
126}
127
128impl<T> FromLocal<ArcWriteSignal<T>> for WriteSignal<T, LocalStorage>
129where
130 T: 'static,
131{
132 #[track_caller]
133 fn from_local(value: ArcWriteSignal<T>) -> Self {
134 WriteSignal {
135 #[cfg(any(debug_assertions, leptos_debuginfo))]
136 defined_at: Location::caller(),
137 inner: ArenaItem::new_with_storage(value),
138 }
139 }
140}
141
142impl<T, S> IsDisposed for WriteSignal<T, S> {
143 fn is_disposed(&self) -> bool {
144 self.inner.is_disposed()
145 }
146}
147
148impl<T, S> IntoInner for WriteSignal<T, S>
149where
150 S: Storage<ArcWriteSignal<T>>,
151{
152 type Value = T;
153
154 #[inline(always)]
155 fn into_inner(self) -> Option<Self::Value> {
156 self.inner.into_inner()?.into_inner()
157 }
158}
159
160impl<T, S> Notify for WriteSignal<T, S>
161where
162 T: 'static,
163 S: Storage<ArcWriteSignal<T>>,
164{
165 fn notify(&self) {
166 if let Some(inner) = self.inner.try_get_value() {
167 inner.notify();
168 }
169 }
170}
171
172impl<T, S> Write for WriteSignal<T, S>
173where
174 T: 'static,
175 S: Storage<ArcWriteSignal<T>>,
176{
177 type Value = T;
178
179 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
180 let guard = self.inner.try_with_value(|n| {
181 ArcRwLockWriteGuardian::take(Arc::clone(&n.value)).ok()
182 })??;
183 Some(WriteGuard::new(*self, guard))
184 }
185
186 fn try_write_untracked(
187 &self,
188 ) -> Option<impl DerefMut<Target = Self::Value>> {
189 self.inner
190 .try_with_value(|n| n.try_write_untracked())
191 .flatten()
192 }
193}