6363#![ allow( dead_code) ]
6464
6565use core:: cell:: UnsafeCell ;
66+ use core:: mem;
67+ use core:: sync:: atomic:: Atomic ;
6668
6769mod rc_alloc;
6870mod rc_layout;
@@ -85,3 +87,83 @@ impl RefCounts {
8587 Self { weak : UnsafeCell :: new ( 1 ) , strong : UnsafeCell :: new ( strong_count) }
8688 }
8789}
90+
91+ /// The return value type for `RefCounter::make_mut`.
92+ #[ cfg( not( no_global_oom_handling) ) ]
93+ pub ( crate ) enum MakeMutStrategy {
94+ /// The strong reference count is 1, but weak reference count (including the one shared by all
95+ /// strong reference count) is more than 1. Before returning, the strong reference count has
96+ /// been set to zero to prevent new strong pointers from being created through upgrading from
97+ /// weak pointers.
98+ Move ,
99+ /// The strong count is more than 1.
100+ Clone ,
101+ }
102+
103+ /// A trait for `rc` and `sync` modules to define their reference-counting behaviors.
104+ ///
105+ /// # Safety
106+ ///
107+ /// - Each method must be implemented according to its description.
108+ /// - `Self` must have transparent representation over `UnsafeCell<usize>` and every valid
109+ /// `UnsafeCell<usize>` can also be reinterpreted as a valid `Self`.
110+ /// - `Self` must have alignment no greater than `align_of::<Atomic<usize>>()`.
111+ pub ( crate ) unsafe trait RefCounter : Sized {
112+ const VERIFY_LAYOUT : ( ) = {
113+ assert ! ( size_of:: <Self >( ) == size_of:: <UnsafeCell <usize >>( ) ) ;
114+ assert ! ( align_of:: <Self >( ) <= align_of:: <Atomic <usize >>( ) ) ;
115+ } ;
116+
117+ /// Returns a reference to `Self` from a reference to `UnsafeCell<usize>`.
118+ ///
119+ /// # Safety
120+ ///
121+ /// - `count` must only be handled by the same `RefCounter` implementation.
122+ /// - The location of `count` must have enough alignment for storing `Atomic<usize>`.
123+ unsafe fn from_raw_counter ( count : & UnsafeCell < usize > ) -> & Self {
124+ ( ) = Self :: VERIFY_LAYOUT ;
125+
126+ // SAFETY: The alignment requirement is guaranteed by both trait implementor and caller.
127+ // Trait implementor guarantees the alignment of `Self` is not greater than the alignment of
128+ // `Atomic<usize>`, and caller guarantees that the alignment of `count` is enough for
129+ // storing `Atomic<usize>`.
130+ unsafe { mem:: transmute ( count) }
131+ }
132+
133+ /// Increments the reference counter. The process will abort if overflow happens.
134+ fn increment ( & self ) ;
135+
136+ /// Decrements the reference counter. Returns whether the reference count becomes zero after
137+ /// decrementing.
138+ fn decrement ( & self ) -> bool ;
139+
140+ /// Increments the reference counter if and only if the reference count is non-zero. Returns
141+ /// whether incrementing is performed.
142+ fn try_upgrade ( & self ) -> bool ;
143+
144+ /// Increments the reference counter. If `self` needs to be called with by both
145+ /// `downgrade_increment_weak` and `is_unique` as the `weak_count` argument concurrently, both
146+ /// operations will be performed atomically.
147+ fn downgrade_increment_weak ( & self ) ;
148+
149+ /// Decrements the reference counter if and only if the reference count is 1. Returns true if
150+ /// decrementing is performed.
151+ fn try_lock_strong_count ( & self ) -> bool ;
152+
153+ /// Sets the reference count to 1.
154+ fn unlock_strong_count ( & self ) ;
155+
156+ /// Returns whether both `strong_count` and `weak_count` are 1. If `weak_count` needs to be
157+ /// called with by both `downgrade_increment_weak` and `is_unique` concurrently, both operations
158+ /// will be performed atomically.
159+ fn is_unique ( strong_count : & Self , weak_count : & Self ) -> bool ;
160+
161+ /// Determines how to make a mutable reference safely to a reference counted value.
162+ ///
163+ /// - If both strong count and weak count are 1, returns `None`.
164+ /// - If strong count is 1 and weak count is greater than 1, returns
165+ /// `Some(MakeMutStrategy::Move)`.
166+ /// - If strong count is greater than 1, returns `Some(MakeMutStrategy::Clone)`.
167+ #[ cfg( not( no_global_oom_handling) ) ]
168+ fn make_mut ( strong_count : & Self , weak_count : & Self ) -> Option < MakeMutStrategy > ;
169+ }
0 commit comments