2 use core
::marker
::PhantomData
;
3 use core
::mem
::ManuallyDrop
;
7 use super::{Arc, ArcBorrow}
;
9 /// An `Arc`, except it holds a pointer to the T instead of to the
12 /// An `OffsetArc<T>` has the same layout and ABI as a non-null
13 /// `const T*` in C, and may be used in FFI function signatures.
16 /// Arc<T> OffsetArc<T>
19 /// ---------------------
20 /// | RefCount | T (data) | [ArcInner<T>]
21 /// ---------------------
24 /// This means that this is a direct pointer to
25 /// its contained data (and can be read from by both C++ and Rust),
26 /// but we can also convert it to a "regular" `Arc<T>` by removing the offset.
28 /// This is very useful if you have an Arc-containing struct shared between Rust and C++,
29 /// and wish for C++ to be able to read the data behind the `Arc` without incurring
30 /// an FFI call overhead.
33 pub struct OffsetArc
<T
> {
34 pub(crate) ptr
: ptr
::NonNull
<T
>,
35 pub(crate) phantom
: PhantomData
<T
>,
38 unsafe impl<T
: Sync
+ Send
> Send
for OffsetArc
<T
> {}
39 unsafe impl<T
: Sync
+ Send
> Sync
for OffsetArc
<T
> {}
41 impl<T
> Deref
for OffsetArc
<T
> {
44 fn deref(&self) -> &Self::Target
{
45 unsafe { &*self.ptr.as_ptr() }
49 impl<T
> Clone
for OffsetArc
<T
> {
51 fn clone(&self) -> Self {
52 Arc
::into_raw_offset(self.clone_arc())
56 impl<T
> Drop
for OffsetArc
<T
> {
58 let _
= Arc
::from_raw_offset(OffsetArc
{
65 impl<T
: fmt
::Debug
> fmt
::Debug
for OffsetArc
<T
> {
66 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
67 fmt
::Debug
::fmt(&**self, f
)
71 impl<T
: PartialEq
> PartialEq
for OffsetArc
<T
> {
72 fn eq(&self, other
: &OffsetArc
<T
>) -> bool
{
76 #[allow(clippy::partialeq_ne_impl)]
77 fn ne(&self, other
: &OffsetArc
<T
>) -> bool
{
82 impl<T
> OffsetArc
<T
> {
83 /// Temporarily converts |self| into a bonafide Arc and exposes it to the
84 /// provided callback. The refcount is not modified.
86 pub fn with_arc
<F
, U
>(&self, f
: F
) -> U
88 F
: FnOnce(&Arc
<T
>) -> U
,
90 // Synthesize transient Arc, which never touches the refcount of the ArcInner.
91 let transient
= unsafe { ManuallyDrop::new(Arc::from_raw(self.ptr.as_ptr())) }
;
93 // Expose the transient Arc to the callback, which may clone it if it wants
94 // and forward the result to the user
98 /// If uniquely owned, provide a mutable reference
99 /// Else create a copy, and mutate that
101 /// This is functionally the same thing as `Arc::make_mut`
103 pub fn make_mut(&mut self) -> &mut T
108 // extract the OffsetArc as an owned variable
109 let this
= ptr
::read(self);
110 // treat it as a real Arc
111 let mut arc
= Arc
::from_raw_offset(this
);
112 // obtain the mutable reference. Cast away the lifetime
113 // This may mutate `arc`
114 let ret
= Arc
::make_mut(&mut arc
) as *mut _
;
115 // Store the possibly-mutated arc back inside, after converting
116 // it to a OffsetArc again
117 ptr
::write(self, Arc
::into_raw_offset(arc
));
122 /// Clone it as an `Arc`
124 pub fn clone_arc(&self) -> Arc
<T
> {
125 OffsetArc
::with_arc(self, |a
| a
.clone())
128 /// Produce a pointer to the data that can be converted back
131 pub fn borrow_arc(&self) -> ArcBorrow
<'_
, T
> {