WIP make ECS work with reactive system

This commit is contained in:
Evan Almloff committed 2023-01-19 14:40:56 -06:00
1 parent e36874d86e
commit 1587b41829
10 files changed
+564 -685

No files matched your search

+1 -1
View File
@@ -20,7 +20,7 @@ smallvec = "1.6"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
anymap = "1.0.0-beta.2" anymap = "1.0.0-beta.2"
slab = "0.4" slab = "0.4"
parking_lot = "0.12.1" parking_lot = { version = "0.12.1", features = ["send_guard"] }
crossbeam-deque = "0.8.2" crossbeam-deque = "0.8.2"
dashmap = "5.4.0" dashmap = "5.4.0"
hashbrown = { version = "0.13.2", features = ["raw"] } hashbrown = { version = "0.13.2", features = ["raw"] }
-2
View File
@@ -5,7 +5,6 @@ pub use node_ref::NodeMask;
pub use passes::AnyMapLike; pub use passes::AnyMapLike;
pub use passes::{Dependancy, Pass, TypeErasedPass}; pub use passes::{Dependancy, Pass, TypeErasedPass};
use rustc_hash::FxHasher; use rustc_hash::FxHasher;
pub use state::State;
pub use tree::NodeId; pub use tree::NodeId;
pub mod layout_attributes; pub mod layout_attributes;
@@ -13,7 +12,6 @@ pub mod node;
pub mod node_ref; pub mod node_ref;
mod passes; mod passes;
pub mod real_dom; pub mod real_dom;
pub mod state;
pub mod tree; pub mod tree;
pub mod utils; pub mod utils;
+7 -19
View File
@@ -1,17 +1,8 @@
use crate::{state::State, tree::NodeId}; use crate::tree::NodeId;
use dioxus_core::{AnyValue, BorrowedAttributeValue, ElementId}; use dioxus_core::{AnyValue, BorrowedAttributeValue, ElementId};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::fmt::Debug; use std::fmt::Debug;
/// The node is stored client side and stores only basic data about the node.
#[derive(Debug, Clone)]
pub struct Node<S: State<V>, V: FromAnyValue = ()> {
/// The transformed state of the node.
pub state: S,
/// The raw data for the node
pub node_data: NodeData<V>,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct NodeData<V: FromAnyValue = ()> { pub struct NodeData<V: FromAnyValue = ()> {
/// The id of the node /// The id of the node
@@ -38,21 +29,18 @@ pub enum NodeType<V: FromAnyValue = ()> {
Placeholder, Placeholder,
} }
impl<S: State<V>, V: FromAnyValue> Node<S, V> { impl<V: FromAnyValue> NodeData<V> {
pub(crate) fn new(node_type: NodeType<V>) -> Self { pub(crate) fn new(node_type: NodeType<V>) -> Self {
Node { NodeData {
state: S::default(), element_id: None,
node_data: NodeData { node_type,
element_id: None, node_id: NodeId(0),
node_type,
node_id: NodeId(0),
},
} }
} }
/// get the mounted id of the node /// get the mounted id of the node
pub fn mounted_id(&self) -> Option<ElementId> { pub fn mounted_id(&self) -> Option<ElementId> {
self.node_data.element_id self.element_id
} }
} }
+37 -1
View File
@@ -1,11 +1,47 @@
use std::cmp::Ordering;
use dioxus_core::ElementId; use dioxus_core::ElementId;
use crate::{ use crate::{
node::{ElementNode, FromAnyValue, NodeData, NodeType, OwnedAttributeView}, node::{ElementNode, FromAnyValue, NodeData, NodeType, OwnedAttributeView},
state::union_ordered_iter,
NodeId, NodeId,
}; };
/// Join two sorted iterators
pub(crate) fn union_ordered_iter<'a>(
s_iter: impl Iterator<Item = &'a str>,
o_iter: impl Iterator<Item = &'a str>,
new_len_guess: usize,
) -> Vec<String> {
let mut s_peekable = s_iter.peekable();
let mut o_peekable = o_iter.peekable();
let mut v = Vec::with_capacity(new_len_guess);
while let Some(s_i) = s_peekable.peek() {
while let Some(o_i) = o_peekable.peek() {
match o_i.cmp(s_i) {
Ordering::Greater => {
break;
}
Ordering::Less => {
v.push(o_peekable.next().unwrap().to_string());
}
Ordering::Equal => {
o_peekable.next();
break;
}
}
}
v.push(s_peekable.next().unwrap().to_string());
}
for o_i in o_peekable {
v.push(o_i.to_string());
}
for w in v.windows(2) {
debug_assert!(w[1] > w[0]);
}
v
}
/// A view into a [VNode] with limited access. /// A view into a [VNode] with limited access.
#[derive(Debug)] #[derive(Debug)]
pub struct NodeView<'a, V: FromAnyValue = ()> { pub struct NodeView<'a, V: FromAnyValue = ()> {
+173 -193
View File
@@ -1,18 +1,115 @@
use anymap::AnyMap; use anymap::AnyMap;
use parking_lot::RwLock;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use std::any::{Any, TypeId}; use std::any::{self, Any, TypeId};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::marker::PhantomData;
use std::sync::Arc; use std::sync::Arc;
use crate::node::{FromAnyValue, Node}; use crate::node::{FromAnyValue, NodeData};
use crate::node_ref::NodeView; use crate::node_ref::NodeView;
use crate::state::State; use crate::real_dom::RealDom;
use crate::tree::TreeViewMut; use crate::tree::{Node, TreeStateView};
use crate::tree::{Tree, TreeView};
use crate::{FxDashMap, FxDashSet, SendAnyMap}; use crate::{FxDashMap, FxDashSet, SendAnyMap};
use crate::{NodeId, NodeMask}; use crate::{NodeId, NodeMask};
pub trait Pass<V: FromAnyValue = ()>: Any { #[derive(Default)]
struct DirtyNodes {
passes_dirty: Vec<u64>,
}
impl DirtyNodes {
pub fn add_node(&mut self, node_id: NodeId) {
let node_id = node_id.0;
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 {
self.passes_dirty.iter().all(|dirty| *dirty == 0)
}
pub fn pop(&mut self) -> Option<NodeId> {
let index = self.passes_dirty.iter().position(|dirty| *dirty != 0)?;
let passes = self.passes_dirty[index];
let node_id = passes.trailing_zeros();
let encoded = 1 << node_id;
self.passes_dirty[index] &= !encoded;
Some(NodeId((index * 64) + node_id as usize))
}
}
#[derive(Default, Clone)]
pub struct DirtyNodeStates {
dirty: Arc<RwLock<BTreeMap<u16, FxDashMap<TypeId, DirtyNodes>>>>,
}
impl DirtyNodeStates {
pub fn insert(&self, pass_id: TypeId, node_id: NodeId, height: u16) {
let mut dirty = self.dirty.write();
if let Some(dirty) = dirty.get_mut(&height) {
if let Some(mut entry) = dirty.get_mut(&pass_id) {
entry.add_node(node_id);
} else {
let mut entry = DirtyNodes::default();
entry.add_node(node_id);
dirty.insert(pass_id, entry);
}
} else {
let mut entry = DirtyNodes::default();
entry.add_node(node_id);
let hm = FxDashMap::default();
hm.insert(pass_id, entry);
dirty.insert(height, hm);
}
}
fn pop_front(&self, pass_id: TypeId) -> Option<(u16, NodeId)> {
let dirty_read = self.dirty.read();
let (&height, values) = dirty_read
.iter()
.find(|(_, values)| values.contains_key(&pass_id))?;
let mut dirty = values.get_mut(&pass_id)?;
let node_id = dirty.pop()?;
if dirty.is_empty() {
values.remove(&pass_id);
}
if values.is_empty() {
let mut dirty_write = self.dirty.write();
dirty_write.remove(&height);
}
Some((height, node_id))
}
fn pop_back(&self, pass_id: TypeId) -> Option<(u16, NodeId)> {
let dirty_read = self.dirty.read();
let (&height, values) = dirty_read
.iter()
.rev()
.find(|(_, values)| values.contains_key(&pass_id))?;
let mut dirty = values.get_mut(&pass_id)?;
let node_id = dirty.pop()?;
if dirty.is_empty() {
values.remove(&pass_id);
}
if values.is_empty() {
let mut dirty_write = self.dirty.write();
dirty_write.remove(&height);
}
Some((height, node_id))
}
}
pub trait Pass<V: FromAnyValue + Send = ()>: Any {
/// This is a tuple of (T: Any, ..) /// This is a tuple of (T: Any, ..)
type ParentDependencies: Dependancy; type ParentDependencies: Dependancy;
/// This is a tuple of (T: Any, ..) /// This is a tuple of (T: Any, ..)
@@ -26,23 +123,21 @@ pub trait Pass<V: FromAnyValue = ()>: Any {
node_view: NodeView<V>, node_view: NodeView<V>,
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>, node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>, parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
children: Option< children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
>,
context: &SendAnyMap, context: &SendAnyMap,
) -> bool; ) -> bool;
fn validate() { 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().into_iter().copied() {
for type_id2 in Self::child_type_ids() { for type_id2 in Self::child_type_ids().into_iter().copied() {
if type_id == type_id2 { if type_id == type_id2 {
panic!("type cannot be both a parent and child dependency"); 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().into_iter().copied() {
if type_id == TypeId::of::<Self>() { if type_id == TypeId::of::<Self>() {
panic!("The current type cannot be a node dependency"); panic!("The current type cannot be a node dependency");
} }
@@ -58,85 +153,74 @@ pub trait Pass<V: FromAnyValue = ()>: Any {
} }
} }
fn to_type_erased<T: AnyMapLike + State<V>>() -> TypeErasedPass<T, V> fn to_type_erased() -> TypeErasedPass<V>
where where
Self: Sized, Self: Sized,
{ {
Self::validate(); 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().copied().collect(),
parent_dependant: !Self::parent_type_ids().is_empty(), parent_dependant: !Self::parent_type_ids().is_empty(),
child_dependant: !Self::child_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(),
pass: Box::new( pass: Box::new(
|node_id: NodeId, any_map: &mut Tree<Node<T, V>>, context: &SendAnyMap| { |node_id: NodeId, tree: &mut TreeStateView, context: &SendAnyMap| {
let (current_node, parent, children) = any_map debug_assert!(!Self::NodeDependencies::type_ids()
.node_parent_children_mut(node_id) .into_iter()
.expect("tried to run pass on node that does not exist"); .any(|id| *id == TypeId::of::<Self>()));
let current_node_raw = current_node as *mut Node<T, V>; // get all of the states from the tree view
let node = Self::NodeDependencies::borrow_elements_from(&current_node.state) // Safety: No node has itself as a parent or child.
.expect("tried to get a pass that does not exist"); let node_raw = tree.get_mut::<Self>(node_id).unwrap() as *mut Self;
let parent = parent.map(|parent| { let node_data = tree.get_single::<NodeData<V>>(node_id).unwrap();
Self::ParentDependencies::borrow_elements_from(&parent.state) let node = tree.get::<Self::NodeDependencies>(node_id).unwrap();
.expect("tried to get a pass that does not exist") let children = tree.children::<Self::ChildDependencies>(node_id);
}); let parent = tree.parent::<Self::ParentDependencies>(node_id);
let children = children.map(|children| { let myself = unsafe { &mut *node_raw };
children.map(|child| {
Self::ChildDependencies::borrow_elements_from(&child.state)
.expect("tried to get a pass that does not exist")
})
});
// safety: we have varified the pass is valid in the is_valid function
let myself: &mut Self = unsafe {
(*current_node_raw)
.state
.get_mut()
.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(&node_data, Self::NODE_MASK),
node, node,
parent, parent,
children, children,
context, context,
) )
}, },
) ) as PassCallback,
as Box<dyn Fn(NodeId, &mut Tree<Node<T, V>>, &SendAnyMap) -> bool + Send + Sync>, phantom: PhantomData,
} }
} }
fn parent_type_ids() -> Vec<TypeId> { fn parent_type_ids() -> Box<[TypeId]> {
Self::ParentDependencies::type_ids() Self::ParentDependencies::type_ids()
} }
fn child_type_ids() -> Vec<TypeId> { fn child_type_ids() -> Box<[TypeId]> {
Self::ChildDependencies::type_ids() Self::ChildDependencies::type_ids()
} }
fn node_type_ids() -> Vec<TypeId> { fn node_type_ids() -> Box<[TypeId]> {
Self::NodeDependencies::type_ids() Self::NodeDependencies::type_ids()
} }
fn all_dependanices() -> Vec<TypeId> { fn all_dependanices() -> Box<[TypeId]> {
let mut dependencies = Self::parent_type_ids(); let mut dependencies = Self::parent_type_ids().to_vec();
dependencies.extend(Self::child_type_ids()); dependencies.extend(Self::child_type_ids().into_iter());
dependencies.extend(Self::node_type_ids()); dependencies.extend(Self::node_type_ids().into_iter());
dependencies dependencies.into_boxed_slice()
} }
fn pass_direction() -> PassDirection { fn pass_direction() -> PassDirection {
if Self::child_type_ids() if Self::child_type_ids()
.into_iter() .into_iter()
.any(|type_id| type_id == TypeId::of::<Self>()) .any(|type_id| *type_id == TypeId::of::<Self>())
{ {
PassDirection::ChildToParent PassDirection::ChildToParent
} else if Self::parent_type_ids() } else if Self::parent_type_ids()
.into_iter() .into_iter()
.any(|type_id| type_id == TypeId::of::<Self>()) .any(|type_id| *type_id == TypeId::of::<Self>())
{ {
PassDirection::ParentToChild PassDirection::ParentToChild
} else { } else {
@@ -145,63 +229,57 @@ pub trait Pass<V: FromAnyValue = ()>: Any {
} }
} }
pub struct TypeErasedPass<T: AnyMapLike + State<V>, V: FromAnyValue = ()> { pub struct TypeErasedPass<V: FromAnyValue + Send = ()> {
pub(crate) this_type_id: TypeId, pub(crate) this_type_id: TypeId,
pub(crate) parent_dependant: bool, pub(crate) parent_dependant: bool,
pub(crate) child_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, V>, pass: PassCallback,
pub(crate) pass_direction: PassDirection, pub(crate) pass_direction: PassDirection,
phantom: PhantomData<V>,
} }
impl<T: AnyMapLike + State<V>, V: FromAnyValue> TypeErasedPass<T, V> { impl<V: FromAnyValue + Send> TypeErasedPass<V> {
fn resolve( fn resolve(
&self, &self,
tree: &mut Tree<Node<T, V>>, mut tree: TreeStateView,
mut dirty: DirtyNodes, dirty: &DirtyNodeStates,
dirty_states: &DirtyNodeStates,
nodes_updated: &FxDashSet<NodeId>, nodes_updated: &FxDashSet<NodeId>,
ctx: &SendAnyMap, ctx: &SendAnyMap,
) { ) {
match self.pass_direction { match self.pass_direction {
PassDirection::ParentToChild => { PassDirection::ParentToChild => {
while let Some(id) = dirty.pop_front() { while let Some((height, id)) = dirty.pop_front(self.this_type_id) {
if (self.pass)(id, tree, ctx) { if (self.pass)(id, &mut tree, ctx) {
nodes_updated.insert(id); nodes_updated.insert(id);
for id in tree.children_ids(id).unwrap() { for id in tree.children_ids(id).unwrap() {
for dependant in &self.dependants { for dependant in &self.dependants {
dirty_states.insert(*dependant, *id); dirty.insert(*dependant, id, height + 1);
} }
let height = tree.height(*id).unwrap();
dirty.insert(height, *id);
} }
} }
} }
} }
PassDirection::ChildToParent => { PassDirection::ChildToParent => {
while let Some(id) = dirty.pop_back() { while let Some((height, id)) = dirty.pop_back(self.this_type_id) {
if (self.pass)(id, tree, ctx) { if (self.pass)(id, &mut 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) {
for dependant in &self.dependants { for dependant in &self.dependants {
dirty_states.insert(*dependant, id); dirty.insert(*dependant, id, height - 1);
} }
let height = tree.height(id).unwrap();
dirty.insert(height, id);
} }
} }
} }
} }
PassDirection::AnyOrder => { PassDirection::AnyOrder => {
while let Some(id) = dirty.pop_back() { while let Some((height, id)) = dirty.pop_back(self.this_type_id) {
if (self.pass)(id, tree, ctx) { if (self.pass)(id, &mut tree, ctx) {
nodes_updated.insert(id); nodes_updated.insert(id);
for dependant in &self.dependants { for dependant in &self.dependants {
dirty_states.insert(*dependant, id); dirty.insert(*dependant, id, height);
} }
} }
} }
@@ -217,30 +295,20 @@ pub enum PassDirection {
AnyOrder, AnyOrder,
} }
type PassCallback<T, V> = type PassCallback = Box<dyn Fn(NodeId, &mut TreeStateView, &SendAnyMap) -> bool + Send + Sync>;
Box<dyn Fn(NodeId, &mut Tree<Node<T, V>>, &SendAnyMap) -> bool + Send + Sync>;
pub trait AnyMapLike { pub trait AnyMapLike<'a> {
fn get<T: Any>(&self) -> Option<&T>; fn get<T: Any>(self) -> Option<&'a T>;
fn get_mut<T: Any>(&mut self) -> Option<&mut T>;
} }
impl AnyMapLike for AnyMap { impl<'a> AnyMapLike<'a> for &'a AnyMap {
fn get<T: Any>(&self) -> Option<&T> { fn get<T: Any>(self) -> Option<&'a T> {
self.get() self.get()
} }
fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
self.get_mut()
}
} }
impl AnyMapLike for SendAnyMap { impl<'a> AnyMapLike<'a> for &'a SendAnyMap {
fn get<T: Any>(&self) -> Option<&T> { fn get<T: Any>(self) -> Option<&'a T> {
todo!()
}
fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
todo!() todo!()
} }
} }
@@ -250,8 +318,10 @@ pub trait Dependancy {
where where
Self: 'a; Self: 'a;
fn borrow_elements_from<T: AnyMapLike>(map: &T) -> Option<Self::ElementBorrowed<'_>>; fn borrow_elements_from<'a, T: AnyMapLike<'a> + Copy>(
fn type_ids() -> Vec<TypeId>; map: T,
) -> Option<Self::ElementBorrowed<'a>>;
fn type_ids() -> Box<[TypeId]>;
} }
macro_rules! impl_dependancy { macro_rules! impl_dependancy {
@@ -260,12 +330,12 @@ macro_rules! impl_dependancy {
type ElementBorrowed<'a> = ($(&'a $t,)*) where Self: 'a; type ElementBorrowed<'a> = ($(&'a $t,)*) where Self: 'a;
#[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<'a, T: AnyMapLike<'a> + Copy>(map: T) -> Option<Self::ElementBorrowed<'a>> {
Some(($(map.get::<$t>()?,)*)) Some(($(map.get::<$t>()?,)*))
} }
fn type_ids() -> Vec<TypeId> { fn type_ids() -> Box<[TypeId]> {
vec![$(TypeId::of::<$t>()),*] Box::new([$(TypeId::of::<$t>()),*])
} }
} }
}; };
@@ -289,96 +359,12 @@ impl_dependancy!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_dependancy!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); impl_dependancy!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_dependancy!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); impl_dependancy!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
#[derive(Debug, Clone, PartialEq, Eq, Default)] pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
pub struct DirtyNodes { tree: &mut RealDom<V>,
map: BTreeMap<u16, FxHashSet<NodeId>>,
}
impl DirtyNodes {
fn add_node(&mut self, node_id: NodeId) {
let node_id = node_id.0;
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;
}
}
fn is_empty(&self) -> bool {
self.passes_dirty.iter().all(|dirty| *dirty == 0)
}
fn pop(&mut self) -> Option<NodeId> {
let index = self.passes_dirty.iter().position(|dirty| *dirty != 0)?;
let passes = self.passes_dirty[index];
let node_id = passes.trailing_zeros();
let encoded = 1 << node_id;
self.passes_dirty[index] &= !encoded;
Some(NodeId((index * 64) + node_id as usize))
}
}
#[derive(Default)]
pub struct DirtyNodeStates {
dirty: FxDashMap<NodeId, FxHashSet<TypeId>>,
}
impl DirtyNodeStates {
pub fn insert(&self, pass_id: TypeId, node_id: NodeId) {
if let Some(mut dirty) = self.dirty.get_mut(&node_id) {
dirty.insert(pass_id);
} else {
let mut v = FxHashSet::default();
v.insert(pass_id);
self.dirty.insert(node_id, v);
}
}
fn all_dirty<T>(&self, pass_id: TypeId, dirty_nodes: &mut DirtyNodes, tree: &impl TreeView<T>) {
for entry in self.dirty.iter() {
let node_id = entry.key();
let dirty = entry.value();
if dirty.contains(&pass_id) {
dirty_nodes.insert(tree.height(*node_id).unwrap(), *node_id);
}
}
if values.is_empty() {
self.dirty.remove(&height);
}
Some((height, node_id))
}
fn pop_back(&mut self, pass_id: PassId) -> Option<(u16, NodeId)> {
let (&height, values) = self
.dirty
.iter_mut()
.rev()
.find(|(_, values)| values.contains_key(&pass_id))?;
let dirty = values.get_mut(&pass_id)?;
let node_id = dirty.pop()?;
if dirty.is_empty() {
values.remove(&pass_id);
}
if values.is_empty() {
self.dirty.remove(&height);
}
Some((height, node_id))
}
}
pub fn resolve_passes<T: AnyMapLike + State<V> + Send, V: FromAnyValue + Send>(
tree: &mut Tree<Node<T, V>>,
dirty_nodes: DirtyNodeStates, dirty_nodes: DirtyNodeStates,
passes: &[TypeErasedPass<T, V>],
ctx: SendAnyMap, ctx: SendAnyMap,
) -> FxDashSet<NodeId> { ) -> FxDashSet<NodeId> {
let dirty_states = Arc::new(dirty_nodes); let passes = &tree.passes;
let mut resolved_passes: FxHashSet<TypeId> = FxHashSet::default(); let mut resolved_passes: FxHashSet<TypeId> = FxHashSet::default();
let mut resolving = Vec::new(); let mut resolving = Vec::new();
let nodes_updated = Arc::new(FxDashSet::default()); let nodes_updated = Arc::new(FxDashSet::default());
@@ -399,21 +385,15 @@ pub fn resolve_passes<T: AnyMapLike + State<V> + Send, V: FromAnyValue + Send>(
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 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_view = tree.tree.state_views(
let tree_unbounded_mut = unsafe { &mut *(tree as *mut _) }; [pass.this_type_id],
let dirty_states = dirty_states.clone(); pass.combined_dependancy_type_ids.iter().copied(),
);
let dirty_nodes = dirty_nodes.clone();
let nodes_updated = nodes_updated.clone(); let nodes_updated = nodes_updated.clone();
let ctx = ctx.clone(); let ctx = ctx.clone();
s.spawn(move || { s.spawn(move || {
let mut dirty = DirtyNodes::default(); pass.resolve(tree_view, &dirty_nodes, &nodes_updated, &ctx);
dirty_states.all_dirty(pass_id, &mut dirty, tree_unbounded_mut);
pass.resolve(
tree_unbounded_mut,
dirty,
&dirty_states,
&nodes_updated,
&ctx,
);
}); });
} else { } else {
i += 1; i += 1;
+170 -198
View File
@@ -1,15 +1,14 @@
use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode}; use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::ops::{Index, IndexMut}; use std::any::Any;
use crate::node::{ use crate::node::{
ElementNode, FromAnyValue, Node, NodeData, NodeType, OwnedAttributeDiscription, ElementNode, FromAnyValue, NodeData, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
OwnedAttributeValue,
}; };
use crate::node_ref::{AttributeMask, NodeMask}; use crate::node_ref::{AttributeMask, NodeMask};
use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass}; use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
use crate::state::State; use crate::tree::{EntryBuilder, NodeId, Tree};
use crate::tree::{NodeId, Tree, TreeLike, TreeView, TreeViewMut};
use crate::{FxDashSet, SendAnyMap}; use crate::{FxDashSet, SendAnyMap};
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers. /// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
@@ -18,41 +17,36 @@ use crate::{FxDashSet, SendAnyMap};
/// ///
/// # Custom values /// # Custom values
/// To allow custom values to be passed into attributes implement FromAnyValue on a type that can represent your custom value and specify the V generic to be that type. If you have many different custom values, it can be useful to use a enum type to represent the varients. /// To allow custom values to be passed into attributes implement FromAnyValue on a type that can represent your custom value and specify the V generic to be that type. If you have many different custom values, it can be useful to use a enum type to represent the varients.
pub struct RealDom<S: State<V>, V: FromAnyValue = ()> { pub struct RealDom<V: FromAnyValue + Send = ()> {
tree: Tree<Node<S, V>>, pub(crate) tree: Tree,
/// a map from element id to real node id /// a map from element id to real node id
node_id_mapping: Vec<Option<NodeId>>, node_id_mapping: Vec<Option<NodeId>>,
nodes_listening: FxHashMap<String, FxHashSet<NodeId>>, nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
stack: Vec<NodeId>, stack: Vec<NodeId>,
templates: FxHashMap<String, Vec<NodeId>>, templates: FxHashMap<String, Vec<NodeId>>,
pub(crate) passes: Box<[TypeErasedPass<S, V>]>, pub(crate) passes: Box<[TypeErasedPass<V>]>,
pub(crate) nodes_updated: FxHashMap<NodeId, NodeMask>, pub(crate) nodes_updated: FxHashMap<NodeId, NodeMask>,
passes_updated: DirtyNodeStates, 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>, nodes_created: FxHashSet<NodeId>,
phantom: std::marker::PhantomData<V>,
} }
impl<S: State<V>, V: FromAnyValue> Default for RealDom<S, V> { impl<V: FromAnyValue + Send + Sync> RealDom<V> {
fn default() -> Self { pub fn new(mut passes: Box<[TypeErasedPass<V>]>) -> RealDom<V> {
Self::new() let tree = Tree::new();
} let root_id = tree.root();
} let root = tree.get_node(root_id);
let mut root_node: NodeData<V> = NodeData::new(NodeType::Element(ElementNode {
impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
pub fn new() -> RealDom<S, V> {
let mut root = Node::new(NodeType::Element(ElementNode {
tag: "Root".to_string(), tag: "Root".to_string(),
namespace: Some("Root".to_string()), namespace: Some("Root".to_string()),
attributes: FxHashMap::default(), attributes: FxHashMap::default(),
listeners: FxHashSet::default(), listeners: FxHashSet::default(),
})); }));
root.node_data.element_id = Some(ElementId(0)); root_node.element_id = Some(ElementId(0));
let mut tree = Tree::new(root); root_node.node_id = root_id;
let root_id = tree.root(); root.insert(root_node);
tree.get_mut(root_id).unwrap().node_data.node_id = root_id;
let mut passes = S::create_passes();
// resolve dependants for each pass // resolve dependants for each pass
for i in 1..passes.len() { for i in 1..passes.len() {
@@ -83,6 +77,7 @@ impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
parent_changed_nodes: FxHashSet::default(), parent_changed_nodes: FxHashSet::default(),
child_changed_nodes: FxHashSet::default(), child_changed_nodes: FxHashSet::default(),
nodes_created: FxHashSet::default(), nodes_created: FxHashSet::default(),
phantom: std::marker::PhantomData,
} }
} }
@@ -107,9 +102,9 @@ impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
} }
fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) { fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) {
let node = self.tree.get_mut(node_id).unwrap(); let mut node = self.tree.write::<NodeData>(node_id).unwrap();
let node_id = node.node_data.node_id; let node_id = node.node_id;
node.node_data.element_id = Some(element_id); node.element_id = Some(element_id);
if self.node_id_mapping.len() <= element_id.0 { if self.node_id_mapping.len() <= element_id.0 {
self.node_id_mapping.resize(element_id.0 + 1, None); self.node_id_mapping.resize(element_id.0 + 1, None);
} }
@@ -124,14 +119,21 @@ impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
current current
} }
fn create_node(&mut self, node: Node<S, V>, mark_dirty: bool) -> NodeId { fn create_node(
let node_id = self.tree.create_node(node); &mut self,
let node = self.tree.get_mut(node_id).unwrap(); mut node: NodeData<V>,
node.node_data.node_id = node_id; id: Option<ElementId>,
mark_dirty: bool,
) -> EntryBuilder<'_> {
let mut node_entry = self.tree.create_node();
let node_id = node_entry.id();
node.node_id = node_id;
node.element_id = id;
node_entry.insert(node);
if mark_dirty { if mark_dirty {
self.nodes_created.insert(node_id); self.nodes_created.insert(node_id);
} }
node_id node_entry
} }
fn add_child(&mut self, node_id: NodeId, child_id: NodeId) { fn add_child(&mut self, node_id: NodeId, child_id: NodeId) {
@@ -146,7 +148,7 @@ impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
attrs, attrs,
children, children,
} => { } => {
let node = Node::new(NodeType::Element(ElementNode { let node = NodeData::new(NodeType::Element(ElementNode {
tag: tag.to_string(), tag: tag.to_string(),
namespace: namespace.map(|s| s.to_string()), namespace: namespace.map(|s| s.to_string()),
attributes: attrs attributes: attrs
@@ -169,22 +171,22 @@ impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
.collect(), .collect(),
listeners: FxHashSet::default(), listeners: FxHashSet::default(),
})); }));
let node_id = self.create_node(node, true); let node_id = self.create_node(node, None, true).id();
for child in *children { for child in *children {
let child_id = self.create_template_node(child); let child_id = self.create_template_node(child);
self.add_child(node_id, child_id); self.add_child(node_id, child_id);
} }
node_id node_id
} }
TemplateNode::Text { text } => { TemplateNode::Text { text } => self
self.create_node(Node::new(NodeType::Text(text.to_string())), true) .create_node(NodeData::new(NodeType::Text(text.to_string())), None, true)
} .id(),
TemplateNode::Dynamic { .. } => { TemplateNode::Dynamic { .. } => self
self.create_node(Node::new(NodeType::Placeholder), true) .create_node(NodeData::new(NodeType::Placeholder), None, true)
} .id(),
TemplateNode::DynamicText { .. } => { TemplateNode::DynamicText { .. } => self
self.create_node(Node::new(NodeType::Text(String::new())), true) .create_node(NodeData::new(NodeType::Text(String::new())), None, true)
} .id(),
} }
} }
@@ -214,29 +216,26 @@ impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
self.set_element_id(self.load_child(path), id); self.set_element_id(self.load_child(path), id);
} }
CreatePlaceholder { id } => { CreatePlaceholder { id } => {
let node = Node::new(NodeType::Placeholder); let node = NodeData::new(NodeType::Placeholder);
let node_id = self.create_node(node, true); let node_id = self.create_node(node, None, true).id();
self.set_element_id(node_id, id); self.set_element_id(node_id, id);
self.stack.push(node_id); self.stack.push(node_id);
} }
CreateTextNode { value, id } => { CreateTextNode { value, id } => {
let node = Node::new(NodeType::Text(value.to_string())); let node_data = NodeData::new(NodeType::Text(value.to_string()));
let node_id = self.create_node(node, true); let node_id = self.create_node(node_data, None, true).id();
let node = self.tree.get_mut(node_id).unwrap(); self.set_element_id(node_id, id);
node.node_data.element_id = Some(id);
self.stack.push(node_id); self.stack.push(node_id);
} }
HydrateText { path, value, id } => { HydrateText { path, value, id } => {
let node_id = self.load_child(path); let node_id = self.load_child(path);
self.set_element_id(node_id, id); self.set_element_id(node_id, id);
let node = self.tree.get_mut(node_id).unwrap(); let mut node = self.get_mut(node_id).unwrap();
if let NodeType::Text(text) = &mut node.node_data.node_type { if let NodeTypeMut::Text(text) = node.node_type_mut() {
*text = value.to_string(); *text = value.to_string();
} else { } else {
node.node_data.node_type = NodeType::Text(value.to_string()); node.set_type(NodeType::Text(value.to_string()));
} }
self.mark_dirty(node_id, NodeMask::new().with_text());
} }
LoadTemplate { name, index, id } => { LoadTemplate { name, index, id } => {
let template_id = self.templates[name][index]; let template_id = self.templates[name][index];
@@ -350,15 +349,14 @@ impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
/// 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.
/// This can be useful to avoid creating duplicate events. /// This can be useful to avoid creating duplicate events.
pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node<S, V>> { pub fn get_listening_sorted(&self, event: &'static str) -> Vec<NodeId> {
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.get(*id).unwrap()).collect(); let mut listening: Vec<_> = nodes
listening.sort_by(|n1, n2| { .iter()
(self.tree.height(n1.node_data.node_id)) .map(|id| (*id, self.tree.height(*id).unwrap()))
.cmp(&self.tree.height(n2.node_data.node_id)) .collect();
.reverse() listening.sort_by(|(_, h1), (_, h2)| h1.cmp(h2).reverse());
}); listening.into_iter().map(|(id, _)| id).collect()
listening
} else { } else {
Vec::new() Vec::new()
} }
@@ -376,160 +374,94 @@ impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
} }
fn clone_node(&mut self, node_id: NodeId) -> NodeId { fn clone_node(&mut self, node_id: NodeId) -> NodeId {
let node = self.tree.get(node_id).unwrap(); let node = self.get(node_id).unwrap();
let new_node = Node { let new_node = node.node_data().clone();
state: node.state.clone(), let new_id = self.create_node(new_node, None, true).id();
node_data: node.node_data.clone(),
};
let new_id = self.create_node(new_node, true);
let self_ptr = self as *mut Self;
for child in self.tree.children_ids(node_id).unwrap() { for child in self.tree.children_ids(node_id).unwrap() {
unsafe { let child_id = self.clone_node(child);
// this is safe because no node has itself as a child self.add_child(new_id, child_id);
let self_mut = &mut *self_ptr;
let child_id = self_mut.clone_node(*child);
self_mut.add_child(new_id, child_id);
}
} }
new_id new_id
} }
fn root(&self) -> NodeId {
self.tree.root()
}
fn get(&self, id: NodeId) -> Option<NodeRef<'_, V>> {
self.tree.contains(id).then(|| NodeRef { id, dom: &self })
}
pub fn get_mut(&mut self, id: NodeId) -> Option<NodeMut<'_, V>> { pub fn get_mut(&mut self, id: NodeId) -> Option<NodeMut<'_, V>> {
self.tree.get_mut(id).map(|node| NodeMut { self.tree.contains(id).then(|| NodeMut {
node: &mut node.node_data, id,
dirty: NodeMask::new(), dirty: NodeMask::new(),
nodes_updated: &mut self.nodes_updated, dom: self,
}) })
} }
/// WARNING: This escapes the reactive system that the real dom uses. Any changes made with this method will not trigger updates in states when [RealDom::update_state] is called. /// WARNING: This escapes the reactive system that the real dom uses. Any changes made with this method will not trigger updates in states when [RealDom::update_state] is called.
pub fn get_mut_raw(&mut self, id: NodeId) -> Option<&mut Node<S, V>> { pub fn get_mut_raw(&mut self, id: NodeId) -> Option<&mut NodeData<V>> {
self.tree.get_mut(id) self.tree.write(id)
} }
}
impl<S: State<V> + Send, V: FromAnyValue + Send> RealDom<S, V> {
/// 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,
ctx: SendAnyMap, ctx: SendAnyMap,
) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) { ) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
let passes = &self.passes;
let dirty_nodes = std::mem::take(&mut self.passes_updated); 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 (&node, 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(node) { if let Some(height) = self.tree.height(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, node); dirty_nodes.insert(pass.this_type_id, node, height);
} }
} }
} }
} }
for node in std::mem::take(&mut self.child_changed_nodes) { 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 // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if self.tree.contains(node) { if let Some(height) = self.tree.height(node) {
for pass in &*self.passes { for pass in &*self.passes {
if pass.child_dependant { if pass.child_dependant {
dirty_nodes.insert(pass.this_type_id, node); dirty_nodes.insert(pass.this_type_id, node, height);
} }
} }
} }
} }
for node in std::mem::take(&mut self.parent_changed_nodes) { 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 // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if self.tree.contains(node) { if let Some(height) = self.tree.height(node) {
for pass in &*self.passes { for pass in &*self.passes {
if pass.parent_dependant { if pass.parent_dependant {
dirty_nodes.insert(pass.this_type_id, node); dirty_nodes.insert(pass.this_type_id, node, height);
} }
} }
} }
} }
for node in std::mem::take(&mut self.nodes_created) { 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 // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if self.tree.contains(node) { if let Some(height) = self.tree.height(node) {
for pass in &*self.passes { for pass in &*self.passes {
dirty_nodes.insert(pass.this_type_id, node); dirty_nodes.insert(pass.this_type_id, node, height);
} }
} }
} }
let tree = &mut self.tree; (resolve_passes(self, dirty_nodes, ctx), nodes_updated)
(
resolve_passes(tree, dirty_nodes, passes, ctx),
nodes_updated,
)
}
}
impl<S: State<V>, V: FromAnyValue> TreeView<Node<S, V>> for RealDom<S, V> {
type Iterator<'a> = <Tree<Node<S, V>> as TreeView<Node<S, V>>>::Iterator<'a>;
fn root(&self) -> NodeId {
self.tree.root()
} }
fn get(&self, id: NodeId) -> Option<&Node<S, V>> { fn remove(&mut self, id: NodeId) {
self.tree.get(id)
}
fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>> {
self.tree.children(id)
}
fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
self.tree.children_ids(id)
}
fn parent(&self, id: NodeId) -> Option<&Node<S, V>> {
self.tree.parent(id)
}
fn parent_id(&self, id: NodeId) -> Option<NodeId> {
self.tree.parent_id(id)
}
fn height(&self, id: NodeId) -> Option<u16> {
self.tree.height(id)
}
fn size(&self) -> usize {
self.tree.size()
}
}
impl<S: State<V>, V: FromAnyValue> TreeLike<Node<S, V>> for RealDom<S, V> {
fn create_node(&mut self, node: Node<S, V>) -> NodeId {
let id = self.tree.create_node(node);
self.tree.get_mut(id).unwrap().node_data.node_id = id;
self.nodes_created.insert(id);
id
}
fn add_child(&mut self, parent: NodeId, child: NodeId) {
// mark the parent's children changed
self.mark_child_changed(parent);
// mark the child's parent changed
self.mark_parent_added_or_removed(child);
self.tree.add_child(parent, child);
}
fn remove(&mut self, id: NodeId) -> Option<Node<S, V>> {
if let Some(parent_id) = self.tree.parent_id(id) { if let Some(parent_id) = self.tree.parent_id(id) {
self.mark_child_changed(parent_id); self.mark_child_changed(parent_id);
} }
self.tree.remove(id) self.tree.remove(id)
} }
fn remove_all_children(&mut self, id: NodeId) -> Vec<Node<S, V>> {
self.mark_child_changed(id);
self.tree.remove_all_children(id)
}
fn replace(&mut self, old: NodeId, new: NodeId) { fn replace(&mut self, old: NodeId, new: NodeId) {
if let Some(parent_id) = self.tree.parent_id(old) { if let Some(parent_id) = self.tree.parent_id(old) {
self.mark_child_changed(parent_id); self.mark_child_changed(parent_id);
@@ -555,68 +487,108 @@ impl<S: State<V>, V: FromAnyValue> TreeLike<Node<S, V>> for RealDom<S, V> {
} }
} }
impl<S: State<V> + Send, V: FromAnyValue> Index<ElementId> for RealDom<S, V> { // impl<V: FromAnyValue> Index<ElementId> for RealDom<V> {
type Output = Node<S, V>; // type Output = Node<V>;
fn index(&self, id: ElementId) -> &Self::Output { // fn index(&self, id: ElementId) -> &Self::Output {
self.tree.get(self.element_to_node_id(id)).unwrap() // self.tree.get(self.element_to_node_id(id)).unwrap()
// }
// }
// impl<V: FromAnyValue> Index<NodeId> for RealDom<V> {
// type Output = Node<V>;
// fn index(&self, idx: NodeId) -> &Self::Output {
// self.tree.get(idx).unwrap()
// }
// }
// impl<V: FromAnyValue> IndexMut<ElementId> for RealDom<V> {
// fn index_mut(&mut self, id: ElementId) -> &mut Self::Output {
// self.tree.get_mut(self.element_to_node_id(id)).unwrap()
// }
// }
// impl<V: FromAnyValue> IndexMut<NodeId> for RealDom<V> {
// fn index_mut(&mut self, idx: NodeId) -> &mut Self::Output {
// self.tree.get_mut(idx).unwrap()
// }
// }
pub struct NodeRef<'a, V: FromAnyValue + Send = ()> {
id: NodeId,
dom: &'a RealDom<V>,
}
impl<'a, V: FromAnyValue + Send> NodeRef<'a, V> {
pub fn node_data(&self) -> &NodeData<V> {
self.read().unwrap()
} }
}
impl<S: State<V> + Send, V: FromAnyValue> Index<NodeId> for RealDom<S, V> {
type Output = Node<S, V>;
fn index(&self, idx: NodeId) -> &Self::Output {
self.tree.get(idx).unwrap()
}
}
impl<S: State<V> + Send, V: FromAnyValue> IndexMut<ElementId> for RealDom<S, V> {
fn index_mut(&mut self, id: ElementId) -> &mut Self::Output {
self.tree.get_mut(self.element_to_node_id(id)).unwrap()
}
}
impl<S: State<V> + Send, V: FromAnyValue> IndexMut<NodeId> for RealDom<S, V> {
fn index_mut(&mut self, idx: NodeId) -> &mut Self::Output {
self.tree.get_mut(idx).unwrap()
}
}
pub struct NodeMut<'a, V: FromAnyValue = ()> {
node: &'a mut NodeData<V>,
dirty: NodeMask,
nodes_updated: &'a mut FxHashMap<NodeId, NodeMask>,
}
impl<'a, V: FromAnyValue> NodeMut<'a, V> {
pub fn node_type(&self) -> &NodeType<V> { pub fn node_type(&self) -> &NodeType<V> {
&self.node.node_type &self.node_data().node_type
}
pub fn read<T: Any>(&self) -> Option<&T> {
self.dom.tree.read(self.id)
}
}
pub struct NodeMut<'a, V: FromAnyValue + Send = ()> {
id: NodeId,
dom: &'a mut RealDom<V>,
dirty: NodeMask,
}
impl<'a, V: FromAnyValue + Send> NodeMut<'a, V> {
fn node_data(&self) -> &NodeData<V> {
self.read().unwrap()
}
fn node_data_mut(&mut self) -> &mut NodeData<V> {
self.dom.tree.write(self.id).unwrap()
}
pub fn node_type(&self) -> &NodeType<V> {
&self.node_data().node_type
} }
pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> { pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
match &mut self.node.node_type { let Self { id, dom, dirty } = self;
NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { let node_type = &mut dom.tree.write::<NodeData<V>>(*id).unwrap().node_type;
element, match node_type {
dirty: &mut self.dirty, NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { element, dirty }),
}),
NodeType::Text(text) => { NodeType::Text(text) => {
self.dirty.set_text(); dirty.set_text();
NodeTypeMut::Text(text) NodeTypeMut::Text(text)
} }
NodeType::Placeholder => NodeTypeMut::Placeholder, NodeType::Placeholder => NodeTypeMut::Placeholder,
} }
} }
pub fn set_type(&mut self, new: NodeType<V>) {
self.node_data_mut().node_type = new;
self.dirty = NodeMask::ALL;
}
pub fn read<T: Any>(&self) -> Option<&T> {
self.dom.tree.read(self.id)
}
pub fn write<T: Any>(&mut self) -> Option<&T> {
todo!("get_mut with mark as dirty")
}
} }
impl<V: FromAnyValue> Drop for NodeMut<'_, V> { impl<V: FromAnyValue + Send> Drop for NodeMut<'_, V> {
fn drop(&mut self) { fn drop(&mut self) {
let node_id = self.node.node_id; let node_id = self.node_data().node_id;
let mask = std::mem::take(&mut self.dirty); let mask = std::mem::take(&mut self.dirty);
if let Some(node) = self.nodes_updated.get_mut(&node_id) { let nodes_updated = &mut self.dom.nodes_updated;
if let Some(node) = nodes_updated.get_mut(&node_id) {
*node = node.union(&mask); *node = node.union(&mask);
} else { } else {
self.nodes_updated.insert(node_id, mask); nodes_updated.insert(node_id, mask);
} }
} }
} }
-46
View File
@@ -1,46 +0,0 @@
use crate::{
node::FromAnyValue,
passes::{AnyMapLike, TypeErasedPass},
};
use std::cmp::Ordering;
/// Join two sorted iterators
pub(crate) fn union_ordered_iter<'a>(
s_iter: impl Iterator<Item = &'a str>,
o_iter: impl Iterator<Item = &'a str>,
new_len_guess: usize,
) -> Vec<String> {
let mut s_peekable = s_iter.peekable();
let mut o_peekable = o_iter.peekable();
let mut v = Vec::with_capacity(new_len_guess);
while let Some(s_i) = s_peekable.peek() {
while let Some(o_i) = o_peekable.peek() {
match o_i.cmp(s_i) {
Ordering::Greater => {
break;
}
Ordering::Less => {
v.push(o_peekable.next().unwrap().to_string());
}
Ordering::Equal => {
o_peekable.next();
break;
}
}
}
v.push(s_peekable.next().unwrap().to_string());
}
for o_i in o_peekable {
v.push(o_i.to_string());
}
for w in v.windows(2) {
debug_assert!(w[1] > w[0]);
}
v
}
/// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
pub trait State<V: FromAnyValue = ()>: Default + Clone + AnyMapLike + 'static {
#[doc(hidden)]
fn create_passes() -> Box<[TypeErasedPass<Self, V>]>;
}
+174 -221
View File
@@ -7,17 +7,19 @@ use std::collections::VecDeque;
use std::fmt::Debug; use std::fmt::Debug;
use std::hash::BuildHasherDefault; use std::hash::BuildHasherDefault;
#[derive(PartialEq, Eq, Clone, Copy, Debug)] use crate::{AnyMapLike, Dependancy};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Hash)]
pub struct NodeId(pub usize); pub struct NodeId(pub usize);
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
pub struct Node { pub(crate) struct Node {
parent: Option<NodeId>, parent: Option<NodeId>,
children: Vec<NodeId>, children: Vec<NodeId>,
height: u16, height: u16,
} }
pub struct NodeView<'a> { pub(crate) struct NodeView<'a> {
tree: &'a Tree, tree: &'a Tree,
id: NodeId, id: NodeId,
} }
@@ -27,25 +29,21 @@ impl NodeView<'_> {
where where
T: Any, T: Any,
{ {
self.tree.nodes.get_slab_mut::<T>().insert(self.id, data); self.tree.nodes.write_slab::<T>().insert(self.id, data);
} }
pub fn get<T>(&self) -> MappedRwLockReadGuard<'_, T> pub fn get<T>(&self) -> &T
where where
T: Any, T: Any,
{ {
MappedRwLockReadGuard::map(self.tree.nodes.get_slab::<T>(), |slab| { self.tree.nodes.read_slab::<T>().get(self.id).unwrap()
slab.get(self.id).unwrap()
})
} }
pub fn get_mut<T>(&self) -> MappedRwLockWriteGuard<'_, T> pub fn get_mut<T>(&self) -> &mut T
where where
T: Any, T: Any,
{ {
MappedRwLockWriteGuard::map(self.tree.nodes.get_slab_mut::<T>(), |slab| { self.tree.nodes.write_slab::<T>().get_mut(self.id).unwrap()
slab.get_mut(self.id).unwrap()
})
} }
pub fn height(&self) -> u16 { pub fn height(&self) -> u16 {
@@ -66,7 +64,7 @@ impl NodeView<'_> {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Tree { pub(crate) struct Tree {
nodes: AnySlab, nodes: AnySlab,
root: NodeId, root: NodeId,
} }
@@ -84,20 +82,20 @@ impl Tree {
Self { nodes, root } Self { nodes, root }
} }
fn node_slab(&self) -> MappedRwLockReadGuard<'_, SlabStorage<Node>> { fn node_slab(&self) -> &SlabStorage<Node> {
self.nodes.get_slab() self.nodes.read_slab()
} }
pub fn get_node_data(&self, id: NodeId) -> MappedRwLockReadGuard<'_, Node> { pub fn get_node_data(&self, id: NodeId) -> &Node {
MappedRwLockReadGuard::map(self.node_slab(), |slab| slab.get(id).unwrap()) self.node_slab().get(id).unwrap()
} }
fn node_slab_mut(&self) -> MappedRwLockWriteGuard<'_, SlabStorage<Node>> { fn node_slab_mut(&self) -> &mut SlabStorage<Node> {
self.nodes.get_slab_mut() self.nodes.write_slab()
} }
pub fn get_node_data_mut(&self, id: NodeId) -> MappedRwLockWriteGuard<'_, Node> { pub fn get_node_data_mut(&self, id: NodeId) -> &mut Node {
MappedRwLockWriteGuard::map(self.node_slab_mut(), |slab| slab.get_mut(id).unwrap()) self.node_slab_mut().get_mut(id).unwrap()
} }
pub fn remove(&mut self, id: NodeId) { pub fn remove(&mut self, id: NodeId) {
@@ -131,7 +129,7 @@ impl Tree {
} }
} }
pub fn create_node(&mut self) -> Entry<'_> { pub fn create_node(&mut self) -> EntryBuilder<'_> {
let mut node = self.nodes.insert(); let mut node = self.nodes.insert();
node.insert(Node { node.insert(Node {
parent: None, parent: None,
@@ -206,7 +204,7 @@ impl Tree {
self.set_height(new_id, height); self.set_height(new_id, height);
} }
pub fn insert<T: Any>(&mut self, id: NodeId, value: T) { pub fn insert<T: Any + Send + Sync>(&mut self, id: NodeId, value: T) {
self.nodes.add(id, value); self.nodes.add(id, value);
} }
@@ -214,42 +212,60 @@ impl Tree {
self.nodes.len() self.nodes.len()
} }
pub fn state_view<T: Any>(&self) -> TreeStateView<'_, T> { pub fn state_views(
&self,
immutable: impl IntoIterator<Item = TypeId>,
mutable: impl IntoIterator<Item = TypeId>,
) -> TreeStateView<'_> {
TreeStateView { TreeStateView {
nodes_data: self.node_slab(), nodes_data: self.node_slab(),
nodes: self.nodes.get_slab(), nodes: immutable
.into_iter()
.map(|id| (id, MaybeRead::Read(self.nodes.data.get(&id).unwrap())))
.chain(
mutable
.into_iter()
.map(|id| (id, MaybeRead::Write(self.nodes.data.get_mut(&id).unwrap()))),
)
.collect(),
root: self.root, root: self.root,
} }
} }
pub fn state_view_mut<T: Any>(&mut self) -> TreeStateViewMut<'_, T> { pub fn read<T: Any>(&self, id: NodeId) -> Option<&T> {
TreeStateViewMut { self.nodes.read_slab().get(id)
nodes_data: self.node_slab(),
nodes: self.nodes.get_slab_mut(),
root: self.root,
}
} }
}
impl NodeDataView for Tree { pub fn write<T: Any>(&mut self, id: NodeId) -> Option<&mut T> {
fn root(&self) -> NodeId { self.nodes.write_slab().get_mut(id)
}
pub fn get_node(&self, id: NodeId) -> NodeView<'_> {
NodeView { tree: self, id }
}
pub fn contains(&self, id: NodeId) -> bool {
self.nodes.contains(id)
}
pub fn root(&self) -> NodeId {
self.root self.root
} }
fn parent_id(&self, id: NodeId) -> Option<NodeId> { pub fn parent_id(&self, id: NodeId) -> Option<NodeId> {
self.get_node_data(id).parent self.get_node_data(id).parent
} }
fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> { pub fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> {
Some(self.get_node_data(id).children.clone()) Some(self.get_node_data(id).children.clone())
} }
fn height(&self, id: NodeId) -> Option<u16> { pub fn height(&self, id: NodeId) -> Option<u16> {
Some(self.get_node_data(id).height) Some(self.get_node_data(id).height)
} }
} }
pub trait NodeDataView { pub(crate) trait NodeDataView {
fn root(&self) -> NodeId; fn root(&self) -> NodeId;
fn parent_id(&self, id: NodeId) -> Option<NodeId>; fn parent_id(&self, id: NodeId) -> Option<NodeId>;
@@ -259,7 +275,7 @@ pub trait NodeDataView {
fn height(&self, id: NodeId) -> Option<u16>; fn height(&self, id: NodeId) -> Option<u16>;
} }
pub trait TreeView<T>: Sized + NodeDataView { trait TreeView<T>: Sized + NodeDataView {
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 {
@@ -298,7 +314,7 @@ pub trait TreeView<T>: Sized + NodeDataView {
} }
} }
pub trait TreeViewMut<T>: Sized + TreeView<T> { trait TreeViewMut<T>: Sized + TreeView<T> {
fn get_mut(&mut self, id: NodeId) -> Option<&mut T>; fn get_mut(&mut self, id: NodeId) -> Option<&mut T>;
unsafe fn get_mut_unchecked(&mut self, id: NodeId) -> &mut T { unsafe fn get_mut_unchecked(&mut self, id: NodeId) -> &mut T {
@@ -357,175 +373,91 @@ pub trait TreeViewMut<T>: Sized + TreeView<T> {
} }
} }
pub trait TreeLike { enum MaybeRead<'a> {
fn create_node(&mut self) -> Entry; Read(&'a Box<dyn AnySlabStorageImpl>),
Write(&'a mut Box<dyn AnySlabStorageImpl>),
fn add_child(&mut self, parent: NodeId, child: NodeId);
fn remove(&mut self, id: NodeId);
fn replace(&mut self, old: NodeId, new: NodeId);
fn insert_before(&mut self, id: NodeId, new: NodeId);
fn insert_after(&mut self, id: NodeId, new: NodeId);
} }
pub struct TreeStateView<'a, T> { #[derive(Clone, Copy)]
nodes_data: MappedRwLockReadGuard<'a, SlabStorage<Node>>, struct TreeStateViewEntry<'a> {
nodes: MappedRwLockReadGuard<'a, SlabStorage<T>>, view: &'a TreeStateView<'a>,
id: NodeId,
}
impl<'a> AnyMapLike<'a> for TreeStateViewEntry<'a> {
fn get<T: Any>(self) -> Option<&'a T> {
self.view.get_slab().and_then(|slab| slab.get(self.id))
}
}
pub struct TreeStateView<'a> {
nodes_data: &'a SlabStorage<Node>,
nodes: hashbrown::HashMap<TypeId, MaybeRead<'a>, BuildHasherDefault<FxHasher>>,
root: NodeId, root: NodeId,
} }
pub struct TreeStateViewMut<'a, T> { impl<'a> TreeStateView<'a> {
nodes_data: MappedRwLockReadGuard<'a, SlabStorage<Node>>, fn get_slab<T: Any>(&self) -> Option<&SlabStorage<T>> {
nodes: MappedRwLockWriteGuard<'a, SlabStorage<T>>, self.nodes
root: NodeId, .get(&TypeId::of::<T>())
} .and_then(|gaurd| match gaurd {
MaybeRead::Read(gaurd) => gaurd.as_any().downcast_ref::<SlabStorage<T>>(),
MaybeRead::Write(gaurd) => gaurd.as_any().downcast_ref::<SlabStorage<T>>(),
})
}
fn get_slab_mut<T: Any>(&mut self) -> Option<&mut SlabStorage<T>> {
self.nodes
.get_mut(&TypeId::of::<T>())
.and_then(|gaurd| match gaurd {
MaybeRead::Read(gaurd) => None,
MaybeRead::Write(gaurd) => gaurd.as_any_mut().downcast_mut::<SlabStorage<T>>(),
})
}
impl<'a, T> NodeDataView for TreeStateView<'a, T> {
fn root(&self) -> NodeId { fn root(&self) -> NodeId {
self.root self.root
} }
fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> { pub fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> {
self.nodes_data.get(id).map(|node| node.children.clone()) self.nodes_data.get(id).map(|node| node.children.clone())
} }
fn parent_id(&self, id: NodeId) -> Option<NodeId> { pub fn parent_id(&self, id: NodeId) -> Option<NodeId> {
self.nodes_data.get(id).and_then(|node| node.parent) self.nodes_data.get(id).and_then(|node| node.parent)
} }
fn height(&self, id: NodeId) -> Option<u16> { pub fn height(&self, id: NodeId) -> Option<u16> {
self.nodes_data.get(id).map(|n| n.height) self.nodes_data.get(id).map(|n| n.height)
} }
}
impl<'a, T> TreeView<T> for TreeStateView<'a, T> { pub fn get<T: Dependancy>(&self, id: NodeId) -> Option<T::ElementBorrowed<'_>> {
fn get(&self, id: NodeId) -> Option<&T> { T::borrow_elements_from(self.entry(id))
self.nodes.get(id)
} }
fn children(&self, id: NodeId) -> Option<Vec<&T>> { pub fn get_single<T: Any>(&self, id: NodeId) -> Option<&T> {
self.get_slab().and_then(|slab| slab.get(id))
}
pub fn get_mut<T: Any>(&mut self, id: NodeId) -> Option<&mut T> {
self.get_slab_mut().and_then(|slab| slab.get_mut(id))
}
fn entry(&self, id: NodeId) -> TreeStateViewEntry<'_> {
TreeStateViewEntry { view: self, id }
}
pub fn children<T: Dependancy>(&self, id: NodeId) -> Option<Vec<T::ElementBorrowed<'_>>> {
let ids = self.children_ids(id); let ids = self.children_ids(id);
ids.map(|ids| ids.iter().map(|id| self.get_unchecked(*id)).collect()) ids.and_then(|ids| {
} ids.iter()
.map(|id| T::borrow_elements_from(self.entry(*id)))
fn parent(&self, id: NodeId) -> Option<&T> { .collect()
self.nodes_data
.get(id)
.and_then(|node| node.parent.map(|id| self.nodes.get(id).unwrap()))
}
fn get_unchecked(&self, id: NodeId) -> &T {
unsafe { &self.nodes.get_unchecked(id) }
}
}
impl<'a, T> NodeDataView for TreeStateViewMut<'a, T> {
fn root(&self) -> NodeId {
self.root
}
fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> {
self.nodes_data.get(id).map(|node| node.children.clone())
}
fn parent_id(&self, id: NodeId) -> Option<NodeId> {
self.nodes_data.get(id).and_then(|node| node.parent)
}
fn height(&self, id: NodeId) -> Option<u16> {
self.nodes_data.get(id).map(|n| n.height)
}
}
impl<'a, T> TreeView<T> for TreeStateViewMut<'a, T> {
fn get(&self, id: NodeId) -> Option<&T> {
self.nodes.get(id)
}
fn children(&self, id: NodeId) -> Option<Vec<&T>> {
let ids = self.children_ids(id);
ids.map(|ids| ids.iter().map(|id| self.get_unchecked(*id)).collect())
}
fn parent(&self, id: NodeId) -> Option<&T> {
self.nodes_data
.get(id)
.and_then(|node| node.parent.map(|id| self.nodes.get(id).unwrap()))
}
fn get_unchecked(&self, id: NodeId) -> &T {
unsafe { &self.nodes.get_unchecked(id) }
}
}
impl<'a, T> TreeViewMut<T> for TreeStateViewMut<'a, T> {
fn get_mut(&mut self, id: NodeId) -> Option<&mut T> {
self.nodes.get_mut(id)
}
fn parent_mut(&mut self, id: NodeId) -> Option<&mut T> {
let parent_id = self.parent_id(id)?;
unsafe { Some(self.get_mut_unchecked(parent_id)) }
}
fn children_mut(&mut self, id: NodeId) -> Option<Vec<&mut T>> {
// Safety: No node has itself as a parent.
if let Some(children_ids) = self.children_ids(id) {
let children_ids = children_ids.to_vec();
unsafe {
self.nodes
.get_many_mut_unchecked(children_ids.into_iter().rev().map(|id| id))
}
} else {
None
}
}
unsafe fn get_mut_unchecked(&mut self, id: NodeId) -> &mut T {
unsafe { self.nodes.get_unchecked_mut(id) }
}
fn node_parent_mut(&mut self, id: NodeId) -> Option<(&mut T, Option<&mut T>)> {
if let Some(parent_id) = self.parent_id(id) {
self.nodes
.get2_mut(id, parent_id)
.map(|(node, parent)| (node, Some(parent)))
} else {
self.nodes.get_mut(id).map(|node| (node, None))
}
}
fn node_parent_children_mut(
&mut self,
id: NodeId,
) -> Option<(&mut T, Option<&mut T>, Option<Vec<&mut T>>)> {
// Safety: No node has itself as a parent.
let unbounded_self = unsafe { &mut *(self as *mut Self) };
self.node_parent_mut(id).map(move |(node, parent)| {
let children = unbounded_self.children_mut(id);
(node, parent, children)
}) })
} }
fn parent_child_mut(&mut self, id: NodeId) -> Option<(&mut T, Vec<&mut T>)> { pub fn parent<T: Dependancy>(&self, id: NodeId) -> Option<T::ElementBorrowed<'_>> {
// Safety: No node will appear as a child twice T::borrow_elements_from(self.entry(id))
if let Some(children_ids) = self.children_ids(id) {
debug_assert!(!children_ids.iter().any(|child_id| *child_id == id));
let mut borrowed = unsafe {
let as_vec = children_ids.to_vec();
self.nodes
.get_many_mut_unchecked(
as_vec.into_iter().map(|id| id).chain(std::iter::once(id)),
)
.unwrap()
};
let node = borrowed.pop().unwrap();
Some((node, borrowed))
} else {
None
}
} }
} }
@@ -727,7 +659,7 @@ fn get_node_children_mut() {
} }
#[derive(Debug)] #[derive(Debug)]
struct SlabStorage<T> { pub(crate) struct SlabStorage<T> {
data: Vec<Option<T>>, data: Vec<Option<T>>,
} }
@@ -737,7 +669,7 @@ impl<T> Default for SlabStorage<T> {
} }
} }
trait AnySlabStorageImpl: Any { trait AnySlabStorageImpl: Any + Send + Sync {
fn remove(&mut self, id: NodeId); fn remove(&mut self, id: NodeId);
fn as_any(&self) -> &dyn Any; fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any; fn as_any_mut(&mut self) -> &mut dyn Any;
@@ -806,7 +738,7 @@ impl<T> SlabStorage<T> {
} }
} }
impl<T: 'static> AnySlabStorageImpl for SlabStorage<T> { impl<T: 'static + Send + Sync> AnySlabStorageImpl for SlabStorage<T> {
fn remove(&mut self, id: NodeId) { fn remove(&mut self, id: NodeId) {
self.data[id.0].take(); self.data[id.0].take();
} }
@@ -820,12 +752,9 @@ impl<T: 'static> AnySlabStorageImpl for SlabStorage<T> {
} }
} }
struct AnySlab { pub(crate) struct AnySlab {
data: hashbrown::HashMap< data: hashbrown::HashMap<TypeId, Box<dyn AnySlabStorageImpl>, BuildHasherDefault<FxHasher>>,
TypeId, filled: Vec<bool>,
RwLock<Box<dyn AnySlabStorageImpl>>,
BuildHasherDefault<FxHasher>,
>,
free: VecDeque<NodeId>, free: VecDeque<NodeId>,
len: usize, len: usize,
} }
@@ -850,80 +779,104 @@ impl AnySlab {
fn new() -> Self { fn new() -> Self {
Self { Self {
data: Default::default(), data: Default::default(),
filled: Default::default(),
free: VecDeque::new(), free: VecDeque::new(),
len: 0, len: 0,
} }
} }
fn try_get_slab<T: Any>(&self) -> Option<MappedRwLockReadGuard<'_, SlabStorage<T>>> { fn try_read_slab<T: Any>(&self) -> Option<&SlabStorage<T>> {
self.data self.data
.get(&TypeId::of::<T>()) .get(&TypeId::of::<T>())
.map(|x| RwLockReadGuard::map(x.read(), |x| x.as_any().downcast_ref().unwrap())) .map(|x| x.as_any().downcast_ref().unwrap())
} }
fn get_slab<T: Any>(&self) -> MappedRwLockReadGuard<'_, SlabStorage<T>> { fn read_slab<T: Any>(&self) -> &SlabStorage<T> {
self.try_get_slab().unwrap() self.try_read_slab().unwrap()
} }
fn try_get_slab_mut<T: Any>(&self) -> Option<MappedRwLockWriteGuard<'_, SlabStorage<T>>> { fn try_write_slab<T: Any>(&self) -> Option<&mut SlabStorage<T>> {
self.data self.data
.get(&TypeId::of::<T>()) .get(&TypeId::of::<T>())
.map(|x| RwLockWriteGuard::map(x.write(), |x| x.as_any_mut().downcast_mut().unwrap())) .map(|x| x.as_any_mut().downcast_mut().unwrap())
} }
fn get_slab_mut<T: Any>(&self) -> MappedRwLockWriteGuard<'_, SlabStorage<T>> { fn write_slab<T: Any>(&self) -> &mut SlabStorage<T> {
self.try_get_slab_mut().unwrap() self.try_write_slab().unwrap()
} }
fn get_or_insert_slab_mut<T: Any>(&mut self) -> MappedRwLockWriteGuard<'_, SlabStorage<T>> { fn get_slab_mut_borrow<T: Any>(&mut self) -> &mut SlabStorage<T> {
RwLockWriteGuard::map( self.data
self.data .get_mut(&TypeId::of::<T>())
.entry(TypeId::of::<T>()) .unwrap()
.or_insert_with(|| RwLock::new(Box::new(SlabStorage::<T>::default()))) .as_any_mut()
.write(), .downcast_mut()
|x| x.as_any_mut().downcast_mut().unwrap(), .unwrap()
)
} }
fn insert(&mut self) -> Entry<'_> { fn get_or_insert_slab_mut<T: Any + Send + Sync>(&mut self) -> &mut SlabStorage<T> {
self.data
.entry(TypeId::of::<T>())
.or_insert_with(|| Box::new(SlabStorage::<T>::default()))
.as_any_mut()
.downcast_mut()
.unwrap()
}
fn insert(&mut self) -> EntryBuilder<'_> {
let id = if let Some(id) = self.free.pop_front() { let id = if let Some(id) = self.free.pop_front() {
self.filled[id.0] = true;
id id
} else { } else {
let id = self.len; let id = self.len;
self.filled.push(true);
self.len += 1; self.len += 1;
NodeId(id) NodeId(id)
}; };
Entry { id, inner: self } EntryBuilder { id, inner: self }
} }
fn add<T: Any>(&mut self, id: NodeId, value: T) { fn add<T: Any + Send + Sync>(&mut self, id: NodeId, value: T) {
self.get_or_insert_slab_mut().insert(id, value); self.get_or_insert_slab_mut().insert(id, value);
} }
fn remove(&mut self, id: NodeId) { fn remove(&mut self, id: NodeId) {
for slab in self.data.values_mut() { for slab in self.data.values_mut() {
slab.write().remove(id); slab.remove(id);
} }
self.filled[id.0] = true;
self.free.push_back(id); self.free.push_back(id);
} }
fn len(&self) -> usize { fn len(&self) -> usize {
self.len - self.free.len() self.len - self.free.len()
} }
fn contains(&self, id: NodeId) -> bool {
self.filled.get(id.0).copied().unwrap_or_default()
}
} }
pub struct Entry<'a> { pub struct EntryBuilder<'a> {
id: NodeId, id: NodeId,
inner: &'a mut AnySlab, inner: &'a mut AnySlab,
} }
impl Entry<'_> { impl EntryBuilder<'_> {
pub fn insert<T: Any>(&mut self, value: T) { pub fn insert<T: Any + Send + Sync>(&mut self, value: T) {
self.inner self.inner
.get_or_insert_slab_mut::<T>() .get_or_insert_slab_mut::<T>()
.insert(self.id, value); .insert(self.id, value);
} }
pub fn get<T: Any>(&self) -> Option<&T> {
self.inner.read_slab().get(self.id)
}
pub fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
self.inner.write_slab().get_mut(self.id)
}
pub fn remove(self) { pub fn remove(self) {
self.inner.remove(self.id); self.inner.remove(self.id);
} }
@@ -946,7 +899,7 @@ fn remove() {
slab.remove(node1_id); slab.remove(node1_id);
assert!(slab.get_slab::<i32>().get(node1_id).is_none()); assert!(slab.read_slab::<i32>().get(node1_id).is_none());
assert_eq!(slab.len(), 1); assert_eq!(slab.len(), 1);
} }
@@ -966,7 +919,7 @@ fn get_many_mut_unchecked() {
println!("ids: {:#?}", [parent, child, grandchild]); println!("ids: {:#?}", [parent, child, grandchild]);
{ {
let mut i32_slab = slab.get_slab_mut::<i32>(); let mut i32_slab = slab.write_slab::<i32>();
let all = let all =
unsafe { i32_slab.get_many_mut_unchecked([parent, child, grandchild].into_iter()) } unsafe { i32_slab.get_many_mut_unchecked([parent, child, grandchild].into_iter()) }
.unwrap(); .unwrap();
@@ -974,7 +927,7 @@ fn get_many_mut_unchecked() {
} }
{ {
let mut i32_slab = slab.get_slab_mut::<i32>(); let mut i32_slab = slab.write_slab::<i32>();
assert!( assert!(
unsafe { i32_slab.get_many_mut_unchecked([NodeId(3), NodeId(100)].into_iter()) } unsafe { i32_slab.get_many_mut_unchecked([NodeId(3), NodeId(100)].into_iter()) }
.is_none() .is_none()
@@ -1001,8 +954,8 @@ fn get_many_many_mut_unchecked() {
println!("slab: {:#?}", slab); println!("slab: {:#?}", slab);
let mut num_entries = slab.get_slab_mut::<i32>(); let mut num_entries = slab.write_slab::<i32>();
let mut str_entries = slab.get_slab_mut::<&str>(); let mut str_entries = slab.write_slab::<&str>();
let all_num = unsafe { let all_num = unsafe {
num_entries num_entries
+2 -2
View File
@@ -1,3 +1,3 @@
mod persistant_iterator; // mod persistant_iterator;
pub use persistant_iterator::*; // pub use persistant_iterator::*;
pub mod cursor; pub mod cursor;
@@ -2,8 +2,6 @@ use crate::{
node::{ElementNode, FromAnyValue, NodeType}, node::{ElementNode, FromAnyValue, NodeType},
passes::{AnyMapLike, TypeErasedPass}, passes::{AnyMapLike, TypeErasedPass},
real_dom::RealDom, real_dom::RealDom,
state::State,
tree::TreeView,
NodeId, NodeId,
}; };
use dioxus_core::{Mutation, Mutations}; use dioxus_core::{Mutation, Mutations};