reactivate/
lib.rs

1//! Thread Safe Reactive Data Structure. Made with ❤️ for 🦀
2//!
3//! # Reactive
4//!
5//! `Reactive` is a thread-safe reactive data structure for managing state changes
6//! in single-threaded or multi-threaded environments. It allows users to create reactive values that automatically
7//! notifies observers when their underlying values change.
8//!
9//! ## Update
10//!
11//! ```
12//! use reactivate::Reactive;
13//!
14//! let r = Reactive::new(10);
15//! let d = r.derive(|val| val + 5);
16//!
17//! r.update(|val| val * 2);
18//! r.update_inplace(|val| *val += 1);
19//! r.update_unchecked(|val| val * 2);
20//! r.update_inplace_unchecked(|val| *val += 1);
21//!
22//! println!("{:?}", r); // Reactive(43)
23//! println!("{:?}", d); // Reactive(48)
24//! ```
25//!
26//! ## Observers
27//!
28//! ```
29//! use reactivate::Reactive;
30//! # use std::rc::Rc;
31//! # use std::cell::RefCell;
32//! # use std::sync::{Arc, Mutex};
33//!
34//! let r = Reactive::new(0);
35//!
36//! // normal observer
37//! r.add_observer(|val| println!("{}", val));
38//!
39//! // non-threadsafe observer
40//! let changes: Rc<RefCell<Vec<usize>>> = Default::default();
41//! r.add_observer({
42//!     let changes = changes.clone();
43//!     move |val| changes.borrow_mut().push(*val)
44//! });
45//!
46//! // threadsafe observer
47//! // must use Arc<Mutex<Vec<_>>> when threadsafety is enabled (features = ["threadsafe"])
48//! // because Reactive as a whole must be thread safe
49//! let tsafe_changes: Arc<Mutex<Vec<usize>>> = Default::default();
50//! r.add_observer({
51//!     let changes = tsafe_changes.clone();
52//!     move |val| changes.lock().expect("unable to acq lock").push(*val)
53//! });
54//! ```
55//!
56//! ## Merge
57//!
58//! ```
59//! use reactivate::{Merge, Reactive};
60//!
61//! let a = Reactive::new(String::from("hazash"));
62//! let b = Reactive::new(0);
63//! let d = (&a, &b).merge().derive(|(s, n)| s.len() + n);
64//!
65//! println!("{:?}", a); // Reactive("hazash")
66//! println!("{:?}", b); // Reactive(0)
67//! println!("{:?}", d); // Reactive(6)
68//!
69//! b.update(|_| 5);
70//!
71//! println!("{:?}", a); // Reactive("hazash")
72//! println!("{:?}", b); // Reactive(5)
73//! println!("{:?}", d); // Reactive(11)
74//!
75//!
76//! a.update(|_| String::from("mouse"));
77//!
78//! println!("{:?}", a); // Reactive("mouse")
79//! println!("{:?}", b); // Reactive(5)
80//! println!("{:?}", d); // Reactive(10)
81//! ```
82//!
83//! ## With Threads (features = ["threadsafe"])
84//!
85//! ```
86//! # #[cfg(feature = "threadsafe")]
87//! # {
88//! use reactivate::Reactive;
89//! use std::{thread, time::Duration};
90//!
91//! let r: Reactive<String> = Reactive::default();
92//! let d = r.derive(|s| s.len());
93//!
94//! let handle = thread::spawn({
95//!     let r = r.clone();
96//!
97//!     move || {
98//!         for _ in 0..10 {
99//!             r.update_inplace(|s| s.push('a'));
100//!             thread::sleep(Duration::from_millis(1));
101//!         }
102//!     }
103//! });
104//!
105//! for _ in 0..10 {
106//!     r.update_inplace(|s| s.push('b'));
107//!     thread::sleep(Duration::from_millis(1));
108//! }
109//!
110//! handle.join().unwrap();
111//!
112//! println!("{:?}", r); // Reactive("babababababababababa")
113//! println!("{:?}", d); // Reactive(20)
114//! # }
115//! ```
116//!
117//! ## Concurrency
118//!
119//! `Reactive` provides thread-safe implementations using `Arc` and `Mutex` for multi-threaded environments. Ensure to enable the `threadsafe` feature to use the thread-safe version.
120//!
121//! ## Performance
122//!
123//! For performance-critical scenarios, `Reactive` provides methods like `update_unchecked` and `update_inplace_unchecked` for efficient updates without checking for value changes, optimizing performance especially in cases where frequent updates occur.
124//!
125//! For more details and usage examples, refer to the individual method documentations.
126//!
127
128mod macros;
129mod merge;
130mod reactive;
131
132pub use merge::Merge;
133pub use reactive::Reactive;