From bbc936dec423ba5acadcfb7ad67934d7e89a887f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 4 May 2012 13:21:25 -0700 Subject: [PATCH] separate tree rd/wr ifaces, make them based on an ops object the ops object is needed to make it so that dom node mutations go through the RCU store --- src/servo/content.rs | 2 +- src/servo/dom/base.rs | 20 +++++++++++++++ src/servo/dom/rcu.rs | 6 +++++ src/servo/layout/base.rs | 51 +++++++++++++++++++++++++++----------- src/servo/layout/layout.rs | 8 +++--- src/servo/util/tree.rs | 47 ++++++++++++++++++++++------------- 6 files changed, 97 insertions(+), 37 deletions(-) diff --git a/src/servo/content.rs b/src/servo/content.rs index 746e619cbb6..7655e6e216f 100644 --- a/src/servo/content.rs +++ b/src/servo/content.rs @@ -4,7 +4,7 @@ export content; import gfx::geom::*; import dom::rcu::*; import dom::base::*; -import layout::base::tree; // method implementations of tree for box and node +import layout::base::{rd_tree_ops, wr_tree_ops}; enum msg { exit diff --git a/src/servo/dom/base.rs b/src/servo/dom/base.rs index eed4ed3e5f2..30c3f9eb210 100644 --- a/src/servo/dom/base.rs +++ b/src/servo/dom/base.rs @@ -23,3 +23,23 @@ impl methods for scope { kind: k})) } } + +impl of tree::rd_tree_ops for scope { + fn each_child(node: node, f: fn(node) -> bool) { + tree::each_child(self, node, f) + } + + fn with_tree_fields(node: node, f: fn(tree::fields) -> R) -> R { + f(self.rd(node) { |f| f.tree }) + } +} + +impl of tree::wr_tree_ops for scope { + fn add_child(node: node, child: node) { + tree::add_child(self, node, child) + } + + fn with_tree_fields(node: node, f: fn(tree::fields) -> R) -> R { + f(self.wr(node) { |f| f.tree }) + } +} diff --git a/src/servo/dom/rcu.rs b/src/servo/dom/rcu.rs index 73196026248..02233b6ed0c 100644 --- a/src/servo/dom/rcu.rs +++ b/src/servo/dom/rcu.rs @@ -123,6 +123,12 @@ impl writer_methods for scope { self.layout_active = false; } + fn rd(h: handle, f: fn(T) -> U) -> U unsafe { + // Use the wr_ptr, which may be more up to date than the + // rd_ptr or may not + f(*h.wr_ptr()) + } + fn wr(h: handle, f: fn(T) -> U) -> U unsafe { if self.layout_active { if h.rd_ptr() == h.wr_ptr() { diff --git a/src/servo/layout/base.rs b/src/servo/layout/base.rs index ecd4c33305a..f1e34053903 100644 --- a/src/servo/layout/base.rs +++ b/src/servo/layout/base.rs @@ -11,15 +11,35 @@ enum box = { mut bounds: geom::rect }; -impl of tree::tree for node { - fn with_tree_fields(f: fn(tree::fields) -> R) -> R { - f(self.rd { |f| f.tree }) +enum ntree { ntree } +impl of tree::rd_tree_ops for ntree { + fn each_child(node: node, f: fn(node) -> bool) { + tree::each_child(self, node, f) + } + + fn with_tree_fields(n: node, f: fn(tree::fields) -> R) -> R { + n.rd { |n| f(n.tree) } } } -impl of tree::tree for @box { - fn with_tree_fields(f: fn(tree::fields<@box>) -> R) -> R { - f(self.tree) +enum btree { btree } +impl of tree::rd_tree_ops<@box> for btree { + fn each_child(node: @box, f: fn(&&@box) -> bool) { + tree::each_child(self, node, f) + } + + fn with_tree_fields(b: @box, f: fn(tree::fields<@box>) -> R) -> R { + f(b.tree) + } +} + +impl of tree::wr_tree_ops<@box> for btree { + fn add_child(node: @box, child: @box) { + tree::add_child(self, node, child) + } + + fn with_tree_fields(b: @box, f: fn(tree::fields<@box>) -> R) -> R { + f(b.tree) } } @@ -55,7 +75,7 @@ fn reflow_block(root: @box, available_width: au) { } let mut current_height = 0; - for tree::each_child(root) {|c| + for tree::each_child(btree, root) {|c| let mut blk_available_width = available_width; // FIXME subtract borders, margins, etc c.bounds.origin = {mut x: au(0), mut y: au(current_height)}; @@ -69,7 +89,8 @@ fn reflow_block(root: @box, available_width: au) { #[cfg(test)] mod test { - import dom::base::{nk_img, node_data, node_kind, node, methods}; + import dom::base::{nk_img, node_data, node_kind, node, methods, + wr_tree_ops}; import dom::rcu::scope; /* @@ -90,7 +111,7 @@ mod test { fn flat_bounds(root: @box) -> [geom::rect] { let mut r = []; - for tree::each_child(root) {|c| + for tree::each_child(btree, root) {|c| r += flat_bounds(c); } ret r + [root.bounds]; @@ -105,18 +126,18 @@ mod test { let n2 = s.new_node(nk_img(size(au(10),au(20)))); let n3 = s.new_node(nk_div); - tree::add_child(n3, n0); - tree::add_child(n3, n1); - tree::add_child(n3, n2); + tree::add_child(s, n3, n0); + tree::add_child(s, n3, n1); + tree::add_child(s, n3, n2); let b0 = linked_box(n0); let b1 = linked_box(n1); let b2 = linked_box(n2); let b3 = linked_box(n3); - tree::add_child(b3, b0); - tree::add_child(b3, b1); - tree::add_child(b3, b2); + tree::add_child(btree, b3, b0); + tree::add_child(btree, b3, b1); + tree::add_child(btree, b3, b2); reflow_block(b3, au(100)); let fb = flat_bounds(b3); diff --git a/src/servo/layout/layout.rs b/src/servo/layout/layout.rs index d67ca770e30..755ec5ef506 100644 --- a/src/servo/layout/layout.rs +++ b/src/servo/layout/layout.rs @@ -13,7 +13,7 @@ import gfx::renderer; import dom::base::*; import display_list::*; import dom::rcu::scope; -import base::tree; +import base::{btree, rd_tree_ops, wr_tree_ops}; enum msg { build, @@ -38,9 +38,9 @@ fn layout(renderer: chan) -> chan { int_to_au(r.next() as int % 800), int_to_au(r.next() as int % 200) ))); - tree::add_child(ndiv, node); + s.add_child(ndiv, node); let b = base::linked_box(node); - tree::add_child(bdiv, b); + btree.add_child(bdiv, b); } alt recv(po) { @@ -63,7 +63,7 @@ fn layout(renderer: chan) -> chan { fn build_display_list(box: @base::box) -> display_list::display_list { let mut list = [box_to_display_item(box)]; - for tree::each_child(box) {|c| + for btree.each_child(box) {|c| list += build_display_list(c); } diff --git a/src/servo/util/tree.rs b/src/servo/util/tree.rs index 1fa7448dc3c..8805853a105 100644 --- a/src/servo/util/tree.rs +++ b/src/servo/util/tree.rs @@ -6,20 +6,24 @@ type fields = { mut next_sibling: option }; -iface tree { - fn with_tree_fields(f: fn(fields) -> R) -> R; +iface rd_tree_ops { + fn with_tree_fields(T, f: fn(fields) -> R) -> R; } -fn each_child( - node: T, f: fn(T) -> bool) { +iface wr_tree_ops { + fn with_tree_fields(T, f: fn(fields) -> R) -> R; +} - let mut p = node.with_tree_fields { |f| f.first_child }; +fn each_child>( + ops: O, node: T, f: fn(T) -> bool) { + + let mut p = ops.with_tree_fields(node) { |f| f.first_child }; loop { alt p { none { ret; } some(c) { if !f(c) { ret; } - p = c.with_tree_fields { |f| f.next_sibling }; + p = ops.with_tree_fields(c) { |f| f.next_sibling }; } } } @@ -33,10 +37,10 @@ fn empty() -> fields { mut next_sibling: none} } -fn add_child( - node: T, child: T) { +fn add_child>( + ops: O, node: T, child: T) { - child.with_tree_fields { |child_tf| + ops.with_tree_fields(child) { |child_tf| alt child_tf.parent { some(_) { fail "Already has a parent"; } none { child_tf.parent = some(node); } @@ -45,14 +49,15 @@ fn add_child( assert child_tf.prev_sibling == none; assert child_tf.next_sibling == none; - node.with_tree_fields { |node_tf| + ops.with_tree_fields(node) { |node_tf| alt node_tf.last_child { none { node_tf.first_child = some(child); } some(lc) { - lc.with_tree_fields { |lc_tf| + let lc = lc; // satisfy alias checker + ops.with_tree_fields(lc) { |lc_tf| assert lc_tf.next_sibling == none; lc_tf.next_sibling = some(child); } @@ -72,9 +77,17 @@ mod test { value: uint }; - impl of tree for dummy { - fn with_tree_fields(f: fn(fields) -> R) -> R { - f(self.fields) + enum dtree { dtree } + + impl of rd_tree_ops for dtree { + fn with_tree_fields(d: dummy, f: fn(fields) -> R) -> R { + f(d.fields) + } + } + + impl of wr_tree_ops for dtree { + fn with_tree_fields(d: dummy, f: fn(fields) -> R) -> R { + f(d.fields) } } @@ -89,7 +102,7 @@ mod test { let p = new_dummy(3u); for vec::each(children) {|c| - add_child(p, c); + add_child(dtree, p, c); } ret {p: p, children: children}; @@ -99,7 +112,7 @@ mod test { fn add_child_0() { let {p, children} = parent_with_3_children(); let mut i = 0u; - for each_child(p) {|c| + for each_child(dtree, p) {|c| assert c.value == i; i += 1u; } @@ -110,7 +123,7 @@ mod test { fn add_child_break() { let {p, _} = parent_with_3_children(); let mut i = 0u; - for each_child(p) {|_c| + for each_child(dtree, p) {|_c| i += 1u; break; }