zng_var/
cow.rs

1use std::{
2    mem,
3    sync::{Arc, Weak},
4};
5
6use parking_lot::RwLock;
7
8use super::{animation::ModifyInfo, *};
9
10enum Data<T: VarValue, S> {
11    Source {
12        source: S,
13        source_handle: VarHandle,
14        hooks: Vec<VarHook>,
15    },
16    Owned {
17        value: T,
18        last_update: VarUpdateId,
19        hooks: Vec<VarHook>,
20        animation: ModifyInfo,
21    },
22}
23
24/// See [`Var::cow`].
25pub struct ArcCowVar<T: VarValue, S>(Arc<RwLock<Data<T, S>>>);
26
27/// Weak reference to a [`ArcCowVar<T>`].
28pub struct WeakCowVar<T: VarValue, S>(Weak<RwLock<Data<T, S>>>);
29
30impl<T: VarValue, S: Var<T>> ArcCowVar<T, S> {
31    pub(super) fn new(source: S) -> Self {
32        let cow = Arc::new(RwLock::new(Data::Source {
33            source,
34            source_handle: VarHandle::dummy(),
35            hooks: vec![],
36        }));
37        {
38            let mut data = cow.write();
39            if let Data::Source { source, source_handle, .. } = &mut *data {
40                let weak_cow = Arc::downgrade(&cow);
41                *source_handle = source.hook_any(Box::new(move |value| {
42                    if let Some(cow) = weak_cow.upgrade() {
43                        match &mut *cow.write() {
44                            Data::Source { hooks, .. } => {
45                                hooks.retain(|h| h.call(value));
46                                true
47                            }
48                            Data::Owned { .. } => false,
49                        }
50                    } else {
51                        false
52                    }
53                }));
54            }
55        }
56        Self(cow)
57    }
58
59    fn modify_impl(&self, modify: impl FnOnce(&mut VarModify<T>) + Send + 'static) -> Result<(), VarIsReadOnlyError> {
60        let me = self.clone();
61        VARS.schedule_update(
62            Box::new(move || {
63                let mut data = me.0.write();
64                let data = &mut *data;
65
66                match data {
67                    Data::Source { source, hooks, .. } => {
68                        let (notify, new_value, update, tags, custom_importance) = source.with(|val| {
69                            let mut vm = VarModify::new(val);
70                            modify(&mut vm);
71                            vm.finish()
72                        });
73                        let value = new_value.unwrap_or_else(|| source.get());
74                        if notify {
75                            let hook_args = AnyVarHookArgs::new(&value, update, &tags);
76                            hooks.retain(|h| h.call(&hook_args));
77                            VARS.wake_app();
78                        }
79                        let mut modify = VARS.current_modify();
80                        if let Some(i) = custom_importance {
81                            modify.importance = i;
82                        }
83                        *data = Data::Owned {
84                            value,
85                            last_update: if notify { VARS.update_id() } else { source.last_update() },
86                            hooks: mem::take(hooks),
87                            animation: modify,
88                        };
89                    }
90                    Data::Owned {
91                        value,
92                        last_update,
93                        hooks,
94                        animation,
95                    } => {
96                        {
97                            let cur_anim = VARS.current_modify();
98                            if cur_anim.importance() < animation.importance() {
99                                return;
100                            }
101                            *animation = cur_anim;
102                        }
103
104                        let (notify, new_value, update, tags, custom_importance) = {
105                            let mut vm = VarModify::new(value);
106                            modify(&mut vm);
107                            vm.finish()
108                        };
109
110                        if let Some(i) = custom_importance {
111                            animation.importance = i;
112                        }
113
114                        if notify {
115                            if let Some(nv) = new_value {
116                                *value = nv;
117                            }
118                            *last_update = VARS.update_id();
119                            let hook_args = AnyVarHookArgs::new(value, update, &tags);
120                            hooks.retain(|h| h.call(&hook_args));
121                            VARS.wake_app();
122                        }
123                    }
124                }
125            }),
126            std::any::type_name::<T>(),
127        );
128        Ok(())
129    }
130
131    impl_infallible_write! {
132        for<T>
133    }
134}
135
136impl<T: VarValue, S> Clone for ArcCowVar<T, S> {
137    fn clone(&self) -> Self {
138        Self(self.0.clone())
139    }
140}
141impl<T: VarValue, S> Clone for WeakCowVar<T, S> {
142    fn clone(&self) -> Self {
143        Self(self.0.clone())
144    }
145}
146
147impl<T: VarValue, S: Var<T>> crate::private::Sealed for ArcCowVar<T, S> {}
148impl<T: VarValue, S: Var<T>> crate::private::Sealed for WeakCowVar<T, S> {}
149
150impl<T: VarValue, S: Var<T>> AnyVar for ArcCowVar<T, S> {
151    fn clone_any(&self) -> BoxedAnyVar {
152        Box::new(self.clone())
153    }
154
155    fn as_any(&self) -> &dyn Any {
156        self
157    }
158
159    fn as_unboxed_any(&self) -> &dyn Any {
160        self
161    }
162
163    fn double_boxed_any(self: Box<Self>) -> Box<dyn Any> {
164        let me: BoxedVar<T> = self;
165        Box::new(me)
166    }
167
168    fn var_type_id(&self) -> TypeId {
169        TypeId::of::<T>()
170    }
171
172    fn get_any(&self) -> Box<dyn AnyVarValue> {
173        Box::new(self.get())
174    }
175
176    fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) {
177        self.with(|v| read(v))
178    }
179
180    fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool {
181        self.with_new(|v| read(v)).is_some()
182    }
183
184    fn set_any(&self, value: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError> {
185        self.modify(var_set_any(value));
186        Ok(())
187    }
188
189    fn last_update(&self) -> VarUpdateId {
190        match &*self.0.read_recursive() {
191            Data::Source { source, .. } => source.last_update(),
192            Data::Owned { last_update, .. } => *last_update,
193        }
194    }
195
196    fn is_contextual(&self) -> bool {
197        match &*self.0.read_recursive() {
198            Data::Source { source, .. } => source.is_contextual(),
199            Data::Owned { .. } => false,
200        }
201    }
202
203    fn capabilities(&self) -> VarCapability {
204        VarCapability::MODIFY
205    }
206
207    fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle {
208        let mut data = self.0.write();
209        match &mut *data {
210            Data::Source { hooks, .. } => {
211                let (hook, weak) = VarHandle::new(pos_modify_action);
212                hooks.push(weak);
213                hook
214            }
215            Data::Owned { hooks, .. } => {
216                let (hook, weak) = VarHandle::new(pos_modify_action);
217                hooks.push(weak);
218                hook
219            }
220        }
221    }
222
223    fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>> {
224        match &*self.0.read_recursive() {
225            Data::Source { source, .. } => source.hook_animation_stop(handler),
226            Data::Owned { animation, .. } => animation.hook_animation_stop(handler),
227        }
228    }
229
230    fn strong_count(&self) -> usize {
231        Arc::strong_count(&self.0)
232    }
233
234    fn weak_count(&self) -> usize {
235        Arc::weak_count(&self.0)
236    }
237
238    fn actual_var_any(&self) -> BoxedAnyVar {
239        self.clone_any()
240    }
241
242    fn downgrade_any(&self) -> BoxedAnyWeakVar {
243        Box::new(WeakCowVar(Arc::downgrade(&self.0)))
244    }
245
246    fn is_animating(&self) -> bool {
247        match &*self.0.read_recursive() {
248            Data::Source { source, .. } => source.is_animating(),
249            Data::Owned { animation, .. } => animation.is_animating(),
250        }
251    }
252
253    fn modify_importance(&self) -> usize {
254        match &*self.0.read_recursive() {
255            Data::Source { source, .. } => source.modify_importance(),
256            Data::Owned { animation, .. } => animation.importance(),
257        }
258    }
259
260    fn var_ptr(&self) -> VarPtr {
261        VarPtr::new_arc(&self.0)
262    }
263
264    fn get_debug(&self) -> crate::Txt {
265        self.with(var_debug)
266    }
267
268    fn update(&self) -> Result<(), VarIsReadOnlyError> {
269        Var::modify(self, var_update)
270    }
271
272    fn map_debug(&self) -> BoxedVar<Txt> {
273        Var::map(self, var_debug).boxed()
274    }
275}
276
277impl<T: VarValue, S: Var<T>> AnyWeakVar for WeakCowVar<T, S> {
278    fn clone_any(&self) -> BoxedAnyWeakVar {
279        Box::new(self.clone())
280    }
281
282    fn strong_count(&self) -> usize {
283        self.0.strong_count()
284    }
285
286    fn weak_count(&self) -> usize {
287        self.0.weak_count()
288    }
289
290    fn upgrade_any(&self) -> Option<BoxedAnyVar> {
291        self.0.upgrade().map(|rc| Box::new(ArcCowVar(rc)) as _)
292    }
293
294    fn as_any(&self) -> &dyn Any {
295        self
296    }
297}
298
299impl<T: VarValue, S: Var<T>> IntoVar<T> for ArcCowVar<T, S> {
300    type Var = Self;
301
302    fn into_var(self) -> Self::Var {
303        self
304    }
305}
306
307impl<T: VarValue, S: Var<T>> Var<T> for ArcCowVar<T, S> {
308    type ReadOnly = types::ReadOnlyVar<T, Self>;
309
310    type ActualVar = Self;
311
312    type Downgrade = WeakCowVar<T, S>;
313
314    type Map<O: VarValue> = ReadOnlyArcVar<O>;
315    type MapBidi<O: VarValue> = ArcVar<O>;
316
317    type FlatMap<O: VarValue, V: Var<O>> = types::ArcFlatMapVar<O, V>;
318
319    type FilterMap<O: VarValue> = ReadOnlyArcVar<O>;
320    type FilterMapBidi<O: VarValue> = ArcVar<O>;
321
322    type MapRef<O: VarValue> = types::MapRef<T, O, Self>;
323    type MapRefBidi<O: VarValue> = types::MapRefBidi<T, O, Self>;
324
325    type Easing = ReadOnlyArcVar<T>;
326
327    fn with<R, F>(&self, read: F) -> R
328    where
329        F: FnOnce(&T) -> R,
330    {
331        match &*self.0.read_recursive() {
332            Data::Source { source, .. } => source.with(read),
333            Data::Owned { value, .. } => read(value),
334        }
335    }
336
337    fn modify<F>(&self, modify: F) -> Result<(), VarIsReadOnlyError>
338    where
339        F: FnOnce(&mut VarModify<T>) + Send + 'static,
340    {
341        self.modify_impl(modify)
342    }
343
344    fn actual_var(self) -> Self {
345        self
346    }
347
348    fn downgrade(&self) -> Self::Downgrade {
349        WeakCowVar(Arc::downgrade(&self.0))
350    }
351
352    fn into_value(self) -> T {
353        match Arc::try_unwrap(self.0) {
354            Ok(state) => match state.into_inner() {
355                Data::Source { source, .. } => source.into_value(),
356                Data::Owned { value, .. } => value,
357            },
358            Err(rc) => Self(rc).get(),
359        }
360    }
361
362    fn read_only(&self) -> Self::ReadOnly {
363        types::ReadOnlyVar::new(self.clone())
364    }
365
366    fn map<O, M>(&self, map: M) -> Self::Map<O>
367    where
368        O: VarValue,
369        M: FnMut(&T) -> O + Send + 'static,
370    {
371        var_map(self, map)
372    }
373
374    fn map_bidi<O, M, B>(&self, map: M, map_back: B) -> Self::MapBidi<O>
375    where
376        O: VarValue,
377        M: FnMut(&T) -> O + Send + 'static,
378        B: FnMut(&O) -> T + Send + 'static,
379    {
380        var_map_bidi(self, map, map_back)
381    }
382
383    fn flat_map<O, V, M>(&self, map: M) -> Self::FlatMap<O, V>
384    where
385        O: VarValue,
386        V: Var<O>,
387        M: FnMut(&T) -> V + Send + 'static,
388    {
389        var_flat_map(self, map)
390    }
391
392    fn filter_map<O, M, I>(&self, map: M, fallback: I) -> Self::FilterMap<O>
393    where
394        O: VarValue,
395        M: FnMut(&T) -> Option<O> + Send + 'static,
396        I: Fn() -> O + Send + Sync + 'static,
397    {
398        var_filter_map(self, map, fallback)
399    }
400
401    fn filter_map_bidi<O, M, B, I>(&self, map: M, map_back: B, fallback: I) -> Self::FilterMapBidi<O>
402    where
403        O: VarValue,
404        M: FnMut(&T) -> Option<O> + Send + 'static,
405        B: FnMut(&O) -> Option<T> + Send + 'static,
406        I: Fn() -> O + Send + Sync + 'static,
407    {
408        var_filter_map_bidi(self, map, map_back, fallback)
409    }
410
411    fn map_ref<O, M>(&self, map: M) -> Self::MapRef<O>
412    where
413        O: VarValue,
414        M: Fn(&T) -> &O + Send + Sync + 'static,
415    {
416        var_map_ref(self, map)
417    }
418
419    fn map_ref_bidi<O, M, B>(&self, map: M, map_mut: B) -> Self::MapRefBidi<O>
420    where
421        O: VarValue,
422        M: Fn(&T) -> &O + Send + Sync + 'static,
423        B: Fn(&mut T) -> &mut O + Send + Sync + 'static,
424    {
425        var_map_ref_bidi(self, map, map_mut)
426    }
427
428    fn easing<F>(&self, duration: Duration, easing: F) -> Self::Easing
429    where
430        T: Transitionable,
431        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
432    {
433        var_easing(self, duration, easing)
434    }
435
436    fn easing_with<F, SE>(&self, duration: Duration, easing: F, sampler: SE) -> Self::Easing
437    where
438        T: Transitionable,
439        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
440        SE: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
441    {
442        var_easing_with(self, duration, easing, sampler)
443    }
444}
445
446impl<T: VarValue, S: Var<T>> WeakVar<T> for WeakCowVar<T, S> {
447    type Upgrade = ArcCowVar<T, S>;
448
449    fn upgrade(&self) -> Option<Self::Upgrade> {
450        self.0.upgrade().map(|rc| ArcCowVar(rc))
451    }
452}