reactive_graph/signal/
arc_read.rs1use super::{
2 guards::{Plain, ReadGuard},
3 subscriber_traits::AsSubscriberSet,
4};
5use crate::{
6 graph::SubscriberSet,
7 traits::{DefinedAt, IntoInner, IsDisposed, ReadUntracked},
8};
9use core::fmt::{Debug, Formatter, Result};
10use std::{
11 hash::Hash,
12 panic::Location,
13 sync::{Arc, RwLock},
14};
15
16pub struct ArcReadSignal<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 ArcReadSignal<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 ArcReadSignal<T> {
76 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
77 f.debug_struct("ArcReadSignal")
78 .field("type", &std::any::type_name::<T>())
79 .field("value", &Arc::as_ptr(&self.value))
80 .finish()
81 }
82}
83
84impl<T: Default> Default for ArcReadSignal<T> {
85 #[track_caller]
86 fn default() -> Self {
87 Self {
88 #[cfg(any(debug_assertions, leptos_debuginfo))]
89 defined_at: Location::caller(),
90 value: Arc::new(RwLock::new(T::default())),
91 inner: Arc::new(RwLock::new(SubscriberSet::new())),
92 }
93 }
94}
95
96impl<T> PartialEq for ArcReadSignal<T> {
97 fn eq(&self, other: &Self) -> bool {
98 Arc::ptr_eq(&self.value, &other.value)
99 }
100}
101
102impl<T> Eq for ArcReadSignal<T> {}
103
104impl<T> Hash for ArcReadSignal<T> {
105 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
106 std::ptr::hash(&Arc::as_ptr(&self.value), state);
107 }
108}
109
110impl<T> DefinedAt for ArcReadSignal<T> {
111 #[inline(always)]
112 fn defined_at(&self) -> Option<&'static Location<'static>> {
113 #[cfg(any(debug_assertions, leptos_debuginfo))]
114 {
115 Some(self.defined_at)
116 }
117 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
118 {
119 None
120 }
121 }
122}
123
124impl<T> IsDisposed for ArcReadSignal<T> {
125 #[inline(always)]
126 fn is_disposed(&self) -> bool {
127 false
128 }
129}
130
131impl<T> IntoInner for ArcReadSignal<T> {
132 type Value = T;
133
134 #[inline(always)]
135 fn into_inner(self) -> Option<Self::Value> {
136 Some(Arc::into_inner(self.value)?.into_inner().unwrap())
137 }
138}
139
140impl<T> AsSubscriberSet for ArcReadSignal<T> {
141 type Output = Arc<RwLock<SubscriberSet>>;
142
143 #[inline(always)]
144 fn as_subscriber_set(&self) -> Option<Self::Output> {
145 Some(Arc::clone(&self.inner))
146 }
147}
148
149impl<T: 'static> ReadUntracked for ArcReadSignal<T> {
150 type Value = ReadGuard<T, Plain<T>>;
151
152 #[track_caller]
153 fn try_read_untracked(&self) -> Option<Self::Value> {
154 Plain::try_new(Arc::clone(&self.value)).map(ReadGuard::new)
155 }
156}