reactive_graph/owner/
arc_stored_value.rs1use crate::{
2 signal::guards::{Plain, ReadGuard, UntrackedWriteGuard},
3 traits::{DefinedAt, IntoInner, IsDisposed, ReadValue, WriteValue},
4};
5use std::{
6 fmt::{Debug, Formatter},
7 hash::Hash,
8 panic::Location,
9 sync::{Arc, RwLock},
10};
11
12pub struct ArcStoredValue<T> {
22 #[cfg(any(debug_assertions, leptos_debuginfo))]
23 defined_at: &'static Location<'static>,
24 value: Arc<RwLock<T>>,
25}
26
27impl<T> Clone for ArcStoredValue<T> {
28 fn clone(&self) -> Self {
29 Self {
30 #[cfg(any(debug_assertions, leptos_debuginfo))]
31 defined_at: self.defined_at,
32 value: Arc::clone(&self.value),
33 }
34 }
35}
36
37impl<T> Debug for ArcStoredValue<T> {
38 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
39 f.debug_struct("ArcStoredValue")
40 .field("type", &std::any::type_name::<T>())
41 .field("value", &Arc::as_ptr(&self.value))
42 .finish()
43 }
44}
45
46impl<T: Default> Default for ArcStoredValue<T> {
47 #[track_caller]
48 fn default() -> Self {
49 Self {
50 #[cfg(any(debug_assertions, leptos_debuginfo))]
51 defined_at: Location::caller(),
52 value: Arc::new(RwLock::new(T::default())),
53 }
54 }
55}
56
57impl<T> PartialEq for ArcStoredValue<T> {
58 fn eq(&self, other: &Self) -> bool {
59 Arc::ptr_eq(&self.value, &other.value)
60 }
61}
62
63impl<T> Eq for ArcStoredValue<T> {}
64
65impl<T> Hash for ArcStoredValue<T> {
66 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
67 std::ptr::hash(&Arc::as_ptr(&self.value), state);
68 }
69}
70
71impl<T> DefinedAt for ArcStoredValue<T> {
72 fn defined_at(&self) -> Option<&'static Location<'static>> {
73 #[cfg(any(debug_assertions, leptos_debuginfo))]
74 {
75 Some(self.defined_at)
76 }
77 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
78 {
79 None
80 }
81 }
82}
83
84impl<T> ArcStoredValue<T> {
85 #[cfg_attr(
87 feature = "tracing",
88 tracing::instrument(level = "trace", skip_all)
89 )]
90 #[track_caller]
91 pub fn new(value: T) -> Self {
92 Self {
93 #[cfg(any(debug_assertions, leptos_debuginfo))]
94 defined_at: Location::caller(),
95 value: Arc::new(RwLock::new(value)),
96 }
97 }
98}
99
100impl<T> ReadValue for ArcStoredValue<T>
101where
102 T: 'static,
103{
104 type Value = ReadGuard<T, Plain<T>>;
105
106 fn try_read_value(&self) -> Option<ReadGuard<T, Plain<T>>> {
107 Plain::try_new(Arc::clone(&self.value)).map(ReadGuard::new)
108 }
109}
110
111impl<T> WriteValue for ArcStoredValue<T>
112where
113 T: 'static,
114{
115 type Value = T;
116
117 fn try_write_value(&self) -> Option<UntrackedWriteGuard<T>> {
118 UntrackedWriteGuard::try_new(self.value.clone())
119 }
120}
121
122impl<T> IsDisposed for ArcStoredValue<T> {
123 fn is_disposed(&self) -> bool {
124 false
125 }
126}
127
128impl<T> IntoInner for ArcStoredValue<T> {
129 type Value = T;
130
131 #[inline(always)]
132 fn into_inner(self) -> Option<Self::Value> {
133 Some(Arc::into_inner(self.value)?.into_inner().unwrap())
134 }
135}