RCU -> COW

This commit is contained in:
Brian Anderson 2012-10-10 14:30:12 -07:00
parent fca9e9fa00
commit e523a6375a
7 changed files with 21 additions and 23 deletions

View file

@ -96,7 +96,7 @@ trait StyleMethods {
impl Node : StyleMethods {
/** If none exists, creates empty layout data for the node (the reader-auxiliary
* box in the RCU model) and populates it with an empty style object.
* box in the COW model) and populates it with an empty style object.
*/
fn initialize_layout_data() -> Option<@LayoutData> {
match self.has_aux() {
@ -141,7 +141,7 @@ impl Node : StyleMethods {
* Performs CSS selector matching on a subtree.
* This is, importantly, the function that updates the layout data for
* the node (the reader-auxiliary box in the RCU model) with the
* the node (the reader-auxiliary box in the COW model) with the
* computed style.
*/
fn recompute_style_for_subtree(ctx: &LayoutContext, styles : &ARC<Stylesheet>) {

View file

@ -1,35 +1,35 @@
#[doc(str = "
Implements the RCU DOM-sharing model. This model allows for a single writer and any number of
Implements the copy-on-write DOM-sharing model. This model allows for a single writer and any number of
readers, but the writer must be able to control and manage the lifetimes of the reader(s). For
simplicity I will describe the implementation as though there were a single reader.
The basic idea is that every object in the RCU pool has both a reader view and a writer view. The
The basic idea is that every object in the COW pool has both a reader view and a writer view. The
writer always sees the writer view, which contains the most up-to-date values. The reader uses the
reader view, which contains the values as of the point where the reader was forked. When the
writer joins the reader, the reader view will be synchronized with the writer view.
Internally, the way this works is using a copy-on-write scheme. Each RCU node maintains two
Internally, the way this works is using a copy-on-write scheme. Each COW node maintains two
pointers (`read_ptr` and `write_ptr`). Assuming that readers are active, when a writer wants to
modify a node, it first copies the reader's data into a new pointer. Any writes that occur after
that point (but before the reader is joined) will operate on this same copy. When the reader is
joined, any nodes which the writer modified will free the stale reader data and update the reader
pointer to be the same as the writer pointer.
# Using the RCU APIs as a writer
# Using the COW APIs as a writer
You must first create a `scope` object. The scope object manages the memory and the RCU
operations. RCU'd objects of some sendable type `T` are not referenced directly but rather through
a `handle<T>`. To create a new RCU object, you use `scope.handle(t)` where `t` is some initial
value of type `T`. To write to an RCU object, use `scope.write()` and to read from it use
You must first create a `scope` object. The scope object manages the memory and the COW
operations. COW'd objects of some sendable type `T` are not referenced directly but rather through
a `handle<T>`. To create a new COW object, you use `scope.handle(t)` where `t` is some initial
value of type `T`. To write to an COW object, use `scope.write()` and to read from it use
`scope.read()`. Be sure not to use the various `ReaderMethods`.
Handles can be freely sent between tasks but the RCU scope cannot. It must stay with the writer
Handles can be freely sent between tasks but the COW scope cannot. It must stay with the writer
task. You are responsible for correctly invoking `reader_forked()` and `reader_joined()` to keep
the RCU scope abreast of when the reader is active. Failure to do so will lead to race conditions
the COW scope abreast of when the reader is active. Failure to do so will lead to race conditions
or worse.
# Using the RCU APIs as a reader
# Using the COW APIs as a reader
Import the `ReaderMethods` impl. When you receive a handle, you can invoke `h.read { |v| ... }`
and so forth. There is also a piece of auxiliary data that can be optionally associated with each
@ -45,7 +45,7 @@ fields.
Readers can associate a piece of auxiliary data of type `A` along with main nodes. This is
convenient but dangerous: it is the reader's job to ensure that this data remains live independent
of the RCU nodes themselves.
of the COW nodes themselves.
")];

View file

@ -50,7 +50,7 @@ impl Node {
/* TODO: LayoutData is just a pointer, but we must circumvent the type
system to actually compare the pointers. This should be fixed in
with a generic implementation of rcu::Handle */
with a generic implementation of cow::Handle */
impl Node : cmp::Eq {
pure fn eq(other : &Node) -> bool unsafe {
let my_data : @LayoutData = @self.aux(|a| copy *a);
@ -122,7 +122,7 @@ fn define_bindings(compartment: &bare_compartment, doc: @Document,
}
/** The RCU rd_aux data is a (weak) pointer to the layout data,
/** The COW rd_aux data is a (weak) pointer to the layout data,
defined by this `LayoutData` enum. It contains the CSS style object
as well as the primary `RenderBox`.
@ -132,12 +132,12 @@ enum LayoutData = {
mut flow: Option<@FlowContext>
};
type Node = rcu::Handle<NodeData, LayoutData>;
type Node = cow::Handle<NodeData, LayoutData>;
type NodeScope = rcu::Scope<NodeData, LayoutData>;
type NodeScope = cow::Scope<NodeData, LayoutData>;
fn NodeScope() -> NodeScope {
rcu::Scope()
cow::Scope()
}
trait NodeScopeExtensions {

View file

@ -12,7 +12,6 @@ use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColor
use dl = gfx::display_list;
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
use dom::rcu;
use geom::rect::Rect;
use geom::size::Size2D;
use geom::point::Point2D;

View file

@ -5,7 +5,7 @@ use au::au;
use css::values::{BgColor, BgColorTransparent, Specified};
use dl = gfx::display_list;
use dom::node::{Text, NodeScope};
use dom::rcu::Scope;
use dom::cow::Scope;
use dvec::DVec;
use either::{Left, Right};
use geom::point::Point2D;

View file

@ -3,7 +3,6 @@ use core::dlist::DList;
use core::dvec::DVec;
use css::values::{BoxAuto, BoxLength, Px};
use dl = gfx::display_list;
use dom::rcu;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;

View file

@ -35,7 +35,7 @@ pub mod dom {
pub mod element;
pub mod event;
pub mod node;
pub mod rcu;
pub mod cow;
pub mod window;
}