diff options
author | Simon Sapin <simon.sapin@exyr.org> | 2016-11-05 14:17:48 +0100 |
---|---|---|
committer | Simon Sapin <simon.sapin@exyr.org> | 2016-11-05 17:29:56 +0100 |
commit | 1a18161006c67424750943e1b29d3f3aead92d5e (patch) | |
tree | c056cc7600a828cf00340befce3157d470ae819f | |
parent | 2dd2c9cedde733f30042163c20e763b243567780 (diff) | |
download | servo-1a18161006c67424750943e1b29d3f3aead92d5e.tar.gz servo-1a18161006c67424750943e1b29d3f3aead92d5e.zip |
rule tree: more descriptive field names
-rw-r--r-- | components/style/rule_tree/mod.rs | 178 |
1 files changed, 84 insertions, 94 deletions
diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 1b32ab287e8..5534d76323a 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -120,6 +120,7 @@ impl RuleTree { current } + /// This can only be called when no other threads is accessing this tree. pub unsafe fn gc(&self) { self.root.gc(); } @@ -140,10 +141,10 @@ struct RuleNode { /// meaningless in the root node. importance: Importance, - children: RuleChildrenList, refcount: AtomicUsize, - next: AtomicPtr<RuleNode>, - prev: AtomicPtr<RuleNode>, + first_child: AtomicPtr<RuleNode>, + next_sibling: AtomicPtr<RuleNode>, + prev_sibling: AtomicPtr<RuleNode>, /// The next item in the rule tree free list, that starts on the root node. next_free: AtomicPtr<RuleNode>, @@ -163,10 +164,10 @@ impl RuleNode { parent: Some(parent), source: Some(source), importance: importance, - children: RuleChildrenList::new(), refcount: AtomicUsize::new(1), - next: AtomicPtr::new(ptr::null_mut()), - prev: AtomicPtr::new(ptr::null_mut()), + first_child: AtomicPtr::new(ptr::null_mut()), + next_sibling: AtomicPtr::new(ptr::null_mut()), + prev_sibling: AtomicPtr::new(ptr::null_mut()), next_free: AtomicPtr::new(ptr::null_mut()), } } @@ -177,10 +178,10 @@ impl RuleNode { parent: None, source: None, importance: Importance::Normal, - children: RuleChildrenList::new(), refcount: AtomicUsize::new(1), - next: AtomicPtr::new(ptr::null_mut()), - prev: AtomicPtr::new(ptr::null_mut()), + first_child: AtomicPtr::new(ptr::null_mut()), + next_sibling: AtomicPtr::new(ptr::null_mut()), + prev_sibling: AtomicPtr::new(ptr::null_mut()), next_free: AtomicPtr::new(FREE_LIST_SENTINEL), } } @@ -199,21 +200,21 @@ impl RuleNode { unsafe fn remove_from_child_list(&self) { debug!("Remove from child list: {:?}, parent: {:?}", self as *const RuleNode, self.parent.as_ref().map(|p| p.ptr())); - let previous = self.prev.swap(ptr::null_mut(), Ordering::SeqCst); - let next = self.next.swap(ptr::null_mut(), Ordering::SeqCst); + let prev_sibling = self.prev_sibling.swap(ptr::null_mut(), Ordering::SeqCst); + let next_sibling = self.next_sibling.swap(ptr::null_mut(), Ordering::SeqCst); - if previous != ptr::null_mut() { - let really_previous = WeakRuleNode { ptr: previous }; + if prev_sibling != ptr::null_mut() { + let really_previous = WeakRuleNode { ptr: prev_sibling }; really_previous.upgrade() - .get().next.store(next, Ordering::SeqCst); + .get().next_sibling.store(next_sibling, Ordering::SeqCst); } else { self.parent.as_ref().unwrap() - .get().children.head.store(ptr::null_mut(), Ordering::SeqCst); + .get().first_child.store(ptr::null_mut(), Ordering::SeqCst); } - if next != ptr::null_mut() { - let really_next = WeakRuleNode { ptr: next }; - really_next.upgrade().get().prev.store(previous, Ordering::SeqCst); + if next_sibling != ptr::null_mut() { + let really_next = WeakRuleNode { ptr: next_sibling }; + really_next.upgrade().get().prev_sibling.store(prev_sibling, Ordering::SeqCst); } } @@ -245,10 +246,22 @@ impl RuleNode { } let _ = write!(writer, "\n"); - for child in self.children.iter() { + for child in self.iter_children() { child.get().dump(writer, indent + INDENT_INCREMENT); } } + + fn iter_children(&self) -> RuleChildrenListIter { + // FIXME(emilio): Fiddle with memory orderings. + let first_child = self.first_child.load(Ordering::SeqCst); + RuleChildrenListIter { + current: if first_child.is_null() { + None + } else { + Some(WeakRuleNode { ptr: first_child }) + } + } + } } #[derive(Clone)] @@ -286,10 +299,10 @@ impl StrongRuleNode { } } - fn next(&self) -> Option<WeakRuleNode> { + fn next_sibling(&self) -> Option<WeakRuleNode> { // FIXME(emilio): Investigate what ordering can we achieve without // messing things up. - let ptr = self.get().next.load(Ordering::SeqCst); + let ptr = self.get().next_sibling.load(Ordering::SeqCst); if ptr.is_null() { None } else { @@ -308,7 +321,7 @@ impl StrongRuleNode { source: StyleSource, importance: Importance) -> StrongRuleNode { let mut last = None; - for child in self.get().children.iter() { + for child in self.get().iter_children() { if child .get().importance == importance && child.get().source.as_ref().unwrap().ptr_equals(&source) { return child; @@ -316,25 +329,25 @@ impl StrongRuleNode { last = Some(child); } - let node = Box::new(RuleNode::new(root, - self.clone(), - source.clone(), - importance)); - let new_ptr = &*node as *const _ as *mut RuleNode; + let mut node = Box::new(RuleNode::new(root, + self.clone(), + source.clone(), + importance)); + let new_ptr: *mut RuleNode = &mut *node; loop { let strong; { - let next_ptr = match last { - Some(ref l) => &l.get().next, - None => &self.get().children.head, + let next_sibling_ptr = match last { + Some(ref l) => &l.get().next_sibling, + None => &self.get().first_child, }; let existing = - next_ptr.compare_and_swap(ptr::null_mut(), - new_ptr, - Ordering::SeqCst); + next_sibling_ptr.compare_and_swap(ptr::null_mut(), + new_ptr, + Ordering::SeqCst); if existing == ptr::null_mut() { // Now we know we're in the correct position in the child list, @@ -342,21 +355,22 @@ impl StrongRuleNode { // accessed again in a single-threaded manner when we're // sweeping possibly dead nodes. if let Some(ref l) = last { - node.prev.store(l.ptr(), Ordering::Relaxed); + node.prev_sibling.store(l.ptr(), Ordering::Relaxed); } return StrongRuleNode::new(node); } + // Existing is not null: some thread insert a child node since we accessed `last`. strong = WeakRuleNode { ptr: existing }.upgrade(); if strong.get().source.as_ref().unwrap().ptr_equals(&source) { - // Some thread that was racing with as inserted the same rule - // node than us, so give up and just use that. + // That node happens to be for the same style source, use that. return strong; } } + // Try again inserting after the new last child. last = Some(strong); } } @@ -479,40 +493,42 @@ impl Drop for StrongRuleNode { node.refcount.fetch_sub(1, Ordering::SeqCst) == 1 }; - if should_drop { - debug_assert_eq!(node.children.head.load(Ordering::SeqCst), - ptr::null_mut()); - if node.parent.is_none() { - debug!("Dropping root node!"); - // NOTE: Calling this is fine, because the rule tree root - // destructor needs to happen from the layout thread, where the - // stylist, and hence, the rule tree, is held. - unsafe { self.gc() }; - let _ = unsafe { Box::from_raw(self.ptr()) }; - return; - } - - // The node is already in the free list, so do nothing. - if node.next_free.load(Ordering::SeqCst) != ptr::null_mut() { - return; - } + if !should_drop { + return + } - let free_list = - &unsafe { &*node.root.as_ref().unwrap().ptr() }.next_free; - loop { - let next_free = free_list.load(Ordering::SeqCst); - debug_assert!(!next_free.is_null()); + debug_assert_eq!(node.first_child.load(Ordering::SeqCst), + ptr::null_mut()); + if node.parent.is_none() { + debug!("Dropping root node!"); + // NOTE: Calling this is fine, because the rule tree root + // destructor needs to happen from the layout thread, where the + // stylist, and hence, the rule tree, is held. + unsafe { self.gc() }; + let _ = unsafe { Box::from_raw(self.ptr()) }; + return; + } - node.next_free.store(next_free, Ordering::SeqCst); + // The node is already in the free list, so do nothing. + if node.next_free.load(Ordering::SeqCst) != ptr::null_mut() { + return; + } - let existing = - free_list.compare_and_swap(next_free, - self.ptr(), - Ordering::SeqCst); - if existing == next_free { - // Successfully inserted, yay! Otherwise try again. - break; - } + let free_list = + &unsafe { &*node.root.as_ref().unwrap().ptr() }.next_free; + loop { + let next_free = free_list.load(Ordering::SeqCst); + debug_assert!(!next_free.is_null()); + + node.next_free.store(next_free, Ordering::SeqCst); + + let existing = + free_list.compare_and_swap(next_free, + self.ptr(), + Ordering::SeqCst); + if existing == next_free { + // Successfully inserted, yay! Otherwise try again. + break; } } } @@ -542,32 +558,6 @@ impl WeakRuleNode { } } -struct RuleChildrenList { - head: AtomicPtr<RuleNode>, -} - -impl RuleChildrenList { - fn new() -> Self { - RuleChildrenList { - head: AtomicPtr::new(ptr::null_mut()) - } - } - - fn iter(&self) -> RuleChildrenListIter { - // FIXME(emilio): Fiddle with memory orderings. - let head = self.head.load(Ordering::SeqCst); - RuleChildrenListIter { - current: if head.is_null() { - None - } else { - Some(WeakRuleNode { - ptr: head, - }) - }, - } - } -} - struct RuleChildrenListIter { current: Option<WeakRuleNode>, } @@ -578,7 +568,7 @@ impl Iterator for RuleChildrenListIter { fn next(&mut self) -> Option<Self::Item> { self.current.take().map(|current| { let current = current.upgrade(); - self.current = current.next(); + self.current = current.next_sibling(); current }) } |