Skip to content

Commit

Permalink
Use Layout::extend and clean up code around alloc
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Dec 23, 2023
1 parent 12c5eb5 commit e549b69
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 30 deletions.
35 changes: 19 additions & 16 deletions crossbeam-epoch/src/atomic.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use alloc::boxed::Box;
use core::alloc::Layout;
use core::borrow::{Borrow, BorrowMut};
use core::cmp;
use core::fmt;
Expand All @@ -7,8 +9,6 @@ use core::ops::{Deref, DerefMut};
use core::ptr;
use core::slice;

use crate::alloc::alloc;
use crate::alloc::boxed::Box;
use crate::guard::Guard;
#[cfg(not(miri))]
use crate::primitive::sync::atomic::AtomicUsize;
Expand Down Expand Up @@ -191,31 +191,36 @@ impl<T> Pointable for T {
///
/// Elements are not present in the type, but they will be in the allocation.
/// ```
///
// TODO(@jeehoonkang): once we bump the minimum required Rust version to 1.44 or newer, use
// [`alloc::alloc::Layout::extend`] instead.
#[repr(C)]
struct Array<T> {
/// The number of elements (not the number of bytes).
len: usize,
elements: [MaybeUninit<T>; 0],
}

impl<T> Array<T> {
fn layout(len: usize) -> Layout {
Layout::new::<Self>()
.extend(Layout::array::<MaybeUninit<T>>(len).unwrap())
.unwrap()
.0
.pad_to_align()
}
}

impl<T> Pointable for [MaybeUninit<T>] {
const ALIGN: usize = mem::align_of::<Array<T>>();

type Init = usize;

unsafe fn init(len: Self::Init) -> *mut () {
let size = mem::size_of::<Array<T>>() + mem::size_of::<MaybeUninit<T>>() * len;
let align = mem::align_of::<Array<T>>();
let layout = alloc::Layout::from_size_align(size, align).unwrap();
let layout = Array::<T>::layout(len);
unsafe {
let ptr = alloc::alloc(layout).cast::<Array<T>>();
let ptr = alloc::alloc::alloc(layout).cast::<Array<T>>();
if ptr.is_null() {
alloc::handle_alloc_error(layout);
alloc::alloc::handle_alloc_error(layout);
}
(*ptr).len = len;
ptr::addr_of_mut!((*ptr).len).write(len);
ptr.cast::<()>()
}
}
Expand All @@ -236,11 +241,9 @@ impl<T> Pointable for [MaybeUninit<T>] {

unsafe fn drop(ptr: *mut ()) {
unsafe {
let array = &*ptr.cast::<Array<T>>();
let size = mem::size_of::<Array<T>>() + mem::size_of::<MaybeUninit<T>>() * array.len;
let align = mem::align_of::<Array<T>>();
let layout = alloc::Layout::from_size_align(size, align).unwrap();
alloc::dealloc(ptr.cast::<u8>(), layout);
let len = (*ptr.cast::<Array<T>>()).len;
let layout = Array::<T>::layout(len);
alloc::alloc::dealloc(ptr.cast::<u8>(), layout);
}
}
}
Expand Down
28 changes: 14 additions & 14 deletions crossbeam-skiplist/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,18 @@ impl<K, V> Node<K, V> {
/// with null pointers. However, the key and the value will be left uninitialized, and that is
/// why this function is unsafe.
unsafe fn alloc(height: usize, ref_count: usize) -> *mut Self {
let layout = Self::get_layout(height);
unsafe {
let layout = Self::get_layout(height);
let ptr = alloc(layout).cast::<Self>();
if ptr.is_null() {
handle_alloc_error(layout);
}

ptr::write(
&mut (*ptr).refs_and_height,
AtomicUsize::new((height - 1) | ref_count << HEIGHT_BITS),
);
ptr::write_bytes((*ptr).tower.pointers.as_mut_ptr(), 0, height);
ptr::addr_of_mut!((*ptr).refs_and_height)
.write(AtomicUsize::new((height - 1) | ref_count << HEIGHT_BITS));
ptr::addr_of_mut!((*ptr).tower.pointers)
.cast::<Atomic<Self>>()
.write_bytes(0, height);
ptr
}
}
Expand All @@ -126,14 +126,14 @@ impl<K, V> Node<K, V> {
}

/// Returns the layout of a node with the given `height`.
unsafe fn get_layout(height: usize) -> Layout {
fn get_layout(height: usize) -> Layout {
assert!((1..=MAX_HEIGHT).contains(&height));

let size_self = mem::size_of::<Self>();
let align_self = mem::align_of::<Self>();
let size_pointer = mem::size_of::<Atomic<Self>>();

unsafe { Layout::from_size_align_unchecked(size_self + size_pointer * height, align_self) }
Layout::new::<Self>()
.extend(Layout::array::<Atomic<Self>>(height).unwrap())
.unwrap()
.0
.pad_to_align()
}

/// Returns the height of this node's tower.
Expand Down Expand Up @@ -912,8 +912,8 @@ where
let n = Node::<K, V>::alloc(height, 2);

// Write the key and the value into the node.
ptr::write(&mut (*n).key, key);
ptr::write(&mut (*n).value, value);
ptr::addr_of_mut!((*n).key).write(key);
ptr::addr_of_mut!((*n).value).write(value);

(Shared::<Node<K, V>>::from(n as *const _), &*n)
};
Expand Down

0 comments on commit e549b69

Please sign in to comment.