mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
stylo: Make Servo Arc types use ptr to T instead of ptr to ArcInner<T>
This commit is contained in:
parent
808b1f509b
commit
74519cc1a7
12 changed files with 203 additions and 81 deletions
|
@ -194,6 +194,30 @@ impl<T> Arc<T> {
|
|||
p: NonZeroPtrMut::new(ptr as *mut ArcInner<T>),
|
||||
}
|
||||
}
|
||||
|
||||
/// Produce a pointer to the data that can be converted back
|
||||
/// to an arc
|
||||
pub fn borrow_arc<'a>(&'a self) -> ArcBorrow<'a, T> {
|
||||
ArcBorrow(&**self)
|
||||
}
|
||||
/// Temporarily converts |self| into a bonafide RawOffsetArc and exposes it to the
|
||||
/// provided callback. The refcount is not modified.
|
||||
#[inline(always)]
|
||||
pub fn with_raw_offset_arc<F, U>(&self, f: F) -> U
|
||||
where F: FnOnce(&RawOffsetArc<T>) -> U
|
||||
{
|
||||
// Synthesize transient Arc, which never touches the refcount of the ArcInner.
|
||||
let transient = unsafe { NoDrop::new(Arc::into_raw_offset(ptr::read(self))) };
|
||||
|
||||
// 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.
|
||||
mem::forget(transient);
|
||||
|
||||
// Forward the result.
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
|
@ -717,6 +741,7 @@ impl<H: Eq + 'static, T: Eq + 'static> Eq for ThinArc<H, 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
|
||||
#[derive(Eq)]
|
||||
pub struct RawOffsetArc<T: 'static> {
|
||||
ptr: NonZeroPtrMut<T>,
|
||||
}
|
||||
|
@ -733,7 +758,7 @@ impl<T: 'static> Deref for RawOffsetArc<T> {
|
|||
|
||||
impl<T: 'static> Clone for RawOffsetArc<T> {
|
||||
fn clone(&self) -> Self {
|
||||
RawOffsetArc::with_arc(self, |a| Arc::into_raw_offset(a.clone()))
|
||||
Arc::into_raw_offset(self.clone_arc())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,6 +775,16 @@ impl<T: fmt::Debug + 'static> fmt::Debug for RawOffsetArc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for RawOffsetArc<T> {
|
||||
fn eq(&self, other: &RawOffsetArc<T>) -> bool {
|
||||
*(*self) == *(*other)
|
||||
}
|
||||
|
||||
fn ne(&self, other: &RawOffsetArc<T>) -> bool {
|
||||
*(*self) != *(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> RawOffsetArc<T> {
|
||||
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
|
||||
/// provided callback. The refcount is not modified.
|
||||
|
@ -789,6 +824,17 @@ impl<T: 'static> RawOffsetArc<T> {
|
|||
&mut *ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Clone it as an Arc
|
||||
pub fn clone_arc(&self) -> Arc<T> {
|
||||
RawOffsetArc::with_arc(self, |a| a.clone())
|
||||
}
|
||||
|
||||
/// Produce a pointer to the data that can be converted back
|
||||
/// to an arc
|
||||
pub fn borrow_arc<'a>(&'a self) -> ArcBorrow<'a, T> {
|
||||
ArcBorrow(&**self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> Arc<T> {
|
||||
|
@ -811,6 +857,62 @@ impl<T: 'static> Arc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A "borrowed Arc". This is a pointer to
|
||||
/// a T that is known to have been allocated within an
|
||||
/// Arc.
|
||||
///
|
||||
/// This is equivalent in guarantees to `&Arc<T>`, however it is
|
||||
/// a bit more flexible. To obtain an `&Arc<T>` you must have
|
||||
/// an Arc<T> instance somewhere pinned down until we're done with it.
|
||||
///
|
||||
/// However, Gecko hands us refcounted things as pointers to T directly,
|
||||
/// so we have to conjure up a temporary Arc on the stack each time. The
|
||||
/// same happens for when the object is managed by a RawOffsetArc.
|
||||
///
|
||||
/// ArcBorrow lets us deal with borrows of known-refcounted objects
|
||||
/// without needing to worry about how they're actually stored.
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct ArcBorrow<'a, T: 'a>(&'a T);
|
||||
|
||||
impl<'a, T> Copy for ArcBorrow<'a, T> {}
|
||||
impl<'a, T> Clone for ArcBorrow<'a, T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ArcBorrow<'a, T> {
|
||||
pub fn clone_arc(&self) -> Arc<T> {
|
||||
let arc = unsafe { Arc::from_raw(self.0) };
|
||||
// addref it!
|
||||
mem::forget(arc.clone());
|
||||
arc
|
||||
}
|
||||
|
||||
pub fn with_arc<F, U>(&self, f: F) -> U where F: FnOnce(&Arc<T>) -> U, T: 'static {
|
||||
// Synthesize transient Arc, which never touches the refcount.
|
||||
let transient = unsafe { NoDrop::new(Arc::from_raw(self.0)) };
|
||||
|
||||
// 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<'a, T> Deref for ArcBorrow<'a, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
&*self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::clone::Clone;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue