Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stylo: Fuse ServoStyleContext and ServoComputedValues #17767

Merged
merged 16 commits into from Jul 18, 2017
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

stylo: Add RawOffsetArc<T>

  • Loading branch information
Manishearth committed Jul 18, 2017
commit d1c235d7b70b8a0273dd0e4eb422256267faeb1c
@@ -637,6 +637,8 @@ impl<H: 'static, T: 'static> ThinArc<H, T> {
let result = f(&transient);

// Forget the transient Arc to leave the refcount untouched.
// XXXManishearth this can be removed when unions stabilize,
// since then NoDrop becomes zero overhead
mem::forget(transient);

// Forward the result.
@@ -700,6 +702,95 @@ impl<H: PartialEq + 'static, T: PartialEq + 'static> PartialEq for ThinArc<H, T>

impl<H: Eq + 'static, T: Eq + 'static> Eq for ThinArc<H, T> {}

/// An Arc, except it holds a pointer to the T instead of to the
/// entire ArcInner.
///
/// ```text
/// Arc<T> RawOffsetArc<T>
/// | |
/// v v
/// ---------------------
/// | RefCount | T (data) | [ArcInner<T>]
/// ---------------------
/// ```
///
/// This means that this is a direct pointer to
/// its contained data (and can be read from by both C++ and Rust),
/// but we can also convert it to a "regular" Arc<T> by removing the offset
pub struct RawOffsetArc<T: 'static> {
ptr: NonZeroPtrMut<T>,
}

unsafe impl<T: 'static + Sync + Send> Send for RawOffsetArc<T> {}
unsafe impl<T: 'static + Sync + Send> Sync for RawOffsetArc<T> {}

impl<T: 'static> Deref for RawOffsetArc<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr.ptr() }
}
}

impl<T: 'static> Clone for RawOffsetArc<T> {
fn clone(&self) -> Self {
RawOffsetArc::with_arc(self, |a| Arc::into_raw_offset(a.clone()))
}
}

impl<T: 'static> Drop for RawOffsetArc<T> {
fn drop(&mut self) {
let _ = Arc::from_raw_offset(RawOffsetArc { ptr: self.ptr.clone() });
}
}


impl<T: fmt::Debug + 'static> fmt::Debug for RawOffsetArc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}

impl<T: 'static> RawOffsetArc<T> {
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
/// provided callback. The refcount is not modified.
#[inline(always)]
pub fn with_arc<F, U>(&self, f: F) -> U
where F: FnOnce(&Arc<T>) -> U
{
// Synthesize transient Arc, which never touches the refcount of the ArcInner.
let transient = unsafe { NoDrop::new(Arc::from_raw(self.ptr.ptr())) };

// Expose the transient Arc to the callback, which may clone it if it wants.
let result = f(&transient);

// Forget the transient Arc to leave the refcount untouched.
// XXXManishearth this can be removed when unions stabilize,
// since then NoDrop becomes zero overhead
mem::forget(transient);

// Forward the result.
result
}
}

impl<T: 'static> Arc<T> {
/// Converts an Arc into a RawOffsetArc. This consumes the Arc, so the refcount
/// is not modified.
pub fn into_raw_offset(a: Self) -> RawOffsetArc<T> {
RawOffsetArc {
ptr: NonZeroPtrMut::new(Arc::into_raw(a) as *mut T),
}
}

/// Converts a RawOffsetArc into an Arc. This consumes the RawOffsetArc, so the refcount
/// is not modified.
pub fn from_raw_offset(a: RawOffsetArc<T>) -> Self {
let ptr = a.ptr.ptr();
mem::forget(a);
unsafe { Arc::from_raw(ptr) }
}
}

#[cfg(test)]
mod tests {
use std::clone::Clone;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.