123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906 |
- use crate::tree::{NodeId, TreeView};
- use crate::{FxDashMap, FxDashSet, SendAnyMap};
- use rustc_hash::{FxHashMap, FxHashSet};
- use std::collections::BTreeMap;
- use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
- use std::sync::atomic::{AtomicU64, Ordering};
- use std::sync::Arc;
- #[derive(Debug, Clone, PartialEq, Eq, Default)]
- pub struct DirtyNodes {
- map: BTreeMap<u16, FxHashSet<NodeId>>,
- }
- impl DirtyNodes {
- pub fn insert(&mut self, depth: u16, node_id: NodeId) {
- self.map
- .entry(depth)
- .or_insert_with(FxHashSet::default)
- .insert(node_id);
- }
- fn pop_front(&mut self) -> Option<NodeId> {
- let (&depth, values) = self.map.iter_mut().next()?;
- let key = *values.iter().next()?;
- let node_id = values.take(&key)?;
- if values.is_empty() {
- self.map.remove(&depth);
- }
- Some(node_id)
- }
- fn pop_back(&mut self) -> Option<NodeId> {
- let (&depth, values) = self.map.iter_mut().rev().next()?;
- let key = *values.iter().next()?;
- let node_id = values.take(&key)?;
- if values.is_empty() {
- self.map.remove(&depth);
- }
- Some(node_id)
- }
- }
- #[test]
- fn dirty_nodes() {
- let mut dirty_nodes = DirtyNodes::default();
- dirty_nodes.insert(1, NodeId(1));
- dirty_nodes.insert(0, NodeId(0));
- dirty_nodes.insert(2, NodeId(3));
- dirty_nodes.insert(1, NodeId(2));
- assert_eq!(dirty_nodes.pop_front(), Some(NodeId(0)));
- assert!(matches!(dirty_nodes.pop_front(), Some(NodeId(1 | 2))));
- assert!(matches!(dirty_nodes.pop_front(), Some(NodeId(1 | 2))));
- assert_eq!(dirty_nodes.pop_front(), Some(NodeId(3)));
- }
- #[derive(Default)]
- pub struct DirtyNodeStates {
- dirty: FxDashMap<NodeId, Vec<AtomicU64>>,
- }
- impl DirtyNodeStates {
- pub fn new(starting_nodes: FxHashMap<NodeId, FxHashSet<PassId>>) -> Self {
- let this = Self::default();
- for (node, nodes) in starting_nodes {
- for pass_id in nodes {
- this.insert(pass_id, node);
- }
- }
- this
- }
- pub fn insert(&self, pass_id: PassId, node_id: NodeId) {
- let pass_id = pass_id.0;
- let index = pass_id / 64;
- let bit = pass_id % 64;
- let encoded = 1 << bit;
- if let Some(dirty) = self.dirty.get(&node_id) {
- if let Some(atomic) = dirty.get(index as usize) {
- atomic.fetch_or(encoded, Ordering::Relaxed);
- } else {
- drop(dirty);
- let mut write = self.dirty.get_mut(&node_id).unwrap();
- write.resize_with(index as usize + 1, || AtomicU64::new(0));
- write[index as usize].fetch_or(encoded, Ordering::Relaxed);
- }
- } else {
- let mut v = Vec::with_capacity(index as usize + 1);
- v.resize_with(index as usize + 1, || AtomicU64::new(0));
- v[index as usize].fetch_or(encoded, Ordering::Relaxed);
- self.dirty.insert(node_id, v);
- }
- }
- fn all_dirty<T>(&self, pass_id: PassId, dirty_nodes: &mut DirtyNodes, tree: &impl TreeView<T>) {
- let pass_id = pass_id.0;
- let index = pass_id / 64;
- let bit = pass_id % 64;
- let encoded = 1 << bit;
- for entry in self.dirty.iter() {
- let node_id = entry.key();
- let dirty = entry.value();
- if let Some(atomic) = dirty.get(index as usize) {
- if atomic.load(Ordering::Relaxed) & encoded != 0 {
- dirty_nodes.insert(tree.height(*node_id).unwrap(), *node_id);
- }
- }
- }
- }
- }
- #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
- pub struct PassId(pub u64);
- #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Default)]
- pub struct MemberMask(pub u64);
- impl MemberMask {
- pub fn overlaps(&self, other: Self) -> bool {
- (*self & other).0 != 0
- }
- }
- impl BitAndAssign for MemberMask {
- fn bitand_assign(&mut self, rhs: Self) {
- self.0 &= rhs.0;
- }
- }
- impl BitAnd for MemberMask {
- type Output = Self;
- fn bitand(self, rhs: Self) -> Self::Output {
- MemberMask(self.0 & rhs.0)
- }
- }
- impl BitOrAssign for MemberMask {
- fn bitor_assign(&mut self, rhs: Self) {
- self.0 |= rhs.0;
- }
- }
- impl BitOr for MemberMask {
- type Output = Self;
- fn bitor(self, rhs: Self) -> Self::Output {
- Self(self.0 | rhs.0)
- }
- }
- pub struct PassReturn {
- pub progress: bool,
- pub mark_dirty: bool,
- }
- pub trait Pass {
- fn pass_id(&self) -> PassId;
- fn dependancies(&self) -> &'static [PassId];
- fn dependants(&self) -> &'static [PassId];
- fn mask(&self) -> MemberMask;
- }
- pub trait UpwardPass<T>: Pass {
- 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>(
- tree: &mut impl TreeView<T>,
- pass: &P,
- mut dirty: DirtyNodes,
- dirty_states: &DirtyNodeStates,
- nodes_updated: &FxDashSet<NodeId>,
- ctx: &SendAnyMap,
- ) {
- while let Some(id) = dirty.pop_back() {
- let (node, mut children) = tree.parent_child_mut(id).unwrap();
- let result = pass.pass(node, &mut children, ctx);
- drop(children);
- if result.progress || result.mark_dirty {
- nodes_updated.insert(id);
- if let Some(id) = tree.parent_id(id) {
- if result.mark_dirty {
- for dependant in pass.dependants() {
- dirty_states.insert(*dependant, id);
- }
- }
- if result.progress {
- let height = tree.height(id).unwrap();
- dirty.insert(height, id);
- }
- }
- }
- }
- }
- pub trait DownwardPass<T>: Pass {
- fn pass(&self, node: &mut T, parent: Option<&mut T>, ctx: &SendAnyMap) -> PassReturn;
- }
- fn resolve_downward_pass<T, P: DownwardPass<T> + ?Sized>(
- tree: &mut impl TreeView<T>,
- pass: &P,
- mut dirty: DirtyNodes,
- dirty_states: &DirtyNodeStates,
- nodes_updated: &FxDashSet<NodeId>,
- ctx: &SendAnyMap,
- ) {
- while let Some(id) = dirty.pop_front() {
- let (node, parent) = tree.node_parent_mut(id).unwrap();
- let result = pass.pass(node, parent, ctx);
- if result.mark_dirty {
- nodes_updated.insert(id);
- }
- if result.mark_dirty || result.progress {
- for id in tree.children_ids(id).unwrap() {
- if result.mark_dirty {
- for dependant in pass.dependants() {
- dirty_states.insert(*dependant, *id);
- }
- }
- if result.progress {
- let height = tree.height(*id).unwrap();
- dirty.insert(height, *id);
- }
- }
- }
- }
- }
- pub trait NodePass<T>: Pass {
- fn pass(&self, node: &mut T, ctx: &SendAnyMap) -> bool;
- }
- fn resolve_node_pass<T, P: NodePass<T> + ?Sized>(
- tree: &mut impl TreeView<T>,
- pass: &P,
- mut dirty: DirtyNodes,
- dirty_states: &DirtyNodeStates,
- nodes_updated: &FxDashSet<NodeId>,
- ctx: &SendAnyMap,
- ) {
- while let Some(id) = dirty.pop_back() {
- let node = tree.get_mut(id).unwrap();
- if pass.pass(node, ctx) {
- nodes_updated.insert(id);
- for dependant in pass.dependants() {
- dirty_states.insert(*dependant, id);
- }
- }
- }
- }
- pub enum AnyPass<T: 'static> {
- Upward(&'static (dyn UpwardPass<T> + Send + Sync + 'static)),
- Downward(&'static (dyn DownwardPass<T> + Send + Sync + 'static)),
- Node(&'static (dyn NodePass<T> + Send + Sync + 'static)),
- }
- impl<T> AnyPass<T> {
- pub fn pass_id(&self) -> PassId {
- match self {
- Self::Upward(pass) => pass.pass_id(),
- Self::Downward(pass) => pass.pass_id(),
- Self::Node(pass) => pass.pass_id(),
- }
- }
- pub fn dependancies(&self) -> &'static [PassId] {
- match self {
- Self::Upward(pass) => pass.dependancies(),
- Self::Downward(pass) => pass.dependancies(),
- Self::Node(pass) => pass.dependancies(),
- }
- }
- fn mask(&self) -> MemberMask {
- match self {
- Self::Upward(pass) => pass.mask(),
- Self::Downward(pass) => pass.mask(),
- Self::Node(pass) => pass.mask(),
- }
- }
- fn resolve(
- &self,
- tree: &mut impl TreeView<T>,
- dirty: DirtyNodes,
- dirty_states: &DirtyNodeStates,
- nodes_updated: &FxDashSet<NodeId>,
- ctx: &SendAnyMap,
- ) {
- match self {
- Self::Downward(pass) => {
- resolve_downward_pass(tree, *pass, dirty, dirty_states, nodes_updated, ctx)
- }
- 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)
- }
- }
- }
- }
- struct RawPointer<T>(*mut T);
- unsafe impl<T> Send for RawPointer<T> {}
- unsafe impl<T> Sync for RawPointer<T> {}
- pub fn resolve_passes<T, Tr: TreeView<T>>(
- tree: &mut Tr,
- dirty_nodes: DirtyNodeStates,
- mut passes: Vec<&AnyPass<T>>,
- ctx: SendAnyMap,
- ) -> FxDashSet<NodeId> {
- let dirty_states = Arc::new(dirty_nodes);
- let mut resolved_passes: FxHashSet<PassId> = FxHashSet::default();
- let mut resolving = Vec::new();
- let nodes_updated = Arc::new(FxDashSet::default());
- let ctx = Arc::new(ctx);
- while !passes.is_empty() {
- let mut currently_borrowed = MemberMask::default();
- std::thread::scope(|s| {
- let mut i = 0;
- while i < passes.len() {
- let pass = &passes[i];
- let pass_id = pass.pass_id();
- let pass_mask = pass.mask();
- if pass
- .dependancies()
- .iter()
- .all(|d| resolved_passes.contains(d) || *d == pass_id)
- && !pass_mask.overlaps(currently_borrowed)
- {
- let pass = passes.remove(i);
- resolving.push(pass_id);
- currently_borrowed |= pass_mask;
- let tree_mut = tree as *mut _;
- let raw_ptr = RawPointer(tree_mut);
- let dirty_states = dirty_states.clone();
- let nodes_updated = nodes_updated.clone();
- let ctx = ctx.clone();
- s.spawn(move || unsafe {
- // let tree_mut: &mut Tr = &mut *raw_ptr.0;
- 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 mut dirty = DirtyNodes::default();
- dirty_states.all_dirty(pass_id, &mut dirty, tree_mut);
- pass.resolve(tree_mut, dirty, &dirty_states, &nodes_updated, &ctx);
- });
- } else {
- i += 1;
- }
- }
- // all passes are resolved at the end of the scope
- });
- resolved_passes.extend(resolving.iter().copied());
- resolving.clear()
- }
- std::sync::Arc::try_unwrap(nodes_updated).unwrap()
- }
- #[test]
- fn node_pass() {
- use crate::tree::{Tree, TreeLike};
- let mut tree = Tree::new(0);
- struct AddPass;
- impl Pass for AddPass {
- fn pass_id(&self) -> PassId {
- PassId(0)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl NodePass<i32> for AddPass {
- fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
- *node += 1;
- true
- }
- }
- let add_pass = AnyPass::Node(&AddPass);
- let passes = vec![&add_pass];
- let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
- dirty_nodes.insert(PassId(0), tree.root());
- resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
- assert_eq!(tree.get(tree.root()).unwrap(), &1);
- }
- #[test]
- fn dependant_node_pass() {
- use crate::tree::{Tree, TreeLike};
- let mut tree = Tree::new(0);
- struct AddPass;
- impl Pass for AddPass {
- fn pass_id(&self) -> PassId {
- PassId(0)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[PassId(1)]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl NodePass<i32> for AddPass {
- fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
- *node += 1;
- true
- }
- }
- struct SubtractPass;
- impl Pass for SubtractPass {
- fn pass_id(&self) -> PassId {
- PassId(1)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[PassId(0)]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl NodePass<i32> for SubtractPass {
- fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
- *node -= 1;
- true
- }
- }
- let add_pass = AnyPass::Node(&AddPass);
- let subtract_pass = AnyPass::Node(&SubtractPass);
- let passes = vec![&add_pass, &subtract_pass];
- let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
- dirty_nodes.insert(PassId(1), tree.root());
- resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
- assert_eq!(*tree.get(tree.root()).unwrap(), 0);
- }
- #[test]
- fn independant_node_pass() {
- use crate::tree::{Tree, TreeLike};
- let mut tree = Tree::new((0, 0));
- struct AddPass1;
- impl Pass for AddPass1 {
- fn pass_id(&self) -> PassId {
- PassId(0)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl NodePass<(i32, i32)> for AddPass1 {
- fn pass(&self, node: &mut (i32, i32), _: &SendAnyMap) -> bool {
- node.0 += 1;
- true
- }
- }
- struct AddPass2;
- impl Pass for AddPass2 {
- fn pass_id(&self) -> PassId {
- PassId(1)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(1)
- }
- }
- impl NodePass<(i32, i32)> for AddPass2 {
- fn pass(&self, node: &mut (i32, i32), _: &SendAnyMap) -> bool {
- node.1 += 1;
- true
- }
- }
- let add_pass1 = AnyPass::Node(&AddPass1);
- let add_pass2 = AnyPass::Node(&AddPass2);
- let passes = vec![&add_pass1, &add_pass2];
- let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
- dirty_nodes.insert(PassId(0), tree.root());
- dirty_nodes.insert(PassId(1), tree.root());
- resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
- assert_eq!(tree.get(tree.root()).unwrap(), &(1, 1));
- }
- #[test]
- fn down_pass() {
- use crate::tree::{Tree, TreeLike};
- let mut tree = Tree::new(1);
- let parent = tree.root();
- let child1 = tree.create_node(1);
- tree.add_child(parent, child1);
- let grandchild1 = tree.create_node(1);
- tree.add_child(child1, grandchild1);
- let child2 = tree.create_node(1);
- tree.add_child(parent, child2);
- let grandchild2 = tree.create_node(1);
- tree.add_child(child2, grandchild2);
- struct AddPass;
- impl Pass for AddPass {
- fn pass_id(&self) -> PassId {
- PassId(0)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl DownwardPass<i32> for AddPass {
- fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
- if let Some(parent) = parent {
- *node += *parent;
- }
- PassReturn {
- progress: true,
- mark_dirty: true,
- }
- }
- }
- let add_pass = AnyPass::Downward(&AddPass);
- let passes = vec![&add_pass];
- let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
- dirty_nodes.insert(PassId(0), tree.root());
- resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
- assert_eq!(tree.get(tree.root()).unwrap(), &1);
- assert_eq!(tree.get(child1).unwrap(), &2);
- assert_eq!(tree.get(grandchild1).unwrap(), &3);
- assert_eq!(tree.get(child2).unwrap(), &2);
- assert_eq!(tree.get(grandchild2).unwrap(), &3);
- }
- #[test]
- fn dependant_down_pass() {
- use crate::tree::{Tree, TreeLike};
- // 0
- let mut tree = Tree::new(1);
- let parent = tree.root();
- // 1
- let child1 = tree.create_node(1);
- tree.add_child(parent, child1);
- // 2
- let grandchild1 = tree.create_node(1);
- tree.add_child(child1, grandchild1);
- // 3
- let child2 = tree.create_node(1);
- tree.add_child(parent, child2);
- // 4
- let grandchild2 = tree.create_node(1);
- tree.add_child(child2, grandchild2);
- struct AddPass;
- impl Pass for AddPass {
- fn pass_id(&self) -> PassId {
- PassId(0)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[PassId(1)]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl DownwardPass<i32> for AddPass {
- fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
- if let Some(parent) = parent {
- *node += *parent;
- } else {
- }
- PassReturn {
- progress: true,
- mark_dirty: true,
- }
- }
- }
- struct SubtractPass;
- impl Pass for SubtractPass {
- fn pass_id(&self) -> PassId {
- PassId(1)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[PassId(0)]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl DownwardPass<i32> for SubtractPass {
- fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
- if let Some(parent) = parent {
- *node -= *parent;
- } else {
- }
- PassReturn {
- progress: true,
- mark_dirty: true,
- }
- }
- }
- let add_pass = AnyPass::Downward(&AddPass);
- let subtract_pass = AnyPass::Downward(&SubtractPass);
- let passes = vec![&add_pass, &subtract_pass];
- let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
- dirty_nodes.insert(PassId(1), tree.root());
- resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
- // Tree before:
- // 1=\
- // 1=\
- // 1
- // 1=\
- // 1
- // Tree after subtract:
- // 1=\
- // 0=\
- // 1
- // 0=\
- // 1
- // Tree after add:
- // 1=\
- // 1=\
- // 2
- // 1=\
- // 2
- assert_eq!(tree.get(tree.root()).unwrap(), &1);
- assert_eq!(tree.get(child1).unwrap(), &1);
- assert_eq!(tree.get(grandchild1).unwrap(), &2);
- assert_eq!(tree.get(child2).unwrap(), &1);
- assert_eq!(tree.get(grandchild2).unwrap(), &2);
- }
- #[test]
- fn up_pass() {
- use crate::tree::{Tree, TreeLike};
- // Tree before:
- // 0=\
- // 0=\
- // 1
- // 0=\
- // 1
- // Tree after:
- // 2=\
- // 1=\
- // 1
- // 1=\
- // 1
- let mut tree = Tree::new(0);
- let parent = tree.root();
- let child1 = tree.create_node(0);
- tree.add_child(parent, child1);
- let grandchild1 = tree.create_node(1);
- tree.add_child(child1, grandchild1);
- let child2 = tree.create_node(0);
- tree.add_child(parent, child2);
- let grandchild2 = tree.create_node(1);
- tree.add_child(child2, grandchild2);
- struct AddPass;
- impl Pass for AddPass {
- fn pass_id(&self) -> PassId {
- PassId(0)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl UpwardPass<i32> for AddPass {
- fn pass<'a>(
- &self,
- node: &mut i32,
- children: &mut dyn Iterator<Item = &'a mut i32>,
- _: &SendAnyMap,
- ) -> PassReturn {
- *node += children.map(|i| *i).sum::<i32>();
- PassReturn {
- progress: true,
- mark_dirty: true,
- }
- }
- }
- let add_pass = AnyPass::Upward(&AddPass);
- let passes = vec![&add_pass];
- let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
- dirty_nodes.insert(PassId(0), grandchild1);
- dirty_nodes.insert(PassId(0), grandchild2);
- resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
- assert_eq!(tree.get(tree.root()).unwrap(), &2);
- assert_eq!(tree.get(child1).unwrap(), &1);
- assert_eq!(tree.get(grandchild1).unwrap(), &1);
- assert_eq!(tree.get(child2).unwrap(), &1);
- assert_eq!(tree.get(grandchild2).unwrap(), &1);
- }
- #[test]
- fn dependant_up_pass() {
- use crate::tree::{Tree, TreeLike};
- // 0
- let mut tree = Tree::new(0);
- let parent = tree.root();
- // 1
- let child1 = tree.create_node(0);
- tree.add_child(parent, child1);
- // 2
- let grandchild1 = tree.create_node(1);
- tree.add_child(child1, grandchild1);
- // 3
- let child2 = tree.create_node(0);
- tree.add_child(parent, child2);
- // 4
- let grandchild2 = tree.create_node(1);
- tree.add_child(child2, grandchild2);
- struct AddPass;
- impl Pass for AddPass {
- fn pass_id(&self) -> PassId {
- PassId(0)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[PassId(1)]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl UpwardPass<i32> for AddPass {
- fn pass<'a>(
- &self,
- node: &mut i32,
- children: &mut dyn Iterator<Item = &'a mut i32>,
- _: &SendAnyMap,
- ) -> PassReturn {
- *node += children.map(|i| *i).sum::<i32>();
- PassReturn {
- progress: true,
- mark_dirty: true,
- }
- }
- }
- struct SubtractPass;
- impl Pass for SubtractPass {
- fn pass_id(&self) -> PassId {
- PassId(1)
- }
- fn dependancies(&self) -> &'static [PassId] {
- &[]
- }
- fn dependants(&self) -> &'static [PassId] {
- &[PassId(0)]
- }
- fn mask(&self) -> MemberMask {
- MemberMask(0)
- }
- }
- impl UpwardPass<i32> for SubtractPass {
- fn pass<'a>(
- &self,
- node: &mut i32,
- children: &mut dyn Iterator<Item = &'a mut i32>,
- _: &SendAnyMap,
- ) -> PassReturn {
- *node -= children.map(|i| *i).sum::<i32>();
- PassReturn {
- progress: true,
- mark_dirty: true,
- }
- }
- }
- let add_pass = AnyPass::Upward(&AddPass);
- let subtract_pass = AnyPass::Upward(&SubtractPass);
- let passes = vec![&add_pass, &subtract_pass];
- let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
- dirty_nodes.insert(PassId(1), grandchild1);
- dirty_nodes.insert(PassId(1), grandchild2);
- resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
- // Tree before:
- // 0=\
- // 0=\
- // 1
- // 0=\
- // 1
- // Tree after subtract:
- // 2=\
- // -1=\
- // 1
- // -1=\
- // 1
- // Tree after add:
- // 2=\
- // 0=\
- // 1
- // 0=\
- // 1
- assert_eq!(tree.get(tree.root()).unwrap(), &2);
- assert_eq!(tree.get(child1).unwrap(), &0);
- assert_eq!(tree.get(grandchild1).unwrap(), &1);
- assert_eq!(tree.get(child2).unwrap(), &0);
- assert_eq!(tree.get(grandchild2).unwrap(), &1);
- }
|