88//! threads.
99//!
1010//! It is different from the standard library's [`Arc`] in a few ways:
11- //! 1. It is backed by the kernel's `refcount_t` type.
11+ //! 1. It is backed by the kernel's [`Refcount`] type.
1212//! 2. It does not support weak references, which allows it to be half the size.
1313//! 3. It saturates the reference count instead of aborting when it goes over a threshold.
1414//! 4. It does not provide a `get_mut` method, so the ref counted object is pinned.
1818
1919use crate :: {
2020 alloc:: { AllocError , Flags , KBox } ,
21- bindings,
2221 ffi:: c_void,
2322 init:: InPlaceInit ,
23+ sync:: Refcount ,
2424 try_init,
25- types:: { ForeignOwnable , Opaque } ,
25+ types:: ForeignOwnable ,
2626} ;
2727use core:: {
2828 alloc:: Layout ,
@@ -145,7 +145,7 @@ pub struct Arc<T: ?Sized> {
145145#[ pin_data]
146146#[ repr( C ) ]
147147struct ArcInner < T : ?Sized > {
148- refcount : Opaque < bindings :: refcount_t > ,
148+ refcount : Refcount ,
149149 data : T ,
150150}
151151
@@ -157,7 +157,7 @@ impl<T: ?Sized> ArcInner<T> {
157157 /// `ptr` must have been returned by a previous call to [`Arc::into_raw`], and the `Arc` must
158158 /// not yet have been destroyed.
159159 unsafe fn container_of ( ptr : * const T ) -> NonNull < ArcInner < T > > {
160- let refcount_layout = Layout :: new :: < bindings :: refcount_t > ( ) ;
160+ let refcount_layout = Layout :: new :: < Refcount > ( ) ;
161161 // SAFETY: The caller guarantees that the pointer is valid.
162162 let val_layout = Layout :: for_value ( unsafe { & * ptr } ) ;
163163 // SAFETY: We're computing the layout of a real struct that existed when compiling this
@@ -229,8 +229,7 @@ impl<T> Arc<T> {
229229 pub fn new ( contents : T , flags : Flags ) -> Result < Self , AllocError > {
230230 // INVARIANT: The refcount is initialised to a non-zero value.
231231 let value = ArcInner {
232- // SAFETY: There are no safety requirements for this FFI call.
233- refcount : Opaque :: new ( unsafe { bindings:: REFCOUNT_INIT ( 1 ) } ) ,
232+ refcount : Refcount :: new ( 1 ) ,
234233 data : contents,
235234 } ;
236235
@@ -348,18 +347,13 @@ impl<T: ?Sized> Arc<T> {
348347 // We will manually manage the refcount in this method, so we disable the destructor.
349348 let this = ManuallyDrop :: new ( this) ;
350349 // SAFETY: We own a refcount, so the pointer is still valid.
351- let refcount = unsafe { this. ptr . as_ref ( ) } . refcount . get ( ) ;
350+ let refcount = unsafe { & this. ptr . as_ref ( ) . refcount } ;
352351
353352 // If the refcount reaches a non-zero value, then we have destroyed this `Arc` and will
354353 // return without further touching the `Arc`. If the refcount reaches zero, then there are
355354 // no other arcs, and we can create a `UniqueArc`.
356- //
357- // SAFETY: We own a refcount, so the pointer is not dangling.
358- let is_zero = unsafe { bindings:: refcount_dec_and_test ( refcount) } ;
359- if is_zero {
360- // SAFETY: We have exclusive access to the arc, so we can perform unsynchronized
361- // accesses to the refcount.
362- unsafe { core:: ptr:: write ( refcount, bindings:: REFCOUNT_INIT ( 1 ) ) } ;
355+ if refcount. dec_and_test ( ) {
356+ refcount. set ( 1 ) ;
363357
364358 // INVARIANT: We own the only refcount to this arc, so we may create a `UniqueArc`. We
365359 // must pin the `UniqueArc` because the values was previously in an `Arc`, and they pin
@@ -456,14 +450,10 @@ impl<T: ?Sized> Borrow<T> for Arc<T> {
456450
457451impl < T : ?Sized > Clone for Arc < T > {
458452 fn clone ( & self ) -> Self {
459- // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
460- // safe to dereference it.
461- let refcount = unsafe { self . ptr . as_ref ( ) } . refcount . get ( ) ;
462-
463- // INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero.
453+ // INVARIANT: `Refcount` saturates the refcount, so it cannot overflow to zero.
464454 // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
465455 // safe to increment the refcount.
466- unsafe { bindings :: refcount_inc ( refcount ) } ;
456+ unsafe { self . ptr . as_ref ( ) } . refcount . inc ( ) ;
467457
468458 // SAFETY: We just incremented the refcount. This increment is now owned by the new `Arc`.
469459 unsafe { Self :: from_inner ( self . ptr ) }
@@ -472,16 +462,10 @@ impl<T: ?Sized> Clone for Arc<T> {
472462
473463impl < T : ?Sized > Drop for Arc < T > {
474464 fn drop ( & mut self ) {
475- // SAFETY: By the type invariant, there is necessarily a reference to the object. We cannot
476- // touch `refcount` after it's decremented to a non-zero value because another thread/CPU
477- // may concurrently decrement it to zero and free it. It is ok to have a raw pointer to
478- // freed/invalid memory as long as it is never dereferenced.
479- let refcount = unsafe { self . ptr . as_ref ( ) } . refcount . get ( ) ;
480-
481465 // INVARIANT: If the refcount reaches zero, there are no other instances of `Arc`, and
482466 // this instance is being dropped, so the broken invariant is not observable.
483- // SAFETY: Also by the type invariant, we are allowed to decrement the refcount .
484- let is_zero = unsafe { bindings :: refcount_dec_and_test ( refcount ) } ;
467+ // SAFETY: By the type invariant, there is necessarily a reference to the object .
468+ let is_zero = unsafe { self . ptr . as_ref ( ) } . refcount . dec_and_test ( ) ;
485469 if is_zero {
486470 // The count reached zero, we must free the memory.
487471 //
@@ -775,8 +759,7 @@ impl<T> UniqueArc<T> {
775759 // INVARIANT: The refcount is initialised to a non-zero value.
776760 let inner = KBox :: try_init :: < AllocError > (
777761 try_init ! ( ArcInner {
778- // SAFETY: There are no safety requirements for this FFI call.
779- refcount: Opaque :: new( unsafe { bindings:: REFCOUNT_INIT ( 1 ) } ) ,
762+ refcount: Refcount :: new( 1 ) ,
780763 data <- pin_init:: uninit:: <T , AllocError >( ) ,
781764 } ? AllocError ) ,
782765 flags,
0 commit comments