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::fmt;
|
||||
use std::ops::Deref;
|
||||
use stylearc::Arc;
|
||||
use stylearc::{Arc, UniqueArc};
|
||||
|
||||
use app_units::Au;
|
||||
#[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.
|
||||
Borrowed(&'a Arc<T>),
|
||||
/// 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>
|
||||
|
@ -2067,21 +2069,45 @@ impl<'a, T: 'a> StyleStructRef<'a, T>
|
|||
/// borrowed value, or returning the owned one.
|
||||
pub fn mutate(&mut self) -> &mut T {
|
||||
if let StyleStructRef::Borrowed(v) = *self {
|
||||
*self = StyleStructRef::Owned(Arc::new((**v).clone()));
|
||||
*self = StyleStructRef::Owned(UniqueArc::new((**v).clone()));
|
||||
}
|
||||
|
||||
match *self {
|
||||
StyleStructRef::Owned(ref mut v) => Arc::get_mut(v).unwrap(),
|
||||
StyleStructRef::Owned(ref mut v) => v,
|
||||
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
|
||||
/// hasn't been mutated.
|
||||
pub fn get_if_mutated(&mut self) -> Option<<&mut T> {
|
||||
match *self {
|
||||
StyleStructRef::Owned(ref mut v) => Some(Arc::get_mut(v).unwrap()),
|
||||
StyleStructRef::Owned(ref mut v) => Some(v),
|
||||
StyleStructRef::Borrowed(..) => None,
|
||||
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2089,8 +2115,9 @@ impl<'a, T: 'a> StyleStructRef<'a, T>
|
|||
/// appropriate.
|
||||
pub fn build(self) -> Arc<T> {
|
||||
match self {
|
||||
StyleStructRef::Owned(v) => v,
|
||||
StyleStructRef::Owned(v) => v.shareable(),
|
||||
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 {
|
||||
StyleStructRef::Owned(ref 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()
|
||||
}
|
||||
|
||||
/// 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,
|
||||
/// only if it's been mutated before.
|
||||
pub fn get_${style_struct.name_lower}_if_mutated(&mut self)
|
||||
|
|
|
@ -31,7 +31,7 @@ use std::convert::From;
|
|||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::atomic;
|
||||
use std::sync::atomic::Ordering::{Acquire, Relaxed, Release};
|
||||
|
||||
|
@ -71,6 +71,40 @@ pub struct Arc<T: ?Sized> {
|
|||
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> Sync for Arc<T> {}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue