move height into the tree instead of the realdom

This commit is contained in:
Evan Almloff committed 2022-11-25 22:22:56 -06:00
1 parent 7d3ac26fce
commit 8af59d6969
4 files changed
+110 -23

No files matched your search

-3
View File
@@ -19,8 +19,6 @@ pub struct NodeData {
pub element_id: Option<ElementId>, pub element_id: Option<ElementId>,
/// Additional inforation specific to the node type /// Additional inforation specific to the node type
pub node_type: NodeType, pub node_type: NodeType,
/// The number of parents before the root node. The root node has height 1.
pub height: u16,
} }
/// A type of node with data specific to the node type. The types are a subset of the [VNode] types. /// A type of node with data specific to the node type. The types are a subset of the [VNode] types.
@@ -45,7 +43,6 @@ impl<S: State> Node<S> {
node_data: NodeData { node_data: NodeData {
element_id: None, element_id: None,
node_type, node_type,
height: 0,
node_id: NodeId(0), node_id: NodeId(0),
}, },
} }
+50 -3
View File
@@ -96,6 +96,22 @@ impl DirtyNodeStates {
} }
} }
fn get(&self, pass_id: PassId, node_id: NodeId) -> bool {
let pass_id = pass_id.0;
let index = pass_id / 64;
let bit = pass_id % 64;
let encoded = 1 << bit;
if let Some(dirty) = self.dirty.get(&node_id) {
if let Some(atomic) = dirty.get(index as usize) {
atomic.load(Ordering::SeqCst) & encoded != 0
} else {
false
}
} else {
false
}
}
fn all_dirty(&self, pass_id: PassId) -> impl Iterator<Item = NodeId> + '_ { fn all_dirty(&self, pass_id: PassId) -> impl Iterator<Item = NodeId> + '_ {
let pass_id = pass_id.0; let pass_id = pass_id.0;
let index = pass_id / 64; let index = pass_id / 64;
@@ -160,7 +176,23 @@ fn get_pass<T, Tr: TreeView<T>>(
} }
} }
} }
_ => { AnyPass::Downward(pass) => {
let mut sorted: Vec<_> = dirty_nodes.all_dirty(pass_id).collect();
sorted.sort_unstable_by_key(|id| shared_view.height(*id));
println!(
"Task: {:?} {:?}",
pass_id,
sorted
.iter()
.map(|id| (id, shared_view.height(*id)))
.collect::<Vec<_>>()
);
for node in sorted.into_iter() {
global.push(node);
}
current_pass.replace(AnyPass::Downward(pass));
}
AnyPass::Node(pass) => {
for node in dirty_nodes.all_dirty(pass_id) { for node in dirty_nodes.all_dirty(pass_id) {
global.push(node); global.push(node);
} }
@@ -169,7 +201,7 @@ fn get_pass<T, Tr: TreeView<T>>(
pass_id, pass_id,
dirty_nodes.all_dirty(pass_id).collect::<Vec<_>>() dirty_nodes.all_dirty(pass_id).collect::<Vec<_>>()
); );
current_pass.replace(pass); current_pass.replace(AnyPass::Node(pass));
} }
} }
return; return;
@@ -224,6 +256,7 @@ pub fn resolve_passes<T>(
loop { loop {
let read = current_pass.read(); let read = current_pass.read();
if let Some(current_pass) = &*read { if let Some(current_pass) = &*read {
let current_pass_id = current_pass.pass_id();
match current_pass { match current_pass {
AnyPass::Upward(_) => { AnyPass::Upward(_) => {
todo!("Upward passes are single threaded") todo!("Upward passes are single threaded")
@@ -248,7 +281,9 @@ pub fn resolve_passes<T>(
for dependant in pass.dependants() { for dependant in pass.dependants() {
dirty_nodes.insert(*dependant, *id); dirty_nodes.insert(*dependant, *id);
} }
w.push(*id); if !dirty_nodes.get(current_pass_id, *id) {
w.push(*id);
}
} }
} }
} }
@@ -333,6 +368,7 @@ fn node_pass() {
tree.add_child(parent, child2); tree.add_child(parent, child2);
let grandchild2 = tree.create_node(4); let grandchild2 = tree.create_node(4);
tree.add_child(child2, grandchild2); tree.add_child(child2, grandchild2);
println!("{:#?}", tree);
struct AddPass; struct AddPass;
@@ -484,14 +520,19 @@ fn down_pass() {
#[test] #[test]
fn dependant_down_pass() { fn dependant_down_pass() {
use crate::tree::{Tree, TreeLike}; use crate::tree::{Tree, TreeLike};
// 0
let mut tree = Tree::new(1); let mut tree = Tree::new(1);
let parent = tree.root(); let parent = tree.root();
// 1
let child1 = tree.create_node(1); let child1 = tree.create_node(1);
tree.add_child(parent, child1); tree.add_child(parent, child1);
// 2
let grandchild1 = tree.create_node(1); let grandchild1 = tree.create_node(1);
tree.add_child(child1, grandchild1); tree.add_child(child1, grandchild1);
// 3
let child2 = tree.create_node(1); let child2 = tree.create_node(1);
tree.add_child(parent, child2); tree.add_child(parent, child2);
// 4
let grandchild2 = tree.create_node(1); let grandchild2 = tree.create_node(1);
tree.add_child(child2, grandchild2); tree.add_child(child2, grandchild2);
@@ -512,7 +553,10 @@ fn dependant_down_pass() {
fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> bool { fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> bool {
if let Some(parent) = parent { if let Some(parent) = parent {
println!("AddPass: {} -> {}", node, *node + *parent);
*node += *parent; *node += *parent;
} else {
println!("AddPass: {}", node);
} }
true true
} }
@@ -535,7 +579,10 @@ fn dependant_down_pass() {
fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> bool { fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> bool {
if let Some(parent) = parent { if let Some(parent) = parent {
println!("SubtractPass: {} -> {}", node, *node - *parent);
*node -= *parent; *node -= *parent;
} else {
println!("SubtractPass: {}", node);
} }
true true
} }
+5 -16
View File
@@ -93,21 +93,6 @@ impl<S: State> RealDom<S> {
fn add_child(&mut self, node_id: RealNodeId, child_id: RealNodeId) { fn add_child(&mut self, node_id: RealNodeId, child_id: RealNodeId) {
self.tree.add_child(node_id, child_id); self.tree.add_child(node_id, child_id);
self.resolve_height(child_id);
}
fn resolve_height(&mut self, node_id: RealNodeId) {
if let Some((node, Some(parent))) = self.tree.node_parent_mut(node_id) {
let height = parent.node_data.height;
node.node_data.height = height + 1;
unsafe {
let self_mut = self as *mut Self;
// Safety: No node will have itself as a child
for child in self.tree.children_ids(node_id).unwrap() {
(*self_mut).resolve_height(*child);
}
}
}
} }
/// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state. /// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
@@ -382,7 +367,11 @@ impl<S: State> RealDom<S> {
pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node<S>> { pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node<S>> {
if let Some(nodes) = self.nodes_listening.get(event) { if let Some(nodes) = self.nodes_listening.get(event) {
let mut listening: Vec<_> = nodes.iter().map(|id| &self[*id]).collect(); let mut listening: Vec<_> = nodes.iter().map(|id| &self[*id]).collect();
listening.sort_by(|n1, n2| (n1.node_data.height).cmp(&n2.node_data.height).reverse()); listening.sort_by(|n1, n2| {
(self.tree.height(n1.node_data.node_id))
.cmp(&self.tree.height(n2.node_data.node_id))
.reverse()
});
listening listening
} else { } else {
Vec::new() Vec::new()
+55 -1
View File
@@ -15,6 +15,7 @@ pub struct Node<T> {
value: T, value: T,
parent: Option<NodeId>, parent: Option<NodeId>,
children: Vec<NodeId>, children: Vec<NodeId>,
height: u16,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -46,6 +47,18 @@ impl<T> Tree<T> {
self.remove_recursive(child); self.remove_recursive(child);
} }
} }
fn set_height(&mut self, node: NodeId, height: u16) {
let self_mut = self as *mut Self;
let node = self.nodes.get_mut(node.0).unwrap();
node.height = height;
unsafe {
// Safety: No node has itself as a child
for child in &node.children {
(*self_mut).set_height(*child, height + 1);
}
}
}
} }
pub trait TreeView<T>: Sized { pub trait TreeView<T>: Sized {
@@ -106,6 +119,8 @@ pub trait TreeView<T>: Sized {
fn parent_id(&self, id: NodeId) -> Option<NodeId>; fn parent_id(&self, id: NodeId) -> Option<NodeId>;
fn height(&self, id: NodeId) -> Option<u16>;
fn map<T2, F: Fn(&T) -> &T2, FMut: Fn(&mut T) -> &mut T2>( fn map<T2, F: Fn(&T) -> &T2, FMut: Fn(&mut T) -> &mut T2>(
&mut self, &mut self,
map: F, map: F,
@@ -306,6 +321,10 @@ impl<T> TreeView<T> for Tree<T> {
self.nodes.get(id.0).and_then(|node| node.parent) self.nodes.get(id.0).and_then(|node| node.parent)
} }
fn height(&self, id: NodeId) -> Option<u16> {
self.nodes.get(id.0).map(|n| n.height)
}
fn get_unchecked(&self, id: NodeId) -> &T { fn get_unchecked(&self, id: NodeId) -> &T {
unsafe { &self.nodes.get_unchecked(id.0).value } unsafe { &self.nodes.get_unchecked(id.0).value }
} }
@@ -326,6 +345,7 @@ impl<T> TreeLike<T> for Tree<T> {
value: root, value: root,
parent: None, parent: None,
children: Vec::new(), children: Vec::new(),
height: 0,
})); }));
Self { nodes, root } Self { nodes, root }
} }
@@ -335,12 +355,16 @@ impl<T> TreeLike<T> for Tree<T> {
value, value,
parent: None, parent: None,
children: Vec::new(), children: Vec::new(),
height: 0,
})) }))
} }
fn add_child(&mut self, parent: NodeId, new: NodeId) { fn add_child(&mut self, parent: NodeId, new: NodeId) {
self.nodes.get_mut(parent.0).unwrap().children.push(new);
self.nodes.get_mut(new.0).unwrap().parent = Some(parent); self.nodes.get_mut(new.0).unwrap().parent = Some(parent);
let parent = self.nodes.get_mut(parent.0).unwrap();
parent.children.push(new);
let height = parent.height + 1;
self.set_height(new, height);
} }
fn remove(&mut self, id: NodeId) -> Option<T> { fn remove(&mut self, id: NodeId) -> Option<T> {
@@ -372,6 +396,8 @@ impl<T> TreeLike<T> for Tree<T> {
*id = new_id; *id = new_id;
} }
} }
let height = parent.height + 1;
self.set_height(new_id, height);
} }
} }
@@ -386,6 +412,8 @@ impl<T> TreeLike<T> for Tree<T> {
.position(|child| child == &id) .position(|child| child == &id)
.unwrap(); .unwrap();
parent.children.insert(index, new); parent.children.insert(index, new);
let height = parent.height + 1;
self.set_height(new, height);
} }
fn insert_after(&mut self, id: NodeId, new: NodeId) { fn insert_after(&mut self, id: NodeId, new: NodeId) {
@@ -399,6 +427,8 @@ impl<T> TreeLike<T> for Tree<T> {
.position(|child| child == &id) .position(|child| child == &id)
.unwrap(); .unwrap();
parent.children.insert(index + 1, new); parent.children.insert(index + 1, new);
let height = parent.height + 1;
self.set_height(new, height);
} }
} }
@@ -498,6 +528,10 @@ where
self.tree.parent_id(id) self.tree.parent_id(id)
} }
fn height(&self, id: NodeId) -> Option<u16> {
self.tree.height(id)
}
fn get_unchecked(&self, id: NodeId) -> &T2 { fn get_unchecked(&self, id: NodeId) -> &T2 {
(self.map)(self.tree.get_unchecked(id)) (self.map)(self.tree.get_unchecked(id))
} }
@@ -630,6 +664,10 @@ impl<'a, T, Tr: TreeView<T>> TreeView<T> for SharedView<'a, T, Tr> {
self.with_node(id, |t| t.parent_id(id)) self.with_node(id, |t| t.parent_id(id))
} }
fn height(&self, id: NodeId) -> Option<u16> {
unsafe { (*self.tree.get()).height(id) }
}
fn size(&self) -> usize { fn size(&self) -> usize {
unsafe { (*self.tree.get()).size() } unsafe { (*self.tree.get()).size() }
} }
@@ -644,6 +682,8 @@ fn creation() {
println!("Tree: {:#?}", tree); println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 2); assert_eq!(tree.size(), 2);
assert_eq!(tree.height(parent), Some(0));
assert_eq!(tree.height(child), Some(1));
assert_eq!(*tree.get(parent).unwrap(), 1); assert_eq!(*tree.get(parent).unwrap(), 1);
assert_eq!(*tree.get(child).unwrap(), 0); assert_eq!(*tree.get(child).unwrap(), 0);
assert_eq!(tree.parent_id(parent), None); assert_eq!(tree.parent_id(parent), None);
@@ -664,6 +704,10 @@ fn insertion() {
println!("Tree: {:#?}", tree); println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 4); assert_eq!(tree.size(), 4);
assert_eq!(tree.height(parent), Some(0));
assert_eq!(tree.height(child), Some(1));
assert_eq!(tree.height(before), Some(1));
assert_eq!(tree.height(after), Some(1));
assert_eq!(*tree.get(parent).unwrap(), 0); assert_eq!(*tree.get(parent).unwrap(), 0);
assert_eq!(*tree.get(before).unwrap(), 1); assert_eq!(*tree.get(before).unwrap(), 1);
assert_eq!(*tree.get(child).unwrap(), 2); assert_eq!(*tree.get(child).unwrap(), 2);
@@ -687,6 +731,10 @@ fn deletion() {
println!("Tree: {:#?}", tree); println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 4); assert_eq!(tree.size(), 4);
assert_eq!(tree.height(parent), Some(0));
assert_eq!(tree.height(child), Some(1));
assert_eq!(tree.height(before), Some(1));
assert_eq!(tree.height(after), Some(1));
assert_eq!(*tree.get(parent).unwrap(), 0); assert_eq!(*tree.get(parent).unwrap(), 0);
assert_eq!(*tree.get(before).unwrap(), 1); assert_eq!(*tree.get(before).unwrap(), 1);
assert_eq!(*tree.get(child).unwrap(), 2); assert_eq!(*tree.get(child).unwrap(), 2);
@@ -700,6 +748,9 @@ fn deletion() {
println!("Tree: {:#?}", tree); println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 3); assert_eq!(tree.size(), 3);
assert_eq!(tree.height(parent), Some(0));
assert_eq!(tree.height(before), Some(1));
assert_eq!(tree.height(after), Some(1));
assert_eq!(*tree.get(parent).unwrap(), 0); assert_eq!(*tree.get(parent).unwrap(), 0);
assert_eq!(*tree.get(before).unwrap(), 1); assert_eq!(*tree.get(before).unwrap(), 1);
assert_eq!(tree.get(child), None); assert_eq!(tree.get(child), None);
@@ -712,6 +763,8 @@ fn deletion() {
println!("Tree: {:#?}", tree); println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 2); assert_eq!(tree.size(), 2);
assert_eq!(tree.height(parent), Some(0));
assert_eq!(tree.height(after), Some(1));
assert_eq!(*tree.get(parent).unwrap(), 0); assert_eq!(*tree.get(parent).unwrap(), 0);
assert_eq!(tree.get(before), None); assert_eq!(tree.get(before), None);
assert_eq!(*tree.get(after).unwrap(), 3); assert_eq!(*tree.get(after).unwrap(), 3);
@@ -722,6 +775,7 @@ fn deletion() {
println!("Tree: {:#?}", tree); println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 1); assert_eq!(tree.size(), 1);
assert_eq!(tree.height(parent), Some(0));
assert_eq!(*tree.get(parent).unwrap(), 0); assert_eq!(*tree.get(parent).unwrap(), 0);
assert_eq!(tree.get(after), None); assert_eq!(tree.get(after), None);
assert_eq!(tree.children_ids(parent).unwrap(), &[]); assert_eq!(tree.children_ids(parent).unwrap(), &[]);