mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Express unique ownership of arc in StyleStructRef, add vacated state
MozReview-Commit-ID: GwOw0HaC9S7
This commit is contained in:
parent
c85aae4abd
commit
dd3159f2f5
2 changed files with 79 additions and 7 deletions
|
@ -14,7 +14,7 @@ use std::borrow::Cow;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use stylearc::Arc;
|
use stylearc::{Arc, UniqueArc};
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
#[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA};
|
#[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA};
|
||||||
|
@ -2057,7 +2057,9 @@ pub enum StyleStructRef<'a, T: 'a> {
|
||||||
/// A borrowed struct from the parent, for example, for inheriting style.
|
/// A borrowed struct from the parent, for example, for inheriting style.
|
||||||
Borrowed(&'a Arc<T>),
|
Borrowed(&'a Arc<T>),
|
||||||
/// An owned struct, that we've already mutated.
|
/// An owned struct, that we've already mutated.
|
||||||
Owned(Arc<T>),
|
Owned(UniqueArc<T>),
|
||||||
|
/// Temporarily vacated, will panic if accessed
|
||||||
|
Vacated,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: 'a> StyleStructRef<'a, T>
|
impl<'a, T: 'a> StyleStructRef<'a, T>
|
||||||
|
@ -2067,21 +2069,45 @@ impl<'a, T: 'a> StyleStructRef<'a, T>
|
||||||
/// borrowed value, or returning the owned one.
|
/// borrowed value, or returning the owned one.
|
||||||
pub fn mutate(&mut self) -> &mut T {
|
pub fn mutate(&mut self) -> &mut T {
|
||||||
if let StyleStructRef::Borrowed(v) = *self {
|
if let StyleStructRef::Borrowed(v) = *self {
|
||||||
*self = StyleStructRef::Owned(Arc::new((**v).clone()));
|
*self = StyleStructRef::Owned(UniqueArc::new((**v).clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
StyleStructRef::Owned(ref mut v) => Arc::get_mut(v).unwrap(),
|
StyleStructRef::Owned(ref mut v) => v,
|
||||||
StyleStructRef::Borrowed(..) => unreachable!(),
|
StyleStructRef::Borrowed(..) => unreachable!(),
|
||||||
|
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract a unique Arc from this struct, vacating it.
|
||||||
|
///
|
||||||
|
/// The vacated state is a transient one, please put the Arc back
|
||||||
|
/// when done via `put()`. This function is to be used to separate
|
||||||
|
/// the struct being mutated from the computed context
|
||||||
|
pub fn take(&mut self) -> UniqueArc<T> {
|
||||||
|
use std::mem::replace;
|
||||||
|
let inner = replace(self, StyleStructRef::Vacated);
|
||||||
|
|
||||||
|
match inner {
|
||||||
|
StyleStructRef::Owned(arc) => arc,
|
||||||
|
StyleStructRef::Borrowed(arc) => UniqueArc::new((**arc).clone()),
|
||||||
|
StyleStructRef::Vacated => panic!("Accessed vacated style struct"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replace vacated ref with an arc
|
||||||
|
pub fn put(&mut self, arc: UniqueArc<T>) {
|
||||||
|
debug_assert!(matches!(*self, StyleStructRef::Vacated));
|
||||||
|
*self = StyleStructRef::Owned(arc);
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to the owned struct, or `None` if the struct
|
/// Get a mutable reference to the owned struct, or `None` if the struct
|
||||||
/// hasn't been mutated.
|
/// hasn't been mutated.
|
||||||
pub fn get_if_mutated(&mut self) -> Option<<&mut T> {
|
pub fn get_if_mutated(&mut self) -> Option<<&mut T> {
|
||||||
match *self {
|
match *self {
|
||||||
StyleStructRef::Owned(ref mut v) => Some(Arc::get_mut(v).unwrap()),
|
StyleStructRef::Owned(ref mut v) => Some(v),
|
||||||
StyleStructRef::Borrowed(..) => None,
|
StyleStructRef::Borrowed(..) => None,
|
||||||
|
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2089,8 +2115,9 @@ impl<'a, T: 'a> StyleStructRef<'a, T>
|
||||||
/// appropriate.
|
/// appropriate.
|
||||||
pub fn build(self) -> Arc<T> {
|
pub fn build(self) -> Arc<T> {
|
||||||
match self {
|
match self {
|
||||||
StyleStructRef::Owned(v) => v,
|
StyleStructRef::Owned(v) => v.shareable(),
|
||||||
StyleStructRef::Borrowed(v) => v.clone(),
|
StyleStructRef::Borrowed(v) => v.clone(),
|
||||||
|
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2102,6 +2129,7 @@ impl<'a, T: 'a> Deref for StyleStructRef<'a, T> {
|
||||||
match *self {
|
match *self {
|
||||||
StyleStructRef::Owned(ref v) => &**v,
|
StyleStructRef::Owned(ref v) => &**v,
|
||||||
StyleStructRef::Borrowed(v) => &**v,
|
StyleStructRef::Borrowed(v) => &**v,
|
||||||
|
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2183,6 +2211,16 @@ impl<'a> StyleBuilder<'a> {
|
||||||
self.${style_struct.ident}.mutate()
|
self.${style_struct.ident}.mutate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a mutable view of the current `${style_struct.name}` style.
|
||||||
|
pub fn take_${style_struct.name_lower}(&mut self) -> UniqueArc<style_structs::${style_struct.name}> {
|
||||||
|
self.${style_struct.ident}.take()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a mutable view of the current `${style_struct.name}` style.
|
||||||
|
pub fn put_${style_struct.name_lower}(&mut self, s: UniqueArc<style_structs::${style_struct.name}>) {
|
||||||
|
self.${style_struct.ident}.put(s)
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a mutable view of the current `${style_struct.name}` style,
|
/// Gets a mutable view of the current `${style_struct.name}` style,
|
||||||
/// only if it's been mutated before.
|
/// only if it's been mutated before.
|
||||||
pub fn get_${style_struct.name_lower}_if_mutated(&mut self)
|
pub fn get_${style_struct.name_lower}_if_mutated(&mut self)
|
||||||
|
|
|
@ -31,7 +31,7 @@ use std::convert::From;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Deref;
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::atomic;
|
use std::sync::atomic;
|
||||||
use std::sync::atomic::Ordering::{Acquire, Relaxed, Release};
|
use std::sync::atomic::Ordering::{Acquire, Relaxed, Release};
|
||||||
|
|
||||||
|
@ -71,6 +71,40 @@ pub struct Arc<T: ?Sized> {
|
||||||
ptr: *mut ArcInner<T>,
|
ptr: *mut ArcInner<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An Arc that is known to be uniquely owned
|
||||||
|
///
|
||||||
|
/// This lets us build arcs that we can mutate before
|
||||||
|
/// freezing, without needing to change the allocation
|
||||||
|
pub struct UniqueArc<T: ?Sized>(Arc<T>);
|
||||||
|
|
||||||
|
impl<T> UniqueArc<T> {
|
||||||
|
#[inline]
|
||||||
|
/// Construct a new UniqueArc
|
||||||
|
pub fn new(data: T) -> Self {
|
||||||
|
UniqueArc(Arc::new(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Convert to a shareable Arc<T> once we're done using it
|
||||||
|
pub fn shareable(self) -> Arc<T> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Deref for UniqueArc<T> {
|
||||||
|
type Target = T;
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&*self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> DerefMut for UniqueArc<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
// We know this to be uniquely owned
|
||||||
|
unsafe { &mut (*self.0.ptr).data }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
|
unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
|
||||||
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
|
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue