Skip to content

Commit

Permalink
separate tree rd/wr ifaces, make them based on an ops object
Browse files Browse the repository at this point in the history
the ops object is needed to make it so that dom node mutations
go through the RCU store
  • Loading branch information
nikomatsakis committed May 4, 2012
1 parent 39462a5 commit bbc936d
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/servo/content.rs
Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions src/servo/dom/base.rs
Expand Up @@ -23,3 +23,23 @@ impl methods for scope<node_data, box> {
kind: k}))
}
}

impl of tree::rd_tree_ops<node> for scope<node_data, box> {
fn each_child(node: node, f: fn(node) -> bool) {
tree::each_child(self, node, f)
}

fn with_tree_fields<R>(node: node, f: fn(tree::fields<node>) -> R) -> R {
f(self.rd(node) { |f| f.tree })
}
}

impl of tree::wr_tree_ops<node> for scope<node_data, box> {
fn add_child(node: node, child: node) {
tree::add_child(self, node, child)
}

fn with_tree_fields<R>(node: node, f: fn(tree::fields<node>) -> R) -> R {
f(self.wr(node) { |f| f.tree })
}
}
6 changes: 6 additions & 0 deletions src/servo/dom/rcu.rs
Expand Up @@ -123,6 +123,12 @@ impl writer_methods<T:send,A> for scope<T,A> {
self.layout_active = false;
}

fn rd<U>(h: handle<T,A>, 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<U>(h: handle<T,A>, f: fn(T) -> U) -> U unsafe {
if self.layout_active {
if h.rd_ptr() == h.wr_ptr() {
Expand Down
51 changes: 36 additions & 15 deletions src/servo/layout/base.rs
Expand Up @@ -11,15 +11,35 @@ enum box = {
mut bounds: geom::rect<au>
};

impl of tree::tree for node {
fn with_tree_fields<R>(f: fn(tree::fields<node>) -> R) -> R {
f(self.rd { |f| f.tree })
enum ntree { ntree }
impl of tree::rd_tree_ops<node> for ntree {
fn each_child(node: node, f: fn(node) -> bool) {
tree::each_child(self, node, f)
}

fn with_tree_fields<R>(n: node, f: fn(tree::fields<node>) -> R) -> R {
n.rd { |n| f(n.tree) }
}
}

impl of tree::tree for @box {
fn with_tree_fields<R>(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<R>(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<R>(b: @box, f: fn(tree::fields<@box>) -> R) -> R {
f(b.tree)
}
}

Expand Down Expand Up @@ -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)};
Expand All @@ -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;

/*
Expand All @@ -90,7 +111,7 @@ mod test {

fn flat_bounds(root: @box) -> [geom::rect<au>] {
let mut r = [];
for tree::each_child(root) {|c|
for tree::each_child(btree, root) {|c|
r += flat_bounds(c);
}
ret r + [root.bounds];
Expand All @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions src/servo/layout/layout.rs
Expand Up @@ -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,
Expand All @@ -38,9 +38,9 @@ fn layout(renderer: chan<renderer::msg>) -> chan<msg> {
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) {
Expand All @@ -63,7 +63,7 @@ fn layout(renderer: chan<renderer::msg>) -> chan<msg> {
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);
}

Expand Down
47 changes: 30 additions & 17 deletions src/servo/util/tree.rs
Expand Up @@ -6,20 +6,24 @@ type fields<T> = {
mut next_sibling: option<T>
};

iface tree {
fn with_tree_fields<R>(f: fn(fields<self>) -> R) -> R;
iface rd_tree_ops<T> {
fn with_tree_fields<R>(T, f: fn(fields<T>) -> R) -> R;
}

fn each_child<T:copy tree>(
node: T, f: fn(T) -> bool) {
iface wr_tree_ops<T> {
fn with_tree_fields<R>(T, f: fn(fields<T>) -> R) -> R;
}

fn each_child<T:copy,O:rd_tree_ops<T>>(
ops: O, node: T, f: fn(T) -> bool) {

let mut p = node.with_tree_fields { |f| f.first_child };
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 };
}
}
}
Expand All @@ -33,10 +37,10 @@ fn empty<T>() -> fields<T> {
mut next_sibling: none}
}

fn add_child<T:copy tree>(
node: T, child: T) {
fn add_child<T:copy,O:wr_tree_ops<T>>(
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); }
Expand All @@ -45,14 +49,15 @@ fn add_child<T:copy tree>(
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);
}
Expand All @@ -72,9 +77,17 @@ mod test {
value: uint
};

impl of tree for dummy {
fn with_tree_fields<R>(f: fn(fields<dummy>) -> R) -> R {
f(self.fields)
enum dtree { dtree }

impl of rd_tree_ops<dummy> for dtree {
fn with_tree_fields<R>(d: dummy, f: fn(fields<dummy>) -> R) -> R {
f(d.fields)
}
}

impl of wr_tree_ops<dummy> for dtree {
fn with_tree_fields<R>(d: dummy, f: fn(fields<dummy>) -> R) -> R {
f(d.fields)
}
}

Expand All @@ -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};
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down

0 comments on commit bbc936d

Please sign in to comment.