abi_stable/std_types/
arc.rs
1use std::{borrow::Borrow, marker::PhantomData, mem::ManuallyDrop, sync::Arc};
4
5use core_extensions::SelfOps;
6
7use crate::{
8 abi_stability::StableAbi,
9 marker_type::ErasedPrefix,
10 pointer_trait::{
11 AsPtr, CallReferentDrop, CanTransmuteElement, GetPointerKind, PK_SmartPointer,
12 },
13 prefix_type::{PrefixRef, WithMetadata},
14 std_types::{
15 utypeid::{new_utypeid, UTypeId},
16 RResult,
17 },
18};
19
20#[cfg(all(test, not(feature = "only_new_tests")))]
21mod test;
22
23mod private {
24 use super::*;
25
26 #[derive(StableAbi)]
74 #[repr(C)]
75 pub struct RArc<T> {
76 data: *const T,
77 #[sabi(unsafe_change_type = ArcVtable_Ref<T>)]
78 vtable: PrefixRef<ErasedPrefix>,
79 _marker: PhantomData<T>,
80 }
81
82 impl_from_rust_repr! {
83 impl[T] From<Arc<T>> for RArc<T> {
84 fn(this){
85 RArc {
86 data: Arc::into_raw(this),
87 vtable: unsafe{ VTableGetter::<T>::LIB_VTABLE.0.cast() },
88 _marker: Default::default(),
89 }
90 }
91 }
92 }
93
94 unsafe impl<T> GetPointerKind for RArc<T> {
95 type Kind = PK_SmartPointer;
96
97 type PtrTarget = T;
98 }
99
100 unsafe impl<T> AsPtr for RArc<T> {
101 fn as_ptr(&self) -> *const T {
102 self.data
103 }
104 }
105
106 unsafe impl<T, O> CanTransmuteElement<O> for RArc<T> {
107 type TransmutedPtr = RArc<O>;
108
109 unsafe fn transmute_element_(self) -> Self::TransmutedPtr {
110 unsafe { core_extensions::utils::transmute_ignore_size(self) }
111 }
112 }
113
114 impl<T> RArc<T> {
115 #[inline(always)]
116 pub(super) const fn data(&self) -> *const T {
117 self.data
118 }
119
120 #[inline(always)]
121 pub(super) unsafe fn data_mut(&mut self) -> *mut T {
122 self.data as *mut T
123 }
124
125 #[inline]
126 pub(crate) fn into_raw(self) -> *const T {
127 let this = ManuallyDrop::new(self);
128 this.data
129 }
130
131 #[inline(always)]
132 pub(crate) const fn vtable(&self) -> ArcVtable_Ref<T> {
133 unsafe { ArcVtable_Ref::<T>(self.vtable.cast()) }
134 }
135
136 #[allow(dead_code)]
137 #[cfg(test)]
138 pub(super) fn set_vtable_for_testing(&mut self) {
139 self.vtable = unsafe { VTableGetter::<T>::LIB_VTABLE_FOR_TESTING.0.cast() };
140 }
141 }
142}
143
144pub use self::private::RArc;
145
146impl<T> RArc<T> {
147 pub fn new(this: T) -> Self {
158 Arc::new(this).into()
159 }
160
161 pub fn into_arc(this: Self) -> Arc<T>
186 where
187 T: Clone,
188 {
189 let this_vtable = this.vtable();
190 let other_vtable = VTableGetter::LIB_VTABLE;
191 if ::std::ptr::eq(this_vtable.0.to_raw_ptr(), other_vtable.0.to_raw_ptr())
192 || this_vtable.type_id()() == other_vtable.type_id()()
193 {
194 unsafe { Arc::from_raw(this.into_raw()) }
195 } else {
196 Self::try_unwrap(this)
197 .unwrap_or_else(|x| T::clone(&x))
198 .piped(Arc::new)
199 }
200 }
201
202 #[inline]
219 pub fn try_unwrap(this: Self) -> Result<T, Self> {
220 let vtable = this.vtable();
221 unsafe { (vtable.try_unwrap())(this).into_result() }
222 }
223
224 #[inline]
242 pub fn get_mut(this: &mut Self) -> Option<&mut T> {
243 let vtable = this.vtable();
244 unsafe { (vtable.get_mut())(this) }
245 }
246
247 #[inline]
276 pub fn make_mut(this: &mut Self) -> &mut T
277 where
278 T: Clone,
279 {
280 let unbounded_this = unsafe { &mut *(this as *mut Self) };
283 match Self::get_mut(unbounded_this) {
284 Some(x) => x,
285 None => {
286 let new_arc = RArc::new((**this).clone());
287 *this = new_arc;
288 unsafe { &mut *this.data_mut() }
290 }
291 }
292 }
293
294 pub fn strong_count(this: &Self) -> usize {
309 let vtable = this.vtable();
310 unsafe { vtable.strong_count()(this) }
311 }
312
313 pub fn weak_count(this: &Self) -> usize {
333 let vtable = this.vtable();
334 unsafe { vtable.weak_count()(this) }
335 }
336}
337
338impl<T> Borrow<T> for RArc<T> {
341 fn borrow(&self) -> &T {
342 self
343 }
344}
345
346impl<T> AsRef<T> for RArc<T> {
347 fn as_ref(&self) -> &T {
348 self
349 }
350}
351
352impl<T> Default for RArc<T>
355where
356 T: Default,
357{
358 fn default() -> Self {
359 RArc::new(T::default())
360 }
361}
362
363impl<T> Clone for RArc<T> {
364 fn clone(&self) -> Self {
365 unsafe { (self.vtable().clone_())(self) }
366 }
367}
368
369impl_into_rust_repr! {
370 impl[T] Into<Arc<T>> for RArc<T>
371 where[
372 T: Clone+StableAbi,
373 ]{
374 fn(this){
375 RArc::into_arc(this)
376 }
377 }
378}
379
380impl<T> Drop for RArc<T> {
381 fn drop(&mut self) {
382 unsafe {
385 let vtable = self.vtable();
386 (vtable.destructor())(self.data() as *const T, CallReferentDrop::Yes);
387 }
388 }
389}
390
391shared_impls! {pointer
392 mod = arc_impls
393 new_type = RArc[][T],
394 original_type = Arc,
395}
396
397unsafe impl<T> Sync for RArc<T> where T: Send + Sync {}
398
399unsafe impl<T> Send for RArc<T> where T: Send + Sync {}
400
401impl<T> Unpin for RArc<T> {}
402
403mod vtable_mod {
406 use super::*;
407
408 pub(super) struct VTableGetter<'a, T>(&'a T);
409
410 impl<'a, T: 'a> VTableGetter<'a, T> {
411 const DEFAULT_VTABLE: ArcVtable<T> = ArcVtable {
412 type_id: new_utypeid::<RArc<()>>,
413 destructor: destructor_arc::<T>,
414 clone_: clone_arc::<T>,
415 get_mut: get_mut_arc::<T>,
416 try_unwrap: try_unwrap_arc::<T>,
417 strong_count: strong_count_arc::<T>,
418 weak_count: weak_count_arc::<T>,
419 };
420
421 staticref! {
422 const WM_DEFAULT: WithMetadata<ArcVtable<T>> =
423 WithMetadata::new(Self::DEFAULT_VTABLE)
424 }
425
426 pub(super) const LIB_VTABLE: ArcVtable_Ref<T> =
428 { ArcVtable_Ref(Self::WM_DEFAULT.as_prefix()) };
429
430 #[cfg(test)]
431 staticref! {const WM_FOR_TESTING: WithMetadata<ArcVtable<T>> =
432 WithMetadata::new(
433 ArcVtable{
434 type_id: new_utypeid::<RArc<i32>>,
435 ..Self::DEFAULT_VTABLE
436 }
437 )
438 }
439
440 #[cfg(test)]
441 pub(super) const LIB_VTABLE_FOR_TESTING: ArcVtable_Ref<T> =
442 { ArcVtable_Ref(Self::WM_FOR_TESTING.as_prefix()) };
443 }
444
445 #[derive(StableAbi)]
446 #[repr(C)]
447 #[sabi(kind(Prefix))]
448 #[sabi(missing_field(panic))]
449 pub struct ArcVtable<T> {
450 pub(super) type_id: extern "C" fn() -> UTypeId,
451 pub(super) destructor: unsafe extern "C" fn(*const T, CallReferentDrop),
452 pub(super) clone_: unsafe extern "C" fn(&RArc<T>) -> RArc<T>,
453 pub(super) get_mut: unsafe extern "C" fn(&mut RArc<T>) -> Option<&mut T>,
454 pub(super) try_unwrap: unsafe extern "C" fn(RArc<T>) -> RResult<T, RArc<T>>,
455 pub(super) strong_count: unsafe extern "C" fn(&RArc<T>) -> usize,
456 #[sabi(last_prefix_field)]
457 pub(super) weak_count: unsafe extern "C" fn(&RArc<T>) -> usize,
458 }
459
460 unsafe extern "C" fn destructor_arc<T>(this: *const T, call_drop: CallReferentDrop) {
461 extern_fn_panic_handling! {no_early_return; unsafe {
462 if call_drop == CallReferentDrop::Yes {
463 drop(Arc::from_raw(this));
464 } else {
465 drop(Arc::from_raw(this as *const ManuallyDrop<T>));
466 }
467 }}
468 }
469
470 unsafe fn with_arc_ref<T, F, R>(this: &RArc<T>, f: F) -> R
471 where
472 F: FnOnce(&Arc<T>) -> R,
473 {
474 let x = this.data();
475 let x = unsafe { Arc::from_raw(x) };
476 let x = ManuallyDrop::new(x);
477 f(&x)
478 }
479
480 unsafe extern "C" fn clone_arc<T>(this: &RArc<T>) -> RArc<T> {
481 unsafe { with_arc_ref(this, |x| Arc::clone(x).into()) }
482 }
483
484 unsafe extern "C" fn get_mut_arc<'a, T>(this: &'a mut RArc<T>) -> Option<&'a mut T> {
485 let arc = unsafe { Arc::from_raw(this.data()) };
486 let mut arc = ManuallyDrop::new(arc);
487 let arc: &'a mut Arc<T> = unsafe { &mut *(&mut *arc as *mut Arc<T>) };
490 Arc::get_mut(arc)
491 }
492
493 unsafe extern "C" fn try_unwrap_arc<T>(this: RArc<T>) -> RResult<T, RArc<T>> {
494 this.into_raw()
495 .piped(|x| unsafe { Arc::from_raw(x) })
496 .piped(Arc::try_unwrap)
497 .map_err(RArc::from)
498 .into()
499 }
500
501 unsafe extern "C" fn strong_count_arc<T>(this: &RArc<T>) -> usize {
502 unsafe { with_arc_ref(this, |x| Arc::strong_count(x)) }
503 }
504
505 unsafe extern "C" fn weak_count_arc<T>(this: &RArc<T>) -> usize {
506 unsafe { with_arc_ref(this, |x| Arc::weak_count(x)) }
507 }
508}
509use self::vtable_mod::{ArcVtable_Ref, VTableGetter};