work on intigrating state with passes

This commit is contained in:
Evan Almloff committed 2022-11-26 15:25:02 -06:00
1 parent 4812b5124a
commit d78af904e6
5 files changed
+137 -108

No files matched your search

+7 -1
View File
@@ -1,3 +1,6 @@
use std::hash::BuildHasherDefault;
use rustc_hash::FxHasher;
use tree::NodeId; use tree::NodeId;
pub mod layout_attributes; pub mod layout_attributes;
@@ -10,7 +13,10 @@ pub mod tree;
pub mod utils; pub mod utils;
/// A id for a node that lives in the real dom. /// A id for a node that lives in the real dom.
type RealNodeId = NodeId; pub type RealNodeId = NodeId;
pub(crate) type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
pub(crate) type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>;
pub(crate) type SendAnyMap = anymap::Map<dyn anymap::any::Any + Send + Sync + 'static>;
/// Used in derived state macros /// Used in derived state macros
#[derive(Eq, PartialEq)] #[derive(Eq, PartialEq)]
+86 -67
View File
@@ -1,13 +1,11 @@
use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; use crate::tree::{NodeId, TreeView};
use crate::{FxDashMap, FxDashSet, SendAnyMap};
use rustc_hash::{FxHashMap, FxHashSet};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::hash::BuildHasherDefault;
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign}; use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc; use std::sync::Arc;
use crate::tree::{NodeId, TreeView};
#[derive(Debug, Clone, PartialEq, Eq, Default)] #[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct DirtyNodes { pub struct DirtyNodes {
map: BTreeMap<u16, FxHashSet<NodeId>>, map: BTreeMap<u16, FxHashSet<NodeId>>,
@@ -57,8 +55,6 @@ fn dirty_nodes() {
assert_eq!(dirty_nodes.pop_front(), Some(NodeId(3))); assert_eq!(dirty_nodes.pop_front(), Some(NodeId(3)));
} }
type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
#[derive(Default)] #[derive(Default)]
pub struct DirtyNodeStates { pub struct DirtyNodeStates {
dirty: FxDashMap<NodeId, Vec<AtomicU64>>, dirty: FxDashMap<NodeId, Vec<AtomicU64>>,
@@ -167,7 +163,12 @@ pub trait Pass {
} }
pub trait UpwardPass<T>: Pass { pub trait UpwardPass<T>: Pass {
fn pass<'a>(&self, node: &mut T, children: &mut dyn Iterator<Item = &'a mut T>) -> PassReturn; fn pass<'a>(
&self,
node: &mut T,
children: &mut dyn Iterator<Item = &'a mut T>,
ctx: &SendAnyMap,
) -> PassReturn;
} }
fn resolve_upward_pass<T, P: UpwardPass<T> + ?Sized>( fn resolve_upward_pass<T, P: UpwardPass<T> + ?Sized>(
@@ -175,12 +176,15 @@ fn resolve_upward_pass<T, P: UpwardPass<T> + ?Sized>(
pass: &P, pass: &P,
mut dirty: DirtyNodes, mut dirty: DirtyNodes,
dirty_states: &DirtyNodeStates, dirty_states: &DirtyNodeStates,
nodes_updated: &FxDashSet<NodeId>,
ctx: &SendAnyMap,
) { ) {
while let Some(id) = dirty.pop_back() { while let Some(id) = dirty.pop_back() {
let (node, mut children) = tree.parent_child_mut(id).unwrap(); let (node, mut children) = tree.parent_child_mut(id).unwrap();
let result = pass.pass(node, &mut children); let result = pass.pass(node, &mut children, ctx);
drop(children); drop(children);
if result.progress || result.mark_dirty { if result.progress || result.mark_dirty {
nodes_updated.insert(id);
if let Some(id) = tree.parent_id(id) { if let Some(id) = tree.parent_id(id) {
if result.mark_dirty { if result.mark_dirty {
for dependant in pass.dependants() { for dependant in pass.dependants() {
@@ -197,7 +201,7 @@ fn resolve_upward_pass<T, P: UpwardPass<T> + ?Sized>(
} }
pub trait DownwardPass<T>: Pass { pub trait DownwardPass<T>: Pass {
fn pass(&self, node: &mut T, parent: Option<&mut T>) -> PassReturn; fn pass(&self, node: &mut T, parent: Option<&mut T>, ctx: &SendAnyMap) -> PassReturn;
} }
fn resolve_downward_pass<T, P: DownwardPass<T> + ?Sized>( fn resolve_downward_pass<T, P: DownwardPass<T> + ?Sized>(
@@ -205,11 +209,14 @@ fn resolve_downward_pass<T, P: DownwardPass<T> + ?Sized>(
pass: &P, pass: &P,
mut dirty: DirtyNodes, mut dirty: DirtyNodes,
dirty_states: &DirtyNodeStates, dirty_states: &DirtyNodeStates,
nodes_updated: &FxDashSet<NodeId>,
ctx: &SendAnyMap,
) { ) {
while let Some(id) = dirty.pop_front() { while let Some(id) = dirty.pop_front() {
let (node, parent) = tree.node_parent_mut(id).unwrap(); let (node, parent) = tree.node_parent_mut(id).unwrap();
let result = pass.pass(node, parent); let result = pass.pass(node, parent, ctx);
if result.mark_dirty || result.progress { if result.mark_dirty || result.progress {
nodes_updated.insert(id);
for id in tree.children_ids(id).unwrap() { for id in tree.children_ids(id).unwrap() {
if result.mark_dirty { if result.mark_dirty {
for dependant in pass.dependants() { for dependant in pass.dependants() {
@@ -226,7 +233,7 @@ fn resolve_downward_pass<T, P: DownwardPass<T> + ?Sized>(
} }
pub trait NodePass<T>: Pass { pub trait NodePass<T>: Pass {
fn pass(&self, node: &mut T) -> bool; fn pass(&self, node: &mut T, ctx: &SendAnyMap) -> bool;
} }
fn resolve_node_pass<T, P: NodePass<T> + ?Sized>( fn resolve_node_pass<T, P: NodePass<T> + ?Sized>(
@@ -234,10 +241,13 @@ fn resolve_node_pass<T, P: NodePass<T> + ?Sized>(
pass: &P, pass: &P,
mut dirty: DirtyNodes, mut dirty: DirtyNodes,
dirty_states: &DirtyNodeStates, dirty_states: &DirtyNodeStates,
nodes_updated: &FxDashSet<NodeId>,
ctx: &SendAnyMap,
) { ) {
while let Some(id) = dirty.pop_back() { while let Some(id) = dirty.pop_back() {
let node = tree.get_mut(id).unwrap(); let node = tree.get_mut(id).unwrap();
if pass.pass(node) { if pass.pass(node, ctx) {
nodes_updated.insert(id);
for dependant in pass.dependants() { for dependant in pass.dependants() {
dirty_states.insert(*dependant, id); dirty_states.insert(*dependant, id);
} }
@@ -245,14 +255,14 @@ fn resolve_node_pass<T, P: NodePass<T> + ?Sized>(
} }
} }
pub enum AnyPass<T> { pub enum AnyPass<T: 'static> {
Upward(Box<dyn UpwardPass<T> + Send + Sync>), Upward(&'static (dyn UpwardPass<T> + Send + Sync + 'static)),
Downward(Box<dyn DownwardPass<T> + Send + Sync>), Downward(&'static (dyn DownwardPass<T> + Send + Sync + 'static)),
Node(Box<dyn NodePass<T> + Send + Sync>), Node(&'static (dyn NodePass<T> + Send + Sync + 'static)),
} }
impl<T> AnyPass<T> { impl<T> AnyPass<T> {
fn pass_id(&self) -> PassId { pub fn pass_id(&self) -> PassId {
match self { match self {
Self::Upward(pass) => pass.pass_id(), Self::Upward(pass) => pass.pass_id(),
Self::Downward(pass) => pass.pass_id(), Self::Downward(pass) => pass.pass_id(),
@@ -260,7 +270,7 @@ impl<T> AnyPass<T> {
} }
} }
fn dependancies(&self) -> &'static [PassId] { pub fn dependancies(&self) -> &'static [PassId] {
match self { match self {
Self::Upward(pass) => pass.dependancies(), Self::Upward(pass) => pass.dependancies(),
Self::Downward(pass) => pass.dependancies(), Self::Downward(pass) => pass.dependancies(),
@@ -281,11 +291,19 @@ impl<T> AnyPass<T> {
tree: &mut impl TreeView<T>, tree: &mut impl TreeView<T>,
dirty: DirtyNodes, dirty: DirtyNodes,
dirty_states: &DirtyNodeStates, dirty_states: &DirtyNodeStates,
nodes_updated: &FxDashSet<NodeId>,
ctx: &SendAnyMap,
) { ) {
match self { match self {
Self::Downward(pass) => resolve_downward_pass(tree, pass.as_ref(), dirty, dirty_states), Self::Downward(pass) => {
Self::Upward(pass) => resolve_upward_pass(tree, pass.as_ref(), dirty, dirty_states), resolve_downward_pass(tree, *pass, dirty, dirty_states, nodes_updated, ctx)
Self::Node(pass) => resolve_node_pass(tree, pass.as_ref(), dirty, dirty_states), }
Self::Upward(pass) => {
resolve_upward_pass(tree, *pass, dirty, dirty_states, nodes_updated, ctx)
}
Self::Node(pass) => {
resolve_node_pass(tree, *pass, dirty, dirty_states, nodes_updated, ctx)
}
} }
} }
} }
@@ -297,11 +315,14 @@ unsafe impl<T> Sync for RawPointer<T> {}
pub fn resolve_passes<T, Tr: TreeView<T>>( pub fn resolve_passes<T, Tr: TreeView<T>>(
tree: &mut Tr, tree: &mut Tr,
dirty_nodes: DirtyNodeStates, dirty_nodes: DirtyNodeStates,
mut passes: Vec<AnyPass<T>>, mut passes: Vec<&AnyPass<T>>,
) { ctx: SendAnyMap,
) -> FxDashSet<NodeId> {
let dirty_states = Arc::new(dirty_nodes); let dirty_states = Arc::new(dirty_nodes);
let mut resolved_passes: FxHashSet<PassId> = FxHashSet::default(); let mut resolved_passes: FxHashSet<PassId> = FxHashSet::default();
let mut resolving = Vec::new(); let mut resolving = Vec::new();
let nodes_updated = Arc::new(FxDashSet::default());
let ctx = Arc::new(ctx);
while !passes.is_empty() { while !passes.is_empty() {
let mut currently_borrowed = MemberMask::default(); let mut currently_borrowed = MemberMask::default();
std::thread::scope(|s| { std::thread::scope(|s| {
@@ -322,13 +343,16 @@ pub fn resolve_passes<T, Tr: TreeView<T>>(
let tree_mut = tree as *mut _; let tree_mut = tree as *mut _;
let raw_ptr = RawPointer(tree_mut); let raw_ptr = RawPointer(tree_mut);
let dirty_states = dirty_states.clone(); let dirty_states = dirty_states.clone();
let nodes_updated = nodes_updated.clone();
let ctx = ctx.clone();
s.spawn(move || unsafe { s.spawn(move || unsafe {
// let tree_mut: &mut Tr = &mut *raw_ptr.0; // let tree_mut: &mut Tr = &mut *raw_ptr.0;
let raw = raw_ptr; let raw = raw_ptr;
// this is safe because the member_mask acts as a per-member mutex and we have verified that the pass does not overlap with any other pass
let tree_mut: &mut Tr = &mut *raw.0; let tree_mut: &mut Tr = &mut *raw.0;
let mut dirty = DirtyNodes::default(); let mut dirty = DirtyNodes::default();
dirty_states.all_dirty(pass_id, &mut dirty, tree_mut); dirty_states.all_dirty(pass_id, &mut dirty, tree_mut);
pass.resolve(tree_mut, dirty, &dirty_states); pass.resolve(tree_mut, dirty, &dirty_states, &nodes_updated, &ctx);
}); });
} else { } else {
i += 1; i += 1;
@@ -339,14 +363,13 @@ pub fn resolve_passes<T, Tr: TreeView<T>>(
resolved_passes.extend(resolving.iter().copied()); resolved_passes.extend(resolving.iter().copied());
resolving.clear() resolving.clear()
} }
std::sync::Arc::try_unwrap(nodes_updated).unwrap()
} }
#[test] #[test]
fn node_pass() { fn node_pass() {
use crate::tree::{Tree, TreeLike}; use crate::tree::{Tree, TreeLike};
let mut tree = Tree::new(0); let mut tree = Tree::new(0);
let parent = tree.root();
println!("{:#?}", tree);
struct AddPass; struct AddPass;
impl Pass for AddPass { impl Pass for AddPass {
@@ -368,16 +391,17 @@ fn node_pass() {
} }
impl NodePass<i32> for AddPass { impl NodePass<i32> for AddPass {
fn pass(&self, node: &mut i32) -> bool { fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
*node += 1; *node += 1;
true true
} }
} }
let passes = vec![AnyPass::Node(Box::new(AddPass))]; let add_pass = AnyPass::Node(&AddPass);
let passes = vec![&add_pass];
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
dirty_nodes.insert(PassId(0), tree.root()); dirty_nodes.insert(PassId(0), tree.root());
resolve_passes(&mut tree, dirty_nodes, passes); resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
assert_eq!(tree.get(tree.root()).unwrap(), &1); assert_eq!(tree.get(tree.root()).unwrap(), &1);
} }
@@ -407,8 +431,7 @@ fn dependant_node_pass() {
} }
impl NodePass<i32> for AddPass { impl NodePass<i32> for AddPass {
fn pass(&self, node: &mut i32) -> bool { fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
println!("AddPass: {}", node);
*node += 1; *node += 1;
true true
} }
@@ -434,20 +457,18 @@ fn dependant_node_pass() {
} }
} }
impl NodePass<i32> for SubtractPass { impl NodePass<i32> for SubtractPass {
fn pass(&self, node: &mut i32) -> bool { fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
println!("SubtractPass: {}", node);
*node -= 1; *node -= 1;
true true
} }
} }
let passes = vec![ let add_pass = AnyPass::Node(&AddPass);
AnyPass::Node(Box::new(AddPass)), let subtract_pass = AnyPass::Node(&SubtractPass);
AnyPass::Node(Box::new(SubtractPass)), let passes = vec![&add_pass, &subtract_pass];
];
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
dirty_nodes.insert(PassId(1), tree.root()); dirty_nodes.insert(PassId(1), tree.root());
resolve_passes(&mut tree, dirty_nodes, passes); resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
assert_eq!(*tree.get(tree.root()).unwrap(), 0); assert_eq!(*tree.get(tree.root()).unwrap(), 0);
} }
@@ -477,7 +498,7 @@ fn independant_node_pass() {
} }
impl NodePass<(i32, i32)> for AddPass1 { impl NodePass<(i32, i32)> for AddPass1 {
fn pass(&self, node: &mut (i32, i32)) -> bool { fn pass(&self, node: &mut (i32, i32), _: &SendAnyMap) -> bool {
node.0 += 1; node.0 += 1;
true true
} }
@@ -503,20 +524,19 @@ fn independant_node_pass() {
} }
impl NodePass<(i32, i32)> for AddPass2 { impl NodePass<(i32, i32)> for AddPass2 {
fn pass(&self, node: &mut (i32, i32)) -> bool { fn pass(&self, node: &mut (i32, i32), _: &SendAnyMap) -> bool {
node.1 += 1; node.1 += 1;
true true
} }
} }
let passes = vec![ let add_pass1 = AnyPass::Node(&AddPass1);
AnyPass::Node(Box::new(AddPass1)), let add_pass2 = AnyPass::Node(&AddPass2);
AnyPass::Node(Box::new(AddPass2)), let passes = vec![&add_pass1, &add_pass2];
];
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
dirty_nodes.insert(PassId(0), tree.root()); dirty_nodes.insert(PassId(0), tree.root());
dirty_nodes.insert(PassId(1), tree.root()); dirty_nodes.insert(PassId(1), tree.root());
resolve_passes(&mut tree, dirty_nodes, passes); resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
assert_eq!(tree.get(tree.root()).unwrap(), &(1, 1)); assert_eq!(tree.get(tree.root()).unwrap(), &(1, 1));
} }
@@ -555,7 +575,7 @@ fn down_pass() {
} }
} }
impl DownwardPass<i32> for AddPass { impl DownwardPass<i32> for AddPass {
fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> PassReturn { fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
if let Some(parent) = parent { if let Some(parent) = parent {
*node += *parent; *node += *parent;
} }
@@ -566,10 +586,11 @@ fn down_pass() {
} }
} }
let passes = vec![AnyPass::Downward(Box::new(AddPass))]; let add_pass = AnyPass::Downward(&AddPass);
let passes = vec![&add_pass];
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
dirty_nodes.insert(PassId(0), tree.root()); dirty_nodes.insert(PassId(0), tree.root());
resolve_passes(&mut tree, dirty_nodes, passes); resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
assert_eq!(tree.get(tree.root()).unwrap(), &1); assert_eq!(tree.get(tree.root()).unwrap(), &1);
assert_eq!(tree.get(child1).unwrap(), &2); assert_eq!(tree.get(child1).unwrap(), &2);
@@ -616,12 +637,10 @@ fn dependant_down_pass() {
} }
} }
impl DownwardPass<i32> for AddPass { impl DownwardPass<i32> for AddPass {
fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> PassReturn { fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
if let Some(parent) = parent { if let Some(parent) = parent {
println!("AddPass: {} -> {}", node, *node + *parent);
*node += *parent; *node += *parent;
} else { } else {
println!("AddPass: {}", node);
} }
PassReturn { PassReturn {
progress: true, progress: true,
@@ -649,12 +668,10 @@ fn dependant_down_pass() {
} }
} }
impl DownwardPass<i32> for SubtractPass { impl DownwardPass<i32> for SubtractPass {
fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> PassReturn { fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
if let Some(parent) = parent { if let Some(parent) = parent {
println!("SubtractPass: {} -> {}", node, *node - *parent);
*node -= *parent; *node -= *parent;
} else { } else {
println!("SubtractPass: {}", node);
} }
PassReturn { PassReturn {
progress: true, progress: true,
@@ -663,13 +680,12 @@ fn dependant_down_pass() {
} }
} }
let passes = vec![ let add_pass = AnyPass::Downward(&AddPass);
AnyPass::Downward(Box::new(AddPass)), let subtract_pass = AnyPass::Downward(&SubtractPass);
AnyPass::Downward(Box::new(SubtractPass)), let passes = vec![&add_pass, &subtract_pass];
];
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
dirty_nodes.insert(PassId(1), tree.root()); dirty_nodes.insert(PassId(1), tree.root());
resolve_passes(&mut tree, dirty_nodes, passes); resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
// Tree before: // Tree before:
// 1=\ // 1=\
@@ -745,6 +761,7 @@ fn up_pass() {
&self, &self,
node: &mut i32, node: &mut i32,
children: &mut dyn Iterator<Item = &'a mut i32>, children: &mut dyn Iterator<Item = &'a mut i32>,
_: &SendAnyMap,
) -> PassReturn { ) -> PassReturn {
*node += children.map(|i| *i).sum::<i32>(); *node += children.map(|i| *i).sum::<i32>();
PassReturn { PassReturn {
@@ -754,11 +771,12 @@ fn up_pass() {
} }
} }
let passes = vec![AnyPass::Upward(Box::new(AddPass))]; let add_pass = AnyPass::Upward(&AddPass);
let passes = vec![&add_pass];
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
dirty_nodes.insert(PassId(0), grandchild1); dirty_nodes.insert(PassId(0), grandchild1);
dirty_nodes.insert(PassId(0), grandchild2); dirty_nodes.insert(PassId(0), grandchild2);
resolve_passes(&mut tree, dirty_nodes, passes); resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
assert_eq!(tree.get(tree.root()).unwrap(), &2); assert_eq!(tree.get(tree.root()).unwrap(), &2);
assert_eq!(tree.get(child1).unwrap(), &1); assert_eq!(tree.get(child1).unwrap(), &1);
@@ -809,6 +827,7 @@ fn dependant_up_pass() {
&self, &self,
node: &mut i32, node: &mut i32,
children: &mut dyn Iterator<Item = &'a mut i32>, children: &mut dyn Iterator<Item = &'a mut i32>,
_: &SendAnyMap,
) -> PassReturn { ) -> PassReturn {
*node += children.map(|i| *i).sum::<i32>(); *node += children.map(|i| *i).sum::<i32>();
PassReturn { PassReturn {
@@ -841,6 +860,7 @@ fn dependant_up_pass() {
&self, &self,
node: &mut i32, node: &mut i32,
children: &mut dyn Iterator<Item = &'a mut i32>, children: &mut dyn Iterator<Item = &'a mut i32>,
_: &SendAnyMap,
) -> PassReturn { ) -> PassReturn {
*node -= children.map(|i| *i).sum::<i32>(); *node -= children.map(|i| *i).sum::<i32>();
PassReturn { PassReturn {
@@ -850,14 +870,13 @@ fn dependant_up_pass() {
} }
} }
let passes = vec![ let add_pass = AnyPass::Upward(&AddPass);
AnyPass::Upward(Box::new(AddPass)), let subtract_pass = AnyPass::Upward(&SubtractPass);
AnyPass::Upward(Box::new(SubtractPass)), let passes = vec![&add_pass, &subtract_pass];
];
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
dirty_nodes.insert(PassId(1), grandchild1); dirty_nodes.insert(PassId(1), grandchild1);
dirty_nodes.insert(PassId(1), grandchild2); dirty_nodes.insert(PassId(1), grandchild2);
resolve_passes(&mut tree, dirty_nodes, passes); resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
// Tree before: // Tree before:
// 0=\ // 0=\
+20 -28
View File
@@ -1,13 +1,13 @@
use anymap::AnyMap;
use dioxus_core::{ElementId, Mutations}; use dioxus_core::{ElementId, Mutations};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use crate::node::{Node, NodeData, NodeType, OwnedAttributeDiscription}; use crate::node::{Node, NodeType, OwnedAttributeDiscription};
use crate::node_ref::{AttributeMask, NodeMask}; use crate::node_ref::{AttributeMask, NodeMask};
use crate::passes::DirtyNodeStates;
use crate::state::State; use crate::state::State;
use crate::tree::{NodeId, Tree, TreeLike, TreeView}; use crate::tree::{NodeId, Tree, TreeLike, TreeView};
use crate::RealNodeId; use crate::{FxDashSet, RealNodeId, SendAnyMap};
fn mark_dirty( fn mark_dirty(
node_id: NodeId, node_id: NodeId,
@@ -96,10 +96,7 @@ impl<S: State> RealDom<S> {
} }
/// 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.
pub fn apply_mutations( pub fn apply_mutations(&mut self, mutations_vec: Vec<Mutations>) -> DirtyNodeStates {
&mut self,
mutations_vec: Vec<Mutations>,
) -> FxHashMap<RealNodeId, NodeMask> {
let mut nodes_updated: FxHashMap<RealNodeId, NodeMask> = FxHashMap::default(); let mut nodes_updated: FxHashMap<RealNodeId, NodeMask> = FxHashMap::default();
for mutations in mutations_vec { for mutations in mutations_vec {
for e in mutations.edits { for e in mutations.edits {
@@ -346,20 +343,28 @@ impl<S: State> RealDom<S> {
} }
} }
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list let dirty_nodes = DirtyNodeStates::default();
nodes_updated.retain(|k, _| self.tree.get(*k).is_some()); for (n, mask) in nodes_updated {
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if self.tree.contains(n) {
for (m, p) in S::MASKS.iter().zip(S::PASSES.iter()) {
if mask.overlaps(m) {
dirty_nodes.insert(p.pass_id(), n);
}
}
}
}
nodes_updated dirty_nodes
} }
/// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts. /// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
pub fn update_state( pub fn update_state(
&mut self, &mut self,
nodes_updated: FxHashMap<RealNodeId, NodeMask>, nodes_updated: DirtyNodeStates,
ctx: AnyMap, ctx: SendAnyMap,
) -> FxHashSet<RealNodeId> { ) -> FxDashSet<RealNodeId> {
let (mut state_tree, node_tree) = self.split(); S::update(nodes_updated, &mut self.tree, ctx)
S::update(&nodes_updated, &mut state_tree, &node_tree, &ctx)
} }
/// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up. /// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
@@ -389,19 +394,6 @@ impl<S: State> RealDom<S> {
self.tree.root() self.tree.root()
} }
pub fn split(&mut self) -> (impl TreeView<S> + '_, impl TreeView<NodeData> + '_) {
let raw = self as *mut Self;
// this is safe beacuse the treeview trait does not allow mutation of the position of elements, and within elements the access is disjoint.
(
unsafe { &mut *raw }
.tree
.map(|n| &n.state, |n| &mut n.state),
unsafe { &mut *raw }
.tree
.map(|n| &n.node_data, |n| &mut n.node_data),
)
}
fn clone_node(&mut self, node_id: NodeId) -> RealNodeId { fn clone_node(&mut self, node_id: NodeId) -> RealNodeId {
let node = self.tree.get(node_id).unwrap(); let node = self.tree.get(node_id).unwrap();
let new_node = node.clone(); let new_node = node.clone();
+20 -12
View File
@@ -1,11 +1,10 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use crate::node::NodeData; use crate::node::Node;
use crate::node_ref::{NodeMask, NodeView}; use crate::node_ref::{NodeMask, NodeView};
use crate::passes::{resolve_passes, AnyPass, DirtyNodeStates};
use crate::tree::TreeView; use crate::tree::TreeView;
use crate::RealNodeId; use crate::{FxDashSet, RealNodeId, SendAnyMap};
use anymap::AnyMap;
use rustc_hash::{FxHashMap, FxHashSet};
/// Join two sorted iterators /// Join two sorted iterators
pub(crate) fn union_ordered_iter<'a>( pub(crate) fn union_ordered_iter<'a>(
@@ -204,20 +203,29 @@ pub trait NodeDepState {
fn reduce<'a>( fn reduce<'a>(
&mut self, &mut self,
node: NodeView, node: NodeView,
siblings: <Self::DepState as ElementBorrowable>::ElementBorrowed<'a>, node_state: <Self::DepState as ElementBorrowable>::ElementBorrowed<'a>,
ctx: &Self::Ctx, ctx: &Self::Ctx,
) -> bool; ) -> bool;
} }
/// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom]. /// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
pub trait State: Default + Clone { pub trait State: Default + Clone + 'static {
#[doc(hidden)] #[doc(hidden)]
fn update<'a, T: TreeView<Self>, T2: TreeView<NodeData>>( const PASSES: &'static [AnyPass<Node<Self>>];
dirty: &FxHashMap<RealNodeId, NodeMask>, #[doc(hidden)]
state_tree: &'a mut T, const MASKS: &'static [NodeMask];
rdom: &'a T2,
ctx: &AnyMap, #[doc(hidden)]
) -> FxHashSet<RealNodeId>; fn update<T: TreeView<Node<Self>>>(
dirty: DirtyNodeStates,
tree: &mut T,
ctx: SendAnyMap,
) -> FxDashSet<RealNodeId> {
let set = FxDashSet::default();
let passes = Self::PASSES.iter().collect();
resolve_passes(tree, dirty, passes, ctx);
set
}
} }
impl ChildDepState for () { impl ChildDepState for () {
+4
View File
@@ -73,6 +73,10 @@ pub trait TreeView<T>: Sized {
fn root(&self) -> NodeId; fn root(&self) -> NodeId;
fn contains(&self, id: NodeId) -> bool {
self.get(id).is_some()
}
fn get(&self, id: NodeId) -> Option<&T>; fn get(&self, id: NodeId) -> Option<&T>;
fn get_unchecked(&self, id: NodeId) -> &T { fn get_unchecked(&self, id: NodeId) -> &T {