Skip to content

Commit 1098f6f

Browse files
committed
- Use Weak<Effect> instead of Rc<Effect> to support effect release
- Optimize effect test cases to verify correct effect release
1 parent bf392ed commit 1098f6f

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

cache/src/memo.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ where
1616
{
1717
fn invalidate(&'static self) {
1818
remove_from_cache(self);
19-
self.dependents
20-
.iter()
21-
.for_each(|dependent| dependent.invalidate());
19+
self.dependents.iter().for_each(|d| d.invalidate());
2220
}
2321
}
2422

cache/src/signal.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{
22
cell::{Ref, RefCell},
3-
rc::Rc,
3+
rc::{Rc, Weak},
44
};
55

66
use mvvm::System::ComponentModel::ObservableProperty;
@@ -13,22 +13,26 @@ where
1313
{
1414
prop: ObservableProperty<'static, T>,
1515
dependents: RefCell<Vec<&'static dyn Observable>>,
16-
effects: RefCell<Vec<Rc<Effect>>>,
16+
effects: RefCell<Vec<Weak<Effect>>>,
1717
}
1818

1919
impl<T> Signal<T>
2020
where
2121
T: Eq + Default + 'static,
2222
{
2323
fn invalidate(&self) {
24-
self.dependents
25-
.borrow()
26-
.iter()
27-
.for_each(|dependent| dependent.invalidate());
24+
self.dependents.borrow().iter().for_each(|d| d.invalidate());
2825
}
2926

3027
fn flush_effects(&self) {
31-
self.effects.borrow().iter().for_each(|effect| effect.run());
28+
self.effects.borrow_mut().retain(|w| {
29+
if let Some(e) = w.upgrade() {
30+
e.run();
31+
true
32+
} else {
33+
false
34+
}
35+
});
3236
}
3337

3438
pub fn new(value: Option<T>) -> Rc<Self> {
@@ -65,10 +69,14 @@ where
6569
{
6670
self.dependents.borrow_mut().push(*last);
6771
}
68-
if let Some(effect) = call_stack::current_effect_peak()
69-
&& !self.effects.borrow().iter().any(|e| Rc::ptr_eq(e, &effect))
72+
if let Some(e) = call_stack::current_effect_peak()
73+
&& !self
74+
.effects
75+
.borrow()
76+
.iter()
77+
.any(|w| w.as_ptr() == Rc::as_ptr(&e))
7078
{
71-
self.effects.borrow_mut().push(effect);
79+
self.effects.borrow_mut().push(Rc::downgrade(&e));
7280
}
7381

7482
self.prop.GetValue()

macros/tests/effect.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![allow(static_mut_refs)]
22

3+
use std::rc::Rc;
4+
35
use macros::{effect, memo, signal};
46

57
static mut SOURCE_A_CALLED: i32 = 0;
@@ -65,6 +67,26 @@ pub fn effect_f() {
6567
fn simple_effect_test() {
6668
A_set(0);
6769
effect!(effect_e);
70+
effect!(|| { effect_f() });
71+
72+
unsafe { SOURCE_A_CALLED = 0 };
73+
unsafe { SOURCE_B_CALLED = 0 };
74+
unsafe { DERIVED_C_CALLED = 0 };
75+
unsafe { DERIVED_D_CALLED = 0 };
76+
unsafe { EFFECT_E_CALLED = 0 };
77+
unsafe { EFFECT_F_CALLED = 0 };
78+
79+
A_set(10);
80+
81+
assert_eq!(unsafe { SOURCE_A_CALLED }, 0);
82+
assert_eq!(unsafe { SOURCE_B_CALLED }, 0);
83+
assert_eq!(unsafe { DERIVED_C_CALLED }, 0);
84+
assert_eq!(unsafe { DERIVED_D_CALLED }, 0);
85+
assert_eq!(unsafe { EFFECT_E_CALLED }, 0);
86+
assert_eq!(unsafe { EFFECT_F_CALLED }, 0);
87+
88+
A_set(0);
89+
let _ = Rc::into_raw(effect!(effect_e));
6890

6991
unsafe { SOURCE_A_CALLED = 0 };
7092
unsafe { SOURCE_B_CALLED = 0 };
@@ -83,7 +105,7 @@ fn simple_effect_test() {
83105
assert_eq!(unsafe { EFFECT_F_CALLED }, 0);
84106

85107
A_set(0);
86-
effect!(|| { effect_f() });
108+
let _ = Rc::into_raw(effect!(|| { effect_f() }));
87109

88110
unsafe { SOURCE_A_CALLED = 0 };
89111
unsafe { SOURCE_B_CALLED = 0 };

0 commit comments

Comments
 (0)