Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions src/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,27 +108,6 @@ impl<T> Arc<T> {
f(&transient)
}

/// Converts an `Arc` into a `OffsetArc`. This consumes the `Arc`, so the refcount
/// is not modified.
#[inline]
pub fn into_raw_offset(a: Self) -> OffsetArc<T> {
unsafe {
OffsetArc {
ptr: ptr::NonNull::new_unchecked(Arc::into_raw(a) as *mut T),
phantom: PhantomData,
}
}
}

/// Converts a `OffsetArc` into an `Arc`. This consumes the `OffsetArc`, so the refcount
/// is not modified.
#[inline]
pub fn from_raw_offset(a: OffsetArc<T>) -> Self {
let a = ManuallyDrop::new(a);
let ptr = a.ptr.as_ptr();
unsafe { Arc::from_raw(ptr) }
}

/// Returns the inner value, if the [`Arc`] has exactly one strong reference.
///
/// Otherwise, an [`Err`] is returned with the same [`Arc`] that was
Expand Down Expand Up @@ -266,6 +245,27 @@ impl<T: ?Sized> Arc<T> {
Arc::from_raw_inner(arc_inner_ptr as *mut ArcInner<T>)
}

/// Converts a `OffsetArc` into an `Arc`. This consumes the `OffsetArc`, so the refcount
/// is not modified.
#[inline]
pub fn from_raw_offset(a: OffsetArc<T>) -> Self {
let a = ManuallyDrop::new(a);
let ptr = a.ptr.as_ptr();
unsafe { Arc::from_raw(ptr) }
}

/// Converts an `Arc` into a `OffsetArc`. This consumes the `Arc`, so the refcount
/// is not modified.
#[inline]
pub fn into_raw_offset(a: Self) -> OffsetArc<T> {
unsafe {
OffsetArc {
ptr: ptr::NonNull::new_unchecked(Arc::into_raw(a) as *mut T),
phantom: PhantomData,
}
}
}

/// Returns the raw pointer.
///
/// Same as into_raw except `self` isn't consumed.
Expand Down
54 changes: 29 additions & 25 deletions src/offset_arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,34 @@ use super::{Arc, ArcBorrow};
/// This is very useful if you have an Arc-containing struct shared between Rust and C++,
/// and wish for C++ to be able to read the data behind the `Arc` without incurring
/// an FFI call overhead.
#[derive(Eq)]
#[repr(transparent)]
pub struct OffsetArc<T> {
pub struct OffsetArc<T: ?Sized> {
pub(crate) ptr: ptr::NonNull<T>,
pub(crate) phantom: PhantomData<T>,
}

unsafe impl<T: Sync + Send> Send for OffsetArc<T> {}
unsafe impl<T: Sync + Send> Sync for OffsetArc<T> {}
unsafe impl<T: ?Sized + Sync + Send> Send for OffsetArc<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for OffsetArc<T> {}

impl<T: RefUnwindSafe> UnwindSafe for OffsetArc<T> {}
impl<T: ?Sized + RefUnwindSafe> UnwindSafe for OffsetArc<T> {}

impl<T> Deref for OffsetArc<T> {
impl<T: ?Sized> Deref for OffsetArc<T> {
type Target = T;

#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr.as_ptr() }
}
}

impl<T> Clone for OffsetArc<T> {
impl<T: ?Sized> Clone for OffsetArc<T> {
#[inline]
fn clone(&self) -> Self {
Arc::into_raw_offset(self.clone_arc())
}
}

impl<T> Drop for OffsetArc<T> {
impl<T: ?Sized> Drop for OffsetArc<T> {
fn drop(&mut self) {
let _ = Arc::from_raw_offset(OffsetArc {
ptr: self.ptr,
Expand All @@ -65,13 +65,13 @@ impl<T> Drop for OffsetArc<T> {
}
}

impl<T: fmt::Debug> fmt::Debug for OffsetArc<T> {
impl<T: ?Sized + fmt::Debug> fmt::Debug for OffsetArc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}

impl<T: PartialEq> PartialEq for OffsetArc<T> {
impl<T: ?Sized + PartialEq> PartialEq for OffsetArc<T> {
fn eq(&self, other: &OffsetArc<T>) -> bool {
*(*self) == *(*other)
}
Expand All @@ -82,22 +82,9 @@ impl<T: PartialEq> PartialEq for OffsetArc<T> {
}
}

impl<T> OffsetArc<T> {
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
/// provided callback. The refcount is not modified.
#[inline]
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 { ManuallyDrop::new(Arc::from_raw(self.ptr.as_ptr())) };

// Expose the transient Arc to the callback, which may clone it if it wants
// and forward the result to the user
f(&transient)
}
impl<T: ?Sized + Eq> Eq for OffsetArc<T> {}

impl<T> OffsetArc<T> {
/// If uniquely owned, provide a mutable reference
/// Else create a copy, and mutate that
///
Expand Down Expand Up @@ -125,6 +112,23 @@ impl<T> OffsetArc<T> {
&mut *ret
}
}
}

impl<T: ?Sized> OffsetArc<T> {
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
/// provided callback. The refcount is not modified.
#[inline]
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 { ManuallyDrop::new(Arc::from_raw(self.ptr.as_ptr())) };

// Expose the transient Arc to the callback, which may clone it if it wants
// and forward the result to the user
f(&transient)
}

/// Clone it as an `Arc`
#[inline]
Expand Down
Loading