use std::alloc::{self, Layout};
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
use std::slice;
const ALIGN: usize = 32;
#[cfg_attr(feature = "bench_asyncro", visibility::make(pub))]
pub(crate) struct AlignedBuf<T> {
ptr: NonNull<T>,
len: usize,
_marker: PhantomData<T>,
}
unsafe impl<T: Send> Send for AlignedBuf<T> {}
unsafe impl<T: Sync> Sync for AlignedBuf<T> {}
impl<T: Copy> AlignedBuf<T> {
fn layout(len: usize) -> Layout {
let size = len
.checked_mul(mem::size_of::<T>())
.expect("AlignedBuf size overflow");
Layout::from_size_align(size, ALIGN).expect("invalid AlignedBuf layout")
}
pub(crate) fn zeroed(len: usize) -> Self {
if len == 0 {
return Self {
ptr: NonNull::dangling(),
len: 0,
_marker: PhantomData,
};
}
let layout = Self::layout(len);
let raw = unsafe { alloc::alloc_zeroed(layout) } as *mut T;
let ptr = NonNull::new(raw).unwrap_or_else(|| alloc::handle_alloc_error(layout));
Self {
ptr,
len,
_marker: PhantomData,
}
}
pub(crate) fn from_slice(src: &[T]) -> Self {
if src.is_empty() {
return Self {
ptr: NonNull::dangling(),
len: 0,
_marker: PhantomData,
};
}
let layout = Self::layout(src.len());
let raw = unsafe { alloc::alloc(layout) } as *mut T;
let ptr = NonNull::new(raw).unwrap_or_else(|| alloc::handle_alloc_error(layout));
unsafe {
std::ptr::copy_nonoverlapping(src.as_ptr(), ptr.as_ptr(), src.len());
}
Self {
ptr,
len: src.len(),
_marker: PhantomData,
}
}
}
impl<T> Drop for AlignedBuf<T> {
fn drop(&mut self) {
if self.len != 0 {
let size = self.len * mem::size_of::<T>();
let layout = Layout::from_size_align(size, ALIGN).unwrap();
unsafe { alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout) };
}
}
}
impl<T> Deref for AlignedBuf<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
}
}
impl<T> DerefMut for AlignedBuf<T> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
}
}