Skip to content

Commit

Permalink
Refactor Rc::default
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Jan 2, 2025
1 parent 8dc11bb commit 2f8c95f
Showing 1 changed file with 32 additions and 199 deletions.
231 changes: 32 additions & 199 deletions library/alloc/src/raw_rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,37 @@ impl<T, A> RawRc<T, A> {
unsafe { Self::from_weak_with_value(RawWeak::new_uninit_in::<1>(alloc), value) }
}

#[cfg(not(no_global_oom_handling))]
pub fn new_with<F>(f: F) -> Self
where
A: Allocator + Default,
F: FnOnce() -> T,
{
struct Guard<'a, T, A>
where
A: Allocator,
{
weak: &'a mut RawWeak<T, A>,
}

impl<'a, T, A> Drop for Guard<'a, T, A>
where
A: Allocator,
{
fn drop(&mut self) {
unsafe { self.weak.deallocate() };
}
}

let mut weak = RawWeak::new_uninit::<1>();
let guard = Guard { weak: &mut weak };
let value = f();

mem::forget(guard);

unsafe { Self::from_weak_with_value(weak, value) }
}

#[cfg(not(no_global_oom_handling))]
pub unsafe fn new_cyclic<F, R>(data_fn: F) -> Self
where
Expand Down Expand Up @@ -1283,212 +1314,14 @@ where
}
}

#[cfg(not(no_global_oom_handling))]
trait SpecRcDefault {
fn spec_default() -> Self;
}

#[cfg(not(no_global_oom_handling))]
impl<T, A> SpecRcDefault for RawRc<T, A>
where
T: Default,
A: Allocator + Default,
{
default fn spec_default() -> Self {
Self::new(T::default())
}
}

#[cfg(not(no_global_oom_handling))]
impl<T> SpecRcDefault for RawRc<T, Global>
where
T: Default,
{
fn spec_default() -> Self {
fn spec_default_impl<T, const N: usize>() -> RawRc<T, Global>
where
T: Default,
{
#[repr(C)]
struct RcAllocation<T, const N: usize> {
_padding: MaybeUninit<[RefCounts; N]>,
_ref_counts: RefCounts,
_value: T,
}

impl<T, const N: usize> Default for RcAllocation<T, N>
where
T: Default,
{
fn default() -> Self {
Self {
_padding: MaybeUninit::uninit(),
_ref_counts: RefCounts::new(1),
_value: T::default(),
}
}
}

const {
assert!(
RefCounts::LAYOUT.size().checked_mul(N).unwrap()
== RefCounts::LAYOUT.padding_needed_for(T::LAYOUT.align())
);
};

let (allocation_ptr, alloc) =
Box::into_non_null_with_allocator(Box::<RcAllocation<T, N>>::default());

unsafe {
RawRc::from_raw_parts(
allocation_ptr.byte_add(T::RC_LAYOUT.allocation_offset_bytes).cast(),
alloc,
)
}
}

macro_rules! select_impl {
($($value:literal,)*) => {
match RefCounts::LAYOUT.padding_needed_for(T::LAYOUT.align()) / RefCounts::LAYOUT.size() {
$($value => spec_default_impl::<T, $value>,)*
_ => panic!("invalid padding"),
}
};
}

#[cfg(target_pointer_width = "16")]
let selected_impl: fn() -> Self = const {
select_impl![
0x0000, // (1 << 0) - 1
0x0001, // (1 << 1) - 1
0x0003, // (1 << 2) - 1
0x0007, // (1 << 3) - 1
0x000f, // (1 << 4) - 1
0x001f, // (1 << 5) - 1
0x003f, // (1 << 6) - 1
0x007f, // (1 << 7) - 1
0x00ff, // (1 << 8) - 1
0x01ff, // (1 << 9) - 1
0x03ff, // (1 << 10) - 1
0x07ff, // (1 << 11) - 1
0x0fff, // (1 << 12) - 1
0x1fff, // (1 << 13) - 1
]
};

#[cfg(target_pointer_width = "32")]
let selected_impl: fn() -> Self = const {
select_impl![
0x00000000, // (1 << 0) - 1
0x00000001, // (1 << 1) - 1
0x00000003, // (1 << 2) - 1
0x00000007, // (1 << 3) - 1
0x0000000f, // (1 << 4) - 1
0x0000001f, // (1 << 5) - 1
0x0000003f, // (1 << 6) - 1
0x0000007f, // (1 << 7) - 1
0x000000ff, // (1 << 8) - 1
0x000001ff, // (1 << 9) - 1
0x000003ff, // (1 << 10) - 1
0x000007ff, // (1 << 11) - 1
0x00000fff, // (1 << 12) - 1
0x00001fff, // (1 << 13) - 1
0x00003fff, // (1 << 14) - 1
0x00007fff, // (1 << 15) - 1
0x0000ffff, // (1 << 16) - 1
0x0001ffff, // (1 << 17) - 1
0x0003ffff, // (1 << 18) - 1
0x0007ffff, // (1 << 19) - 1
0x000fffff, // (1 << 20) - 1
0x001fffff, // (1 << 21) - 1
0x003fffff, // (1 << 22) - 1
0x007fffff, // (1 << 23) - 1
0x00ffffff, // (1 << 24) - 1
0x01ffffff, // (1 << 25) - 1
0x03ffffff, // (1 << 26) - 1
0x07ffffff, // (1 << 27) - 1
0x0fffffff, // (1 << 28) - 1
]
};

#[cfg(target_pointer_width = "64")]
let selected_impl: fn() -> Self = const {
select_impl![
0x0000000000000000, // (1 << 0) - 1
0x0000000000000001, // (1 << 1) - 1
0x0000000000000003, // (1 << 2) - 1
0x0000000000000007, // (1 << 3) - 1
0x000000000000000f, // (1 << 4) - 1
0x000000000000001f, // (1 << 5) - 1
0x000000000000003f, // (1 << 6) - 1
0x000000000000007f, // (1 << 7) - 1
0x00000000000000ff, // (1 << 8) - 1
0x00000000000001ff, // (1 << 9) - 1
0x00000000000003ff, // (1 << 10) - 1
0x00000000000007ff, // (1 << 11) - 1
0x0000000000000fff, // (1 << 12) - 1
0x0000000000001fff, // (1 << 13) - 1
0x0000000000003fff, // (1 << 14) - 1
0x0000000000007fff, // (1 << 15) - 1
0x000000000000ffff, // (1 << 16) - 1
0x000000000001ffff, // (1 << 17) - 1
0x000000000003ffff, // (1 << 18) - 1
0x000000000007ffff, // (1 << 19) - 1
0x00000000000fffff, // (1 << 20) - 1
0x00000000001fffff, // (1 << 21) - 1
0x00000000003fffff, // (1 << 22) - 1
0x00000000007fffff, // (1 << 23) - 1
0x0000000000ffffff, // (1 << 24) - 1
0x0000000001ffffff, // (1 << 25) - 1
0x0000000003ffffff, // (1 << 26) - 1
0x0000000007ffffff, // (1 << 27) - 1
0x000000000fffffff, // (1 << 28) - 1
0x000000001fffffff, // (1 << 29) - 1
0x000000003fffffff, // (1 << 30) - 1
0x000000007fffffff, // (1 << 31) - 1
0x00000000ffffffff, // (1 << 32) - 1
0x00000001ffffffff, // (1 << 33) - 1
0x00000003ffffffff, // (1 << 34) - 1
0x00000007ffffffff, // (1 << 35) - 1
0x0000000fffffffff, // (1 << 36) - 1
0x0000001fffffffff, // (1 << 37) - 1
0x0000003fffffffff, // (1 << 38) - 1
0x0000007fffffffff, // (1 << 39) - 1
0x000000ffffffffff, // (1 << 40) - 1
0x000001ffffffffff, // (1 << 41) - 1
0x000003ffffffffff, // (1 << 42) - 1
0x000007ffffffffff, // (1 << 43) - 1
0x00000fffffffffff, // (1 << 44) - 1
0x00001fffffffffff, // (1 << 45) - 1
0x00003fffffffffff, // (1 << 46) - 1
0x00007fffffffffff, // (1 << 47) - 1
0x0000ffffffffffff, // (1 << 48) - 1
0x0001ffffffffffff, // (1 << 49) - 1
0x0003ffffffffffff, // (1 << 50) - 1
0x0007ffffffffffff, // (1 << 51) - 1
0x000fffffffffffff, // (1 << 52) - 1
0x001fffffffffffff, // (1 << 53) - 1
0x003fffffffffffff, // (1 << 54) - 1
0x007fffffffffffff, // (1 << 55) - 1
0x00ffffffffffffff, // (1 << 56) - 1
0x01ffffffffffffff, // (1 << 57) - 1
0x03ffffffffffffff, // (1 << 58) - 1
0x07ffffffffffffff, // (1 << 59) - 1
]
};

selected_impl()
}
}

#[cfg(not(no_global_oom_handling))]
impl<T, A> Default for RawRc<T, A>
where
T: Default,
A: Allocator + Default,
{
fn default() -> Self {
Self::spec_default()
Self::new_with(T::default)
}
}

Expand Down

0 comments on commit 2f8c95f

Please sign in to comment.