Skip to content

Commit 412708a

Browse files
committed
Add RefCounter trait
1 parent 343a3e1 commit 412708a

File tree

1 file changed

+87
-0
lines changed
  • library/alloc/src/raw_rc

1 file changed

+87
-0
lines changed

library/alloc/src/raw_rc/mod.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
#![allow(dead_code)]
6363

6464
use core::cell::UnsafeCell;
65+
use core::mem;
66+
use core::sync::atomic::Atomic;
6567

6668
mod rc_alloc;
6769
mod 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

Comments
 (0)