Remove CowArc and use the new Arc::make_unique() method instead.

This commit is contained in:
Simon Sapin 2014-05-23 15:45:07 +01:00
parent f01bfc7db9
commit 20c72c8ccb
4 changed files with 37 additions and 124 deletions

View file

@ -5,10 +5,10 @@
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use servo_util::cowarc::CowArc;
use servo_util::geometry::{Au, max, min};
use std::i32;
use style::computed_values::float;
use sync::Arc;
/// The kind of float: left or right.
#[deriving(Clone)]
@ -69,7 +69,7 @@ impl FloatList {
/// FIXME(pcwalton): When we have fast `MutexArc`s, try removing `CowArc` and use a mutex instead.
#[deriving(Clone)]
struct FloatListRef {
list: Option<CowArc<FloatList>>,
list: Option<Arc<FloatList>>,
}
impl FloatListRef {
@ -89,16 +89,17 @@ impl FloatListRef {
fn get<'a>(&'a self) -> Option<&'a FloatList> {
match self.list {
None => None,
Some(ref list) => Some(list.get()),
Some(ref list) => Some(&**list),
}
}
#[allow(experimental)]
#[inline]
fn get_mut<'a>(&'a mut self) -> &'a mut FloatList {
if self.list.is_none() {
self.list = Some(CowArc::new(FloatList::new()))
self.list = Some(Arc::new(FloatList::new()))
}
self.list.as_mut().unwrap().get_mut()
self.list.as_mut().unwrap().make_unique()
}
}

View file

@ -10,7 +10,6 @@ use serialize::{Encodable, Encoder};
pub use servo_util::url::parse_url;
use sync::Arc;
pub use url::Url;
use servo_util::cowarc::CowArc;
pub use cssparser::*;
pub use cssparser::ast::*;
@ -1577,10 +1576,10 @@ pub mod style_structs {
% endfor
}
#[deriving(Eq, Clone)]
#[deriving(Clone)]
pub struct ComputedValues {
% for style_struct in STYLE_STRUCTS:
${style_struct.ident}: CowArc<style_structs::${style_struct.name}>,
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
% endfor
shareable: bool,
}
@ -1603,7 +1602,7 @@ impl ComputedValues {
% for style_struct in STYLE_STRUCTS:
pub fn get_${style_struct.name.lower()}
<'a>(&'a self) -> &'a style_structs::${style_struct.name} {
self.${style_struct.ident}.get()
&*self.${style_struct.ident}
}
% endfor
}
@ -1612,7 +1611,7 @@ impl ComputedValues {
lazy_init! {
static ref INITIAL_VALUES: ComputedValues = ComputedValues {
% for style_struct in STYLE_STRUCTS:
${style_struct.ident}: CowArc::new(style_structs::${style_struct.name} {
${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
% for longhand in style_struct.longhands:
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
% endfor
@ -1622,6 +1621,20 @@ lazy_init! {
};
}
/// This only exists to limit the scope of #[allow(experimental)]
/// FIXME: remove this when Arc::make_unique() is not experimental anymore.
trait ArcExperimental<T> {
fn make_unique_experimental<'a>(&'a mut self) -> &'a mut T;
}
impl<T: Send + Share + Clone> ArcExperimental<T> for Arc<T> {
#[inline]
#[allow(experimental)]
fn make_unique_experimental<'a>(&'a mut self) -> &'a mut T {
self.make_unique()
}
}
/// Fast path for the function below. Only computes new inherited styles.
fn cascade_with_cached_declarations(applicable_declarations: &[MatchedProperty],
shareable: bool,
@ -1667,18 +1680,18 @@ fn cascade_with_cached_declarations(applicable_declarations: &[MatchedProperty],
//
// FIXME: is it still?
parent_style.${style_struct.ident}
.get()
.${property.ident}
.clone()
}
};
style_${style_struct.ident}.get_mut().${property.ident} =
computed_value;
style_${style_struct.ident}.make_unique_experimental()
.${property.ident} = computed_value;
% if property.name in DERIVED_LONGHANDS:
% for derived in DERIVED_LONGHANDS[property.name]:
style_${derived.style_struct.ident}.get_mut()
.${derived.ident} =
style_${derived.style_struct.ident}
.make_unique_experimental()
.${derived.ident} =
longhands::${derived.ident}
::derive_from_${property.ident}(
computed_value,
@ -1870,18 +1883,18 @@ pub fn cascade(applicable_declarations: &[MatchedProperty],
// FIXME: is it still?
cacheable = false;
inherited_style.${style_struct.ident}
.get()
.${property.ident}
.clone()
}
};
style_${style_struct.ident}.get_mut().${property.ident} =
computed_value;
style_${style_struct.ident}.make_unique_experimental()
.${property.ident} = computed_value;
% if property.name in DERIVED_LONGHANDS:
% for derived in DERIVED_LONGHANDS[property.name]:
style_${derived.style_struct.ident}.get_mut()
.${derived.ident} =
style_${derived.style_struct.ident}
.make_unique_experimental()
.${derived.ident} =
longhands::${derived.ident}
::derive_from_${property.ident}(
computed_value,
@ -1902,7 +1915,7 @@ pub fn cascade(applicable_declarations: &[MatchedProperty],
// The initial value of border-*-width may be changed at computed value time.
{
let border = style_border.get_mut();
let border = style_border.make_unique_experimental();
% for side in ["top", "right", "bottom", "left"]:
// Like calling to_computed_value, which wouldn't type check.
if !context.border_${side}_present {
@ -1913,7 +1926,7 @@ pub fn cascade(applicable_declarations: &[MatchedProperty],
// The initial value of display may be changed at computed value time.
if !seen.get_display() {
let box_ = style_box_.get_mut();
let box_ = style_box_.make_unique_experimental();
box_.display = longhands::display::to_computed_value(box_.display, &context);
}
@ -1945,7 +1958,7 @@ pub fn cascade_anonymous(parent_style: &ComputedValues) -> ComputedValues {
shareable: false,
};
{
let border = result.border.get_mut();
let border = result.border.make_unique_experimental();
% for side in ["top", "right", "bottom", "left"]:
// Like calling to_computed_value, which wouldn't type check.
border.border_${side}_width = Au(0);

View file

@ -1,100 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! An atomically reference counted type that copies itself on mutation.
use std::cast;
use std::ptr;
use std::sync::atomics::{AtomicUint, SeqCst};
struct CowArcAlloc<T> {
ref_count: AtomicUint,
data: T,
}
#[unsafe_no_drop_flag]
pub struct CowArc<T> {
ptr: *mut CowArcAlloc<T>,
}
#[unsafe_destructor]
impl<T> Drop for CowArc<T> {
#[inline]
fn drop(&mut self) {
unsafe {
if self.ptr != ptr::mut_null() && (*self.ptr).ref_count.fetch_sub(1, SeqCst) == 1 {
let _kill_it: Box<CowArcAlloc<T>> = cast::transmute(self.ptr);
self.ptr = ptr::mut_null()
}
}
}
}
impl<T:Eq + Clone> Eq for CowArc<T> {
fn eq(&self, other: &CowArc<T>) -> bool {
self.get() == other.get()
}
}
impl<T:Clone> Clone for CowArc<T> {
#[inline]
fn clone(&self) -> CowArc<T> {
unsafe {
drop((*self.ptr).ref_count.fetch_add(1, SeqCst));
}
CowArc {
ptr: self.ptr
}
}
}
impl<T:Clone> CowArc<T> {
#[inline]
pub fn new(value: T) -> CowArc<T> {
let alloc = box CowArcAlloc {
ref_count: AtomicUint::new(1),
data: value,
};
unsafe {
CowArc {
ptr: cast::transmute(alloc),
}
}
}
#[inline]
pub fn shared(&self) -> bool {
unsafe {
(*self.ptr).ref_count.load(SeqCst) != 1
}
}
#[inline]
pub fn get<'a>(&'a self) -> &'a T {
unsafe {
cast::transmute(&(*self.ptr).data)
}
}
#[inline(always)]
pub fn get_mut<'a>(&'a mut self) -> &'a mut T {
unsafe {
if (*self.ptr).ref_count.load(SeqCst) == 1 {
return cast::transmute(&mut (*self.ptr).data)
}
let copy = box CowArcAlloc {
ref_count: AtomicUint::new(1),
data: (*self.ptr).data.clone(),
};
*self = CowArc {
ptr: cast::transmute(copy),
};
cast::transmute(&mut (*self.ptr).data)
}
}
}

View file

@ -26,7 +26,6 @@ extern crate std_url = "url";
pub mod cache;
pub mod concurrentmap;
pub mod cowarc;
pub mod debug;
pub mod geometry;
pub mod namespace;