fix Dirty Nodes for large NodeIds

This commit is contained in:
Evan Almloff committed 2023-03-24 13:41:00 -05:00
1 parent 6bc9bc6ef9
commit e4cb8c3aa0
2 files changed
+9 -26

No files matched your search

+7 -24
View File
@@ -16,34 +16,20 @@ use crate::{NodeId, NodeMask};
#[derive(Default)] #[derive(Default)]
struct DirtyNodes { struct DirtyNodes {
passes_dirty: Vec<u64>, nodes_dirty: Vec<NodeId>,
} }
impl DirtyNodes { impl DirtyNodes {
pub fn add_node(&mut self, node_id: NodeId) { pub fn add_node(&mut self, node_id: NodeId) {
let node_id = node_id.uindex(); self.nodes_dirty.push(node_id);
let index = node_id / 64;
let bit = node_id % 64;
let encoded = 1 << bit;
if let Some(passes) = self.passes_dirty.get_mut(index) {
*passes |= encoded;
} else {
self.passes_dirty.resize(index + 1, 0);
self.passes_dirty[index] |= encoded;
}
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.passes_dirty.iter().all(|dirty| *dirty == 0) self.nodes_dirty.is_empty()
} }
pub fn pop(&mut self) -> Option<usize> { pub fn pop(&mut self) -> Option<NodeId> {
let index = self.passes_dirty.iter().position(|dirty| *dirty != 0)?; self.nodes_dirty.pop()
let passes = self.passes_dirty[index];
let node_id = passes.trailing_zeros();
let encoded = 1 << node_id;
self.passes_dirty[index] &= !encoded;
Some((index * 64) + node_id as usize)
} }
} }
@@ -76,7 +62,7 @@ impl DirtyNodeStates {
} }
} }
fn pop_front(&self, pass_id: TypeId) -> Option<(u16, usize)> { fn pop_front(&self, pass_id: TypeId) -> Option<(u16, NodeId)> {
let mut values = self.dirty.get(&pass_id)?.write(); let mut values = self.dirty.get(&pass_id)?.write();
let mut value = values.first_entry()?; let mut value = values.first_entry()?;
let height = *value.key(); let height = *value.key();
@@ -89,7 +75,7 @@ impl DirtyNodeStates {
Some((height, id)) Some((height, id))
} }
fn pop_back(&self, pass_id: TypeId) -> Option<(u16, usize)> { fn pop_back(&self, pass_id: TypeId) -> Option<(u16, NodeId)> {
let mut values = self.dirty.get(&pass_id)?.write(); let mut values = self.dirty.get(&pass_id)?.write();
let mut value = values.last_entry()?; let mut value = values.last_entry()?;
let height = *value.key(); let height = *value.key();
@@ -214,7 +200,6 @@ pub fn run_pass<V: FromAnyValue + Send + Sync>(
match pass_direction { match pass_direction {
PassDirection::ParentToChild => { PassDirection::ParentToChild => {
while let Some((height, id)) = dirty.pop_front(type_id) { while let Some((height, id)) = dirty.pop_front(type_id) {
let id = tree.id_at(id).unwrap();
if (update_node)(id, ctx) { if (update_node)(id, ctx) {
nodes_updated.insert(id); nodes_updated.insert(id);
for id in tree.children_ids(id) { for id in tree.children_ids(id) {
@@ -227,7 +212,6 @@ pub fn run_pass<V: FromAnyValue + Send + Sync>(
} }
PassDirection::ChildToParent => { PassDirection::ChildToParent => {
while let Some((height, id)) = dirty.pop_back(type_id) { while let Some((height, id)) = dirty.pop_back(type_id) {
let id = tree.id_at(id).unwrap();
if (update_node)(id, ctx) { if (update_node)(id, ctx) {
nodes_updated.insert(id); nodes_updated.insert(id);
if let Some(id) = tree.parent_id(id) { if let Some(id) = tree.parent_id(id) {
@@ -240,7 +224,6 @@ pub fn run_pass<V: FromAnyValue + Send + Sync>(
} }
PassDirection::AnyOrder => { PassDirection::AnyOrder => {
while let Some((height, id)) = dirty.pop_back(type_id) { while let Some((height, id)) = dirty.pop_back(type_id) {
let id = tree.id_at(id).unwrap();
if (update_node)(id, ctx) { if (update_node)(id, ctx) {
nodes_updated.insert(id); nodes_updated.insert(id);
for dependant in &dependants { for dependant in &dependants {
+2 -2
View File
@@ -49,7 +49,7 @@ pub trait TreeMut: TreeRef {
impl<'a> TreeRef for TreeRefView<'a> { impl<'a> TreeRef for TreeRefView<'a> {
fn parent_id(&self, id: NodeId) -> Option<NodeId> { fn parent_id(&self, id: NodeId) -> Option<NodeId> {
self.get(id).unwrap().parent self.get(id).ok()?.parent
} }
fn children_ids(&self, id: NodeId) -> Vec<NodeId> { fn children_ids(&self, id: NodeId) -> Vec<NodeId> {
@@ -59,7 +59,7 @@ impl<'a> TreeRef for TreeRefView<'a> {
} }
fn height(&self, id: NodeId) -> Option<u16> { fn height(&self, id: NodeId) -> Option<u16> {
Some(self.get(id).unwrap().height) Some(self.get(id).ok()?.height)
} }
fn contains(&self, id: NodeId) -> bool { fn contains(&self, id: NodeId) -> bool {