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
use super::Signal; use super::signal::signal_data; use super::context::in_node; use super::node::{HasNode, Node, NodeWithValue, NodeValRef}; use std::cell::RefCell; use std::ops::Deref; use std::rc::{Rc, Weak}; pub struct Memo<A> { data: Rc<NodeWithValue<A>>, } impl<A> Clone for Memo<A> { fn clone(&self) -> Self { Memo { data: self.data.clone(), } } } impl<A> From<Signal<A>> for Memo<A> { fn from(x: Signal<A>) -> Self { Memo { data: signal_data(&x).clone(), } } } impl<A> From<&Signal<A>> for Memo<A> { fn from(x: &Signal<A>) -> Self { Memo { data: signal_data(x).clone(), } } } impl<A:'static> Memo<A> { pub fn new<K:FnMut()->A+'static>(k: K) -> Memo<A> { Memo::new_calmed(k, |_, _| false) } pub fn new_calmed_eq<K:FnMut()->A+'static>(k: K) -> Memo<A> where A: PartialEq { Memo::new_calmed(k, PartialEq::eq) } pub fn new_calmed<K:FnMut()->A+'static,EQ:FnMut(&A,&A)->bool+'static>(mut k: K, mut eq: EQ) -> Memo<A> { let this: Rc<RefCell<Option<Weak<dyn HasNode>>>> = Rc::new(RefCell::new(None)); let node = Node::new(this.clone()); let forward_ref: Rc<RefCell<Option<Weak<NodeWithValue<A>>>>> = Rc::new(RefCell::new(None)); let mut update; { let forward_ref = forward_ref.clone(); update = move || { let node = (*forward_ref).borrow().as_ref().unwrap().upgrade().unwrap(); let weak_node = Rc::downgrade(&node) as Weak<dyn HasNode>; for dependency in &*node.node.dependencies.borrow() { dependency.node().dependents.borrow_mut().retain(|x| !x.ptr_eq(&weak_node)); } node.node.dependencies.borrow_mut().clear(); let r = in_node( node, || { k() } ); r }; } let r = Memo { data: Rc::new(NodeWithValue::new2(node)), }; *(*this).borrow_mut() = Some(Rc::downgrade(&r.data) as Weak<dyn HasNode>); *(*forward_ref).borrow_mut() = Some(Rc::downgrade(&r.data)); *r.data.value.borrow_mut() = Some(update()); let node_with_value = Rc::downgrade(&r.data); *r.data.node.update_op.borrow_mut() = Some(Box::new(move || { let node_with_value = node_with_value.upgrade().unwrap(); let r = update(); let changed = !eq(&*node_with_value.value.borrow().as_ref().unwrap(), &r); if changed { *node_with_value.value.borrow_mut() = Some(r); } changed })); r } pub fn read<'a>(&'a self) -> impl Deref<Target=A> + 'a { NodeValRef::new(&*self.data, self.data.clone()) } }