ori_core/reactive/
callback.rs1use std::mem;
2
3use crate::{Lock, Lockable, Sendable, Shared, Weak};
4
5struct CallbackCollection<T> {
6 callbacks: Vec<WeakCallback<T>>,
7}
8
9impl<T> Default for CallbackCollection<T> {
10 fn default() -> Self {
11 Self::new()
12 }
13}
14
15impl<T> CallbackCollection<T> {
16 fn new() -> Self {
17 Self {
18 callbacks: Vec::new(),
19 }
20 }
21
22 fn len(&self) -> usize {
23 self.callbacks.len()
24 }
25
26 fn contains(&self, ptr: CallbackPtr<T>) -> bool {
27 for callback in &self.callbacks {
28 if callback.callback.as_ptr() == ptr {
29 return true;
30 }
31 }
32
33 false
34 }
35
36 fn insert(&mut self, callback: WeakCallback<T>) {
37 if !self.contains(callback.callback.as_ptr()) {
38 self.callbacks.push(callback);
39 }
40 }
41
42 fn remove(&mut self, ptr: CallbackPtr<T>) {
43 let equals = |callback: &WeakCallback<T>| callback.callback.as_ptr() != ptr;
44 self.callbacks.retain(equals);
45 }
46}
47
48impl<T> IntoIterator for CallbackCollection<T> {
49 type Item = WeakCallback<T>;
50 type IntoIter = std::vec::IntoIter<Self::Item>;
51
52 fn into_iter(self) -> Self::IntoIter {
53 self.callbacks.into_iter()
54 }
55}
56
57#[cfg(feature = "multithread")]
58type RawCallback<'a, T> = dyn FnMut(&T) + Send + 'a;
59#[cfg(not(feature = "multithread"))]
60type RawCallback<'a, T> = dyn FnMut(&T) + 'a;
61
62type CallbackPtr<T> = *const Lock<RawCallback<'static, T>>;
63type Callbacks<T> = Lock<CallbackCollection<T>>;
64
65#[derive(Clone)]
67pub struct Callback<'a, T = ()> {
68 callback: Shared<Lock<RawCallback<'a, T>>>,
69}
70
71impl<'a, T> Callback<'a, T> {
72 pub fn new(callback: impl FnMut(&T) + Sendable + 'a) -> Self {
74 Self {
75 callback: Shared::new(Lock::new(callback)),
76 }
77 }
78
79 pub fn downgrade(&self) -> WeakCallback<T> {
84 let callback = unsafe {
89 mem::transmute::<Weak<Lock<RawCallback<'a, T>>>, Weak<Lock<RawCallback<'static, T>>>>(
90 Shared::downgrade(&self.callback),
91 )
92 };
93 WeakCallback { callback }
94 }
95
96 pub fn emit(&self, event: &T) {
98 self.callback.lock_mut()(event);
99 }
100}
101
102impl<'a, T> Default for Callback<'a, T> {
103 fn default() -> Self {
104 Callback::new(|_| {})
105 }
106}
107
108#[derive(Clone)]
112pub struct WeakCallback<T = ()> {
113 callback: Weak<Lock<RawCallback<'static, T>>>,
114}
115
116impl<T> WeakCallback<T> {
117 pub fn new(weak: Weak<Lock<RawCallback<'static, T>>>) -> Self {
119 Self { callback: weak }
120 }
121
122 pub fn upgrade(&self) -> Option<Callback<T>> {
126 Some(Callback {
127 callback: self.callback.upgrade()?,
128 })
129 }
130
131 pub fn as_ptr(&self) -> CallbackPtr<T> {
133 self.callback.as_ptr() as CallbackPtr<T>
134 }
135
136 pub fn emit(&self, event: &T) -> bool {
140 if let Some(callback) = self.upgrade() {
141 callback.emit(event);
142 }
143
144 self.callback.strong_count() > 0
145 }
146}
147
148impl<T> Default for WeakCallback<T> {
149 fn default() -> Self {
150 Callback::default().downgrade()
153 }
154}
155
156pub struct CallbackEmitter<T = ()> {
161 callbacks: Shared<Callbacks<T>>,
162}
163
164impl<T> Default for CallbackEmitter<T> {
165 fn default() -> Self {
166 Self {
167 callbacks: Shared::new(Lock::new(CallbackCollection::new())),
168 }
169 }
170}
171
172impl<T> Clone for CallbackEmitter<T> {
173 fn clone(&self) -> Self {
174 Self {
175 callbacks: self.callbacks.clone(),
176 }
177 }
178}
179
180impl<T> CallbackEmitter<T> {
181 pub fn new() -> Self {
183 Self::default()
184 }
185
186 pub fn len(&self) -> usize {
188 self.callbacks.lock_mut().len()
189 }
190
191 pub fn is_empty(&self) -> bool {
193 self.len() == 0
194 }
195
196 pub fn downgrade(&self) -> WeakCallbackEmitter<T> {
198 WeakCallbackEmitter {
199 callbacks: Shared::downgrade(&self.callbacks),
200 }
201 }
202
203 pub fn subscribe(&self, callback: &Callback<'_, T>) {
209 self.subscribe_weak(callback.downgrade());
210 }
211
212 pub fn subscribe_weak(&self, callback: WeakCallback<T>) {
214 self.callbacks.lock_mut().insert(callback);
215 }
216
217 pub fn unsubscribe(&self, ptr: CallbackPtr<T>) {
219 self.callbacks.lock_mut().remove(ptr);
220 }
221
222 pub fn emit(&self, event: &T) {
224 let callbacks = mem::take(&mut *self.callbacks.lock_mut());
225
226 for callback in callbacks.into_iter() {
227 if let Some(callback) = callback.upgrade() {
228 callback.emit(event);
229 }
230 }
231 }
232}
233
234impl CallbackEmitter {
235 pub fn track(&self) {
237 self.downgrade().track();
238 }
239}
240
241pub struct WeakCallbackEmitter<T = ()> {
245 callbacks: Weak<Callbacks<T>>,
246}
247
248impl<T> WeakCallbackEmitter<T> {
249 pub fn upgrade(&self) -> Option<CallbackEmitter<T>> {
251 Some(CallbackEmitter {
252 callbacks: self.callbacks.upgrade()?,
253 })
254 }
255}
256
257impl<T> Clone for WeakCallbackEmitter<T> {
258 fn clone(&self) -> Self {
259 Self {
260 callbacks: self.callbacks.clone(),
261 }
262 }
263}
264
265impl WeakCallbackEmitter {
266 pub fn track(&self) {
268 super::effect::track_callback(self.clone());
269 }
270}