update the update_state method

This commit is contained in:
Evan Almloff committed 2023-01-01 12:10:19 -06:00
1 parent bc2925240e
commit 3c507479cb
7 files changed
+83 -63

No files matched your search

+17 -24
View File
@@ -19,8 +19,6 @@ pub trait Pass: Any {
type ChildDependencies: Dependancy; type ChildDependencies: Dependancy;
/// This is a tuple of (T: Any, ..) /// This is a tuple of (T: Any, ..)
type NodeDependencies: Dependancy; type NodeDependencies: Dependancy;
/// This is a tuple of (T: Any, ..)
type Ctx: Dependancy;
const NODE_MASK: NodeMask; const NODE_MASK: NodeMask;
fn pass<'a>( fn pass<'a>(
@@ -31,22 +29,22 @@ pub trait Pass: Any {
children: Option< children: Option<
impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>, impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
>, >,
context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>, context: &SendAnyMap,
) -> bool; ) -> bool;
fn is_valid(&self) -> bool { fn validate() {
// no type can be a child and parent dependency // no type can be a child and parent dependency
for type_id in Self::parent_type_ids() { for type_id in Self::parent_type_ids() {
for type_id2 in Self::child_type_ids() { for type_id2 in Self::child_type_ids() {
if type_id == type_id2 { if type_id == type_id2 {
return false; panic!("type cannot be both a parent and child dependency");
} }
} }
} }
// this type should not be a node dependency // this type should not be a node dependency
for type_id in Self::node_type_ids() { for type_id in Self::node_type_ids() {
if type_id == TypeId::of::<Self>() { if type_id == TypeId::of::<Self>() {
return false; panic!("The current type cannot be a node dependency");
} }
} }
// no states have the same type id // no states have the same type id
@@ -56,18 +54,20 @@ pub trait Pass: Any {
.len() .len()
!= Self::all_dependanices().len() != Self::all_dependanices().len()
{ {
return false; panic!("all states must have unique type ids");
} }
true
} }
fn to_type_erased<T: AnyMapLike + State>() -> TypeErasedPass<T> fn to_type_erased<T: AnyMapLike + State>() -> TypeErasedPass<T>
where where
Self: Sized, Self: Sized,
{ {
Self::validate();
TypeErasedPass { TypeErasedPass {
this_type_id: TypeId::of::<Self>(), this_type_id: TypeId::of::<Self>(),
combined_dependancy_type_ids: Self::all_dependanices().into_iter().collect(), combined_dependancy_type_ids: Self::all_dependanices().into_iter().collect(),
parent_dependant: !Self::parent_type_ids().is_empty(),
child_dependant: !Self::child_type_ids().is_empty(),
dependants: FxHashSet::default(), dependants: FxHashSet::default(),
mask: Self::NODE_MASK, mask: Self::NODE_MASK,
pass_direction: Self::pass_direction(), pass_direction: Self::pass_direction(),
@@ -96,8 +96,6 @@ pub trait Pass: Any {
.get_mut() .get_mut()
.expect("tried to get a pass that does not exist") .expect("tried to get a pass that does not exist")
}; };
let context = Self::Ctx::borrow_elements_from(context)
.expect("tried to get a pass that does not exist");
myself.pass( myself.pass(
NodeView::new(&current_node.node_data, Self::NODE_MASK), NodeView::new(&current_node.node_data, Self::NODE_MASK),
node, node,
@@ -149,11 +147,13 @@ pub trait Pass: Any {
pub struct TypeErasedPass<T: AnyMapLike + State> { pub struct TypeErasedPass<T: AnyMapLike + State> {
pub(crate) this_type_id: TypeId, pub(crate) this_type_id: TypeId,
pub(crate) parent_dependant: bool,
pub(crate) child_dependant: bool,
pub(crate) combined_dependancy_type_ids: FxHashSet<TypeId>, pub(crate) combined_dependancy_type_ids: FxHashSet<TypeId>,
pub(crate) dependants: FxHashSet<TypeId>, pub(crate) dependants: FxHashSet<TypeId>,
pub(crate) mask: NodeMask, pub(crate) mask: NodeMask,
pass: PassCallback<T>, pass: PassCallback<T>,
pass_direction: PassDirection, pub(crate) pass_direction: PassDirection,
} }
impl<T: AnyMapLike + State> TypeErasedPass<T> { impl<T: AnyMapLike + State> TypeErasedPass<T> {
@@ -183,6 +183,7 @@ impl<T: AnyMapLike + State> TypeErasedPass<T> {
} }
PassDirection::ChildToParent => { PassDirection::ChildToParent => {
while let Some(id) = dirty.pop_back() { while let Some(id) = dirty.pop_back() {
println!("running pass {:?} on {:?}", self.this_type_id, id);
if (self.pass)(id, tree, ctx) { if (self.pass)(id, tree, 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) {
@@ -210,6 +211,7 @@ impl<T: AnyMapLike + State> TypeErasedPass<T> {
} }
} }
#[derive(Debug)]
pub enum PassDirection { pub enum PassDirection {
ParentToChild, ParentToChild,
ChildToParent, ChildToParent,
@@ -248,7 +250,6 @@ pub trait Dependancy {
where where
Self: 'a; Self: 'a;
fn borrow_elements(&self) -> Self::ElementBorrowed<'_>;
fn borrow_elements_from<T: AnyMapLike>(map: &T) -> Option<Self::ElementBorrowed<'_>>; fn borrow_elements_from<T: AnyMapLike>(map: &T) -> Option<Self::ElementBorrowed<'_>>;
fn type_ids() -> Vec<TypeId>; fn type_ids() -> Vec<TypeId>;
} }
@@ -258,12 +259,6 @@ macro_rules! impl_dependancy {
impl< $($t: Any),* > Dependancy for ($($t,)*) { impl< $($t: Any),* > Dependancy for ($($t,)*) {
type ElementBorrowed<'a> = ($(&'a $t,)*) where Self: 'a; type ElementBorrowed<'a> = ($(&'a $t,)*) where Self: 'a;
#[allow(clippy::unused_unit, non_snake_case)]
fn borrow_elements<'a>(&'a self) -> Self::ElementBorrowed<'a> {
let ($($t,)*) = self;
($($t,)*)
}
#[allow(unused_variables, clippy::unused_unit, non_snake_case)] #[allow(unused_variables, clippy::unused_unit, non_snake_case)]
fn borrow_elements_from<T: AnyMapLike>(map: &T) -> Option<Self::ElementBorrowed<'_>> { fn borrow_elements_from<T: AnyMapLike>(map: &T) -> Option<Self::ElementBorrowed<'_>> {
Some(($(map.get::<$t>()?,)*)) Some(($(map.get::<$t>()?,)*))
@@ -391,15 +386,13 @@ pub fn resolve_passes<T: AnyMapLike + State + Send>(
let pass = &passes[passes_idx]; let pass = &passes[passes_idx];
let pass_id = pass.this_type_id; let pass_id = pass.this_type_id;
// check if the pass is ready to be run // check if the pass is ready to be run
if pass if pass.combined_dependancy_type_ids.iter().all(|d| {
.combined_dependancy_type_ids (resolved_passes.contains(d) || *d == pass_id) && !currently_in_use.contains(d)
.iter() }) {
.all(|d| resolved_passes.contains(d) || *d == pass_id)
{
pass_indexes_remaining.remove(i); pass_indexes_remaining.remove(i);
resolving.push(pass_id); resolving.push(pass_id);
currently_in_use.insert(pass.this_type_id); currently_in_use.insert(pass.this_type_id);
// 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 // this is safe because each pass only has mutable access to the member associated with this_type_id and we have verified that the pass does not overlap with any other pass currently running
let tree_unbounded_mut = unsafe { &mut *(tree as *mut _) }; let tree_unbounded_mut = unsafe { &mut *(tree as *mut _) };
let dirty_states = dirty_states.clone(); let dirty_states = dirty_states.clone();
let nodes_updated = nodes_updated.clone(); let nodes_updated = nodes_updated.clone();
+48 -14
View File
@@ -1,6 +1,5 @@
use dioxus_core::{ElementId, Mutations, TemplateNode}; use dioxus_core::{ElementId, Mutations, TemplateNode};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::any::TypeId;
use std::fmt::Debug; use std::fmt::Debug;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
@@ -25,9 +24,10 @@ pub struct RealDom<S: State + Send> {
templates: FxHashMap<String, Vec<NodeId>>, templates: FxHashMap<String, Vec<NodeId>>,
pub(crate) passes: Box<[TypeErasedPass<S>]>, pub(crate) passes: Box<[TypeErasedPass<S>]>,
pub(crate) nodes_updated: FxHashMap<NodeId, NodeMask>, pub(crate) nodes_updated: FxHashMap<NodeId, NodeMask>,
passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>, passes_updated: DirtyNodeStates,
parent_changed_nodes: FxHashSet<NodeId>, parent_changed_nodes: FxHashSet<NodeId>,
child_changed_nodes: FxHashSet<NodeId>, child_changed_nodes: FxHashSet<NodeId>,
nodes_created: FxHashSet<NodeId>,
} }
impl<S: State + Send + Debug> Debug for RealDom<S> { impl<S: State + Send + Debug> Debug for RealDom<S> {
@@ -75,6 +75,14 @@ impl<S: State + Send> RealDom<S> {
} }
} }
} }
for pass in passes.iter_mut() {
println!("{:?}: {:?}", pass.this_type_id, pass.dependants);
println!("{:?}", pass.child_dependant);
println!("{:?}", pass.parent_dependant);
println!("{:?}", pass.pass_direction);
}
let mut nodes_updated = FxHashMap::default(); let mut nodes_updated = FxHashMap::default();
let root_id = NodeId(0); let root_id = NodeId(0);
nodes_updated.insert(root_id, NodeMask::ALL); nodes_updated.insert(root_id, NodeMask::ALL);
@@ -87,9 +95,10 @@ impl<S: State + Send> RealDom<S> {
templates: FxHashMap::default(), templates: FxHashMap::default(),
passes, passes,
nodes_updated, nodes_updated,
passes_updated: FxHashMap::default(), passes_updated: DirtyNodeStates::default(),
parent_changed_nodes: FxHashSet::default(), parent_changed_nodes: FxHashSet::default(),
child_changed_nodes: FxHashSet::default(), child_changed_nodes: FxHashSet::default(),
nodes_created: FxHashSet::default(),
} }
} }
@@ -140,7 +149,7 @@ impl<S: State + Send> RealDom<S> {
let node = self.tree.get_mut(node_id).unwrap(); let node = self.tree.get_mut(node_id).unwrap();
node.node_data.node_id = node_id; node.node_data.node_id = node_id;
if mark_dirty { if mark_dirty {
self.nodes_updated.insert(node_id, NodeMask::ALL); self.nodes_created.insert(node_id);
} }
node_id node_id
} }
@@ -370,22 +379,50 @@ impl<S: State + Send> RealDom<S> {
&mut self, &mut self,
ctx: SendAnyMap, ctx: SendAnyMap,
) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) { ) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
let tree = &mut self.tree;
let passes = &self.passes; let passes = &self.passes;
let dirty_nodes = DirtyNodeStates::default(); let dirty_nodes = std::mem::take(&mut self.passes_updated);
let nodes_updated = std::mem::take(&mut self.nodes_updated); let nodes_updated = std::mem::take(&mut self.nodes_updated);
for (&n, mask) in &nodes_updated { for (&node, mask) in &nodes_updated {
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if self.tree.contains(n) { if self.tree.contains(node) {
for pass in &*self.passes { for pass in &*self.passes {
if mask.overlaps(&pass.mask) { if mask.overlaps(&pass.mask) {
dirty_nodes.insert(pass.this_type_id, n); dirty_nodes.insert(pass.this_type_id, node);
} }
} }
} }
} }
for node in std::mem::take(&mut self.child_changed_nodes) {
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if self.tree.contains(node) {
for pass in &*self.passes {
if pass.child_dependant {
dirty_nodes.insert(pass.this_type_id, node);
}
}
}
}
for node in std::mem::take(&mut self.parent_changed_nodes) {
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if self.tree.contains(node) {
for pass in &*self.passes {
if pass.parent_dependant {
dirty_nodes.insert(pass.this_type_id, node);
}
}
}
}
for node in std::mem::take(&mut self.nodes_created) {
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if self.tree.contains(node) {
for pass in &*self.passes {
dirty_nodes.insert(pass.this_type_id, node);
}
}
}
let tree = &mut self.tree;
todo!("incorporate other update members");
( (
resolve_passes(tree, dirty_nodes, passes, ctx), resolve_passes(tree, dirty_nodes, passes, ctx),
nodes_updated, nodes_updated,
@@ -428,10 +465,7 @@ impl<S: State + Send> RealDom<S> {
let new_id = self.create_node(new_node, false); let new_id = self.create_node(new_node, false);
let passes = S::non_clone_members(); let passes = S::non_clone_members();
for pass_id in &*passes { for pass_id in &*passes {
self.passes_updated self.passes_updated.insert(*pass_id, node_id);
.entry(node_id)
.or_default()
.insert(*pass_id);
} }
let self_ptr = self as *mut Self; let self_ptr = self as *mut Self;
-5
View File
@@ -1,11 +1,6 @@
use core::panic;
use parking_lot::lock_api::RawMutex as _;
use parking_lot::{RawMutex, RwLock};
use slab::Slab; use slab::Slab;
use std::cell::UnsafeCell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc;
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord)] #[derive(Hash, PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord)]
pub struct NodeId(pub usize); pub struct NodeId(pub usize);
+5 -6
View File
@@ -3,7 +3,7 @@ use crate::{node::PreventDefault, TuiDom};
use dioxus_native_core::{ use dioxus_native_core::{
tree::TreeView, tree::TreeView,
utils::{ElementProduced, PersistantElementIter}, utils::{ElementProduced, PersistantElementIter},
NodeId, Pass, NodeId, Pass, SendAnyMap,
}; };
use dioxus_native_core_macro::sorted_str_slice; use dioxus_native_core_macro::sorted_str_slice;
@@ -62,7 +62,6 @@ pub(crate) struct Focus {
} }
impl Pass for Focus { impl Pass for Focus {
type Ctx = ();
const NODE_MASK: NodeMask = const NODE_MASK: NodeMask =
NodeMask::new_with_attrs(AttributeMask::Static(FOCUS_ATTRIBUTES)).with_listeners(); NodeMask::new_with_attrs(AttributeMask::Static(FOCUS_ATTRIBUTES)).with_listeners();
@@ -73,18 +72,18 @@ impl Pass for Focus {
fn pass<'a>( fn pass<'a>(
&mut self, &mut self,
node_view: NodeView, node_view: NodeView,
node: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, _: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
parent: Option< _: Option<
<Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, <Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
>, >,
children: Option< _: Option<
impl Iterator< impl Iterator<
Item = <Self::ChildDependencies as dioxus_native_core::Dependancy>::ElementBorrowed< Item = <Self::ChildDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<
'a, 'a,
>, >,
>, >,
>, >,
context: <Self::Ctx as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, _: &SendAnyMap,
) -> bool { ) -> bool {
let new = Focus { let new = Focus {
level: if let Some(a) = node_view level: if let Some(a) = node_view
+7 -5
View File
@@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
use dioxus_native_core::layout_attributes::apply_layout_attributes; use dioxus_native_core::layout_attributes::apply_layout_attributes;
use dioxus_native_core::node::OwnedAttributeView; use dioxus_native_core::node::OwnedAttributeView;
use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView}; use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView};
use dioxus_native_core::Pass; use dioxus_native_core::{Pass, SendAnyMap};
use dioxus_native_core_macro::sorted_str_slice; use dioxus_native_core_macro::sorted_str_slice;
use taffy::prelude::*; use taffy::prelude::*;
@@ -14,6 +14,7 @@ pub(crate) enum PossiblyUninitalized<T> {
Uninitalized, Uninitalized,
Initialized(T), Initialized(T),
} }
impl<T> PossiblyUninitalized<T> { impl<T> PossiblyUninitalized<T> {
pub fn unwrap(self) -> T { pub fn unwrap(self) -> T {
match self { match self {
@@ -41,7 +42,6 @@ pub(crate) struct TaffyLayout {
} }
impl Pass for TaffyLayout { impl Pass for TaffyLayout {
type Ctx = (Arc<Mutex<Taffy>>,);
type ChildDependencies = (Self,); type ChildDependencies = (Self,);
type ParentDependencies = (); type ParentDependencies = ();
type NodeDependencies = (); type NodeDependencies = ();
@@ -52,8 +52,8 @@ impl Pass for TaffyLayout {
fn pass<'a>( fn pass<'a>(
&mut self, &mut self,
node_view: NodeView, node_view: NodeView,
node: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, _: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
parent: Option< _: Option<
<Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, <Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
>, >,
children: Option< children: Option<
@@ -63,9 +63,11 @@ impl Pass for TaffyLayout {
>, >,
>, >,
>, >,
(taffy,): <Self::Ctx as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, ctx: &SendAnyMap,
) -> bool { ) -> bool {
println!("running layout pass on node: \n{:#?}", node_view);
let mut changed = false; let mut changed = false;
let taffy: &Arc<Mutex<Taffy>> = ctx.get().unwrap();
let mut taffy = taffy.lock().expect("poisoned taffy"); let mut taffy = taffy.lock().expect("poisoned taffy");
let mut style = Style::default(); let mut style = Style::default();
if let Some(text) = node_view.text() { if let Some(text) = node_view.text() {
+2 -4
View File
@@ -1,7 +1,7 @@
use crate::focus::Focus; use crate::focus::Focus;
use crate::layout::TaffyLayout; use crate::layout::TaffyLayout;
use crate::style_attributes::StyleModifier; use crate::style_attributes::StyleModifier;
use dioxus_native_core::{real_dom::RealDom, Dependancy, Pass}; use dioxus_native_core::{real_dom::RealDom, Dependancy, Pass, SendAnyMap};
use dioxus_native_core_macro::{sorted_str_slice, AnyMapLike, State}; use dioxus_native_core_macro::{sorted_str_slice, AnyMapLike, State};
pub(crate) type TuiDom = RealDom<NodeState>; pub(crate) type TuiDom = RealDom<NodeState>;
@@ -48,8 +48,6 @@ impl Pass for PreventDefault {
type ChildDependencies = (); type ChildDependencies = ();
type NodeDependencies = (); type NodeDependencies = ();
type Ctx = ();
const NODE_MASK: dioxus_native_core::node_ref::NodeMask = const NODE_MASK: dioxus_native_core::node_ref::NodeMask =
dioxus_native_core::node_ref::NodeMask::new_with_attrs( dioxus_native_core::node_ref::NodeMask::new_with_attrs(
dioxus_native_core::node_ref::AttributeMask::Static(&sorted_str_slice!([ dioxus_native_core::node_ref::AttributeMask::Static(&sorted_str_slice!([
@@ -66,7 +64,7 @@ impl Pass for PreventDefault {
children: Option< children: Option<
impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>, impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
>, >,
context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>, context: &SendAnyMap,
) -> bool { ) -> bool {
let new = match node_view.attributes().and_then(|mut attrs| { let new = match node_view.attributes().and_then(|mut attrs| {
attrs attrs
+4 -5
View File
@@ -33,7 +33,7 @@ use dioxus_native_core::{
layout_attributes::parse_value, layout_attributes::parse_value,
node::OwnedAttributeView, node::OwnedAttributeView,
node_ref::{AttributeMask, NodeMask, NodeView}, node_ref::{AttributeMask, NodeMask, NodeView},
Pass, Pass, SendAnyMap,
}; };
use dioxus_native_core_macro::sorted_str_slice; use dioxus_native_core_macro::sorted_str_slice;
use taffy::prelude::*; use taffy::prelude::*;
@@ -47,7 +47,6 @@ pub struct StyleModifier {
} }
impl Pass for StyleModifier { impl Pass for StyleModifier {
type Ctx = ();
type ParentDependencies = (Self,); type ParentDependencies = (Self,);
type ChildDependencies = (); type ChildDependencies = ();
type NodeDependencies = (); type NodeDependencies = ();
@@ -59,18 +58,18 @@ impl Pass for StyleModifier {
fn pass<'a>( fn pass<'a>(
&mut self, &mut self,
node_view: NodeView, node_view: NodeView,
node: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, _: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
parent: Option< parent: Option<
<Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, <Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
>, >,
children: Option< _: Option<
impl Iterator< impl Iterator<
Item = <Self::ChildDependencies as dioxus_native_core::Dependancy>::ElementBorrowed< Item = <Self::ChildDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<
'a, 'a,
>, >,
>, >,
>, >,
context: <Self::Ctx as dioxus_native_core::Dependancy>::ElementBorrowed<'a>, _: &SendAnyMap,
) -> bool { ) -> bool {
let mut new = StyleModifier::default(); let mut new = StyleModifier::default();
if parent.is_some() { if parent.is_some() {