reactive_graph/
signal.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//! Reactive primitives for root values that can be changed, notifying other nodes in the reactive
//! graph.

mod arc_read;
mod arc_rw;
mod arc_trigger;
mod arc_write;
pub mod guards;
mod read;
mod rw;
mod subscriber_traits;
mod trigger;
mod write;

use crate::owner::LocalStorage;
pub use arc_read::*;
pub use arc_rw::*;
pub use arc_trigger::*;
pub use arc_write::*;
pub use read::*;
pub use rw::*;
pub use trigger::*;
pub use write::*;

/// Creates a reference-counted signal.
///
/// A signal is a piece of data that may change over time, and notifies other
/// code when it has changed. This is the atomic unit of reactivity, which begins all other
/// processes of updating.
///
/// Takes the initial value as an argument, and returns a tuple containing an
/// [`ArcReadSignal`] and an [`ArcWriteSignal`].
///
/// This returns reference-counted signals, which are `Clone` but not `Copy`. For arena-allocated
/// `Copy` signals, use [`signal`].
///
/// ```
/// # use reactive_graph::prelude::*;
/// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
/// let (count, set_count) = arc_signal(0);
///
/// // ✅ calling the getter clones and returns the value
/// //    this can be `count()` on nightly
/// assert_eq!(count.get(), 0);
///
/// // ✅ calling the setter sets the value
/// //    this can be `set_count(1)` on nightly
/// set_count.set(1);
/// assert_eq!(count.get(), 1);
///
/// // ❌ you could call the getter within the setter
/// // set_count.set(count.get() + 1);
///
/// // ✅ however it's more efficient to use .update() and mutate the value in place
/// set_count.update(|count: &mut i32| *count += 1);
/// assert_eq!(count.get(), 2);
///
/// // ✅ you can create "derived signals" with a Fn() -> T interface
/// let double_count = move || count.get() * 2;
/// set_count.set(0);
/// assert_eq!(double_count(), 0);
/// set_count.set(1);
/// assert_eq!(double_count(), 2);
/// ```
#[inline(always)]
#[track_caller]
pub fn arc_signal<T>(value: T) -> (ArcReadSignal<T>, ArcWriteSignal<T>) {
    ArcRwSignal::new(value).split()
}

/// Creates an arena-allocated signal, the basic reactive primitive.
///
/// A signal is a piece of data that may change over time, and notifies other
/// code when it has changed. This is the atomic unit of reactivity, which begins all other
/// processes of updating.
///
/// Takes the initial value as an argument, and returns a tuple containing a
/// [`ReadSignal`] and a [`WriteSignal`].
///
/// This returns an arena-allocated signal, which is `Copy` and is disposed when its reactive
/// [`Owner`](crate::owner::Owner) cleans up. For a reference-counted signal that lives
/// as long as a reference to it is alive, see [`arc_signal`].
/// ```
/// # use reactive_graph::prelude::*;
/// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
/// let (count, set_count) = signal(0);
///
/// // ✅ calling the getter clones and returns the value
/// //    this can be `count()` on nightly
/// assert_eq!(count.get(), 0);
///
/// // ✅ calling the setter sets the value
/// //    this can be `set_count(1)` on nightly
/// set_count.set(1);
/// assert_eq!(count.get(), 1);
///
/// // ❌ you could call the getter within the setter
/// // set_count.set(count.get() + 1);
///
/// // ✅ however it's more efficient to use .update() and mutate the value in place
/// set_count.update(|count: &mut i32| *count += 1);
/// assert_eq!(count.get(), 2);
///
/// // ✅ you can create "derived signals" with a Fn() -> T interface
/// let double_count = move || count.get() * 2; // signals are `Copy` so you can `move` them anywhere
/// set_count.set(0);
/// assert_eq!(double_count(), 0);
/// set_count.set(1);
/// assert_eq!(double_count(), 2);
/// ```
#[inline(always)]
#[track_caller]
pub fn signal<T: Send + Sync + 'static>(
    value: T,
) -> (ReadSignal<T>, WriteSignal<T>) {
    let (r, w) = arc_signal(value);
    (r.into(), w.into())
}

/// Creates an arena-allocated signal.
///
/// Unlike [`signal`], this does not require the value to be `Send + Sync`. Instead, it is stored
/// on a local arena. Accessing either of the returned signals from another thread will panic.
#[inline(always)]
#[track_caller]
pub fn signal_local<T: 'static>(
    value: T,
) -> (ReadSignal<T, LocalStorage>, WriteSignal<T, LocalStorage>) {
    RwSignal::new_local(value).split()
}

/// Creates an arena-allocated signal, the basic reactive primitive.
///
/// A signal is a piece of data that may change over time, and notifies other
/// code when it has changed. This is the atomic unit of reactivity, which begins all other
/// processes of updating.
///
/// Takes the initial value as an argument, and returns a tuple containing a
/// [`ReadSignal`] and a [`WriteSignal`].
///
/// This returns an arena-allocated signal, which is `Copy` and is disposed when its reactive
/// [`Owner`](crate::owner::Owner) cleans up. For a reference-counted signal that lives
/// as long as a reference to it is alive, see [`arc_signal`].
/// ```
/// # use reactive_graph::prelude::*;
/// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
/// let (count, set_count) = create_signal(0);
///
/// // ✅ calling the getter clones and returns the value
/// //    this can be `count()` on nightly
/// assert_eq!(count.get(), 0);
///
/// // ✅ calling the setter sets the value
/// //    this can be `set_count(1)` on nightly
/// set_count.set(1);
/// assert_eq!(count.get(), 1);
///
/// // ❌ you could call the getter within the setter
/// // set_count.set(count.get() + 1);
///
/// // ✅ however it's more efficient to use .update() and mutate the value in place
/// set_count.update(|count: &mut i32| *count += 1);
/// assert_eq!(count.get(), 2);
///
/// // ✅ you can create "derived signals" with a Fn() -> T interface
/// let double_count = move || count.get() * 2; // signals are `Copy` so you can `move` them anywhere
/// set_count.set(0);
/// assert_eq!(double_count(), 0);
/// set_count.set(1);
/// assert_eq!(double_count(), 2);
/// ```
#[inline(always)]
#[track_caller]
#[deprecated = "This function is being renamed to `signal()` to conform to \
                Rust idioms."]
pub fn create_signal<T: Send + Sync + 'static>(
    value: T,
) -> (ReadSignal<T>, WriteSignal<T>) {
    signal(value)
}

/// Creates a reactive signal with the getter and setter unified in one value.
#[inline(always)]
#[track_caller]
#[deprecated = "This function is being removed to conform to Rust idioms. \
                Please use `RwSignal::new()` instead."]
pub fn create_rw_signal<T: Send + Sync + 'static>(value: T) -> RwSignal<T> {
    RwSignal::new(value)
}

/// A trigger is a data-less signal with the sole purpose of notifying other reactive code of a change.
#[inline(always)]
#[track_caller]
#[deprecated = "This function is being removed to conform to Rust idioms. \
                Please use `ArcTrigger::new()` instead."]
pub fn create_trigger() -> ArcTrigger {
    ArcTrigger::new()
}