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