#[repr(align(64))]
#[derive(Debug, Clone, Copy)]
pub struct Padded<T> {
pub data: T,
_padding: [u8; 64],
}
impl<T> Padded<T> {
pub fn new(data: T) -> Self {
Self {
data,
_padding: [0; 64],
}
}
pub fn size() -> usize {
core::mem::size_of::<Self>()
}
pub fn is_aligned(ptr: &T) -> bool {
(ptr as *const T as usize) % 64 == 0
}
pub fn is_vec_aligned(vec: &[T]) -> bool {
if vec.is_empty() {
return true;
}
(vec.as_ptr() as usize) % 64 == 0
}
}
impl<T> core::ops::Deref for Padded<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T> core::ops::DerefMut for Padded<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
impl<T: Default> Default for Padded<T> {
fn default() -> Self {
Self::new(T::default())
}
}
#[inline]
pub fn prefetch_read<T>(data: &T) {
#[cfg(target_arch = "x86_64")]
unsafe {
core::arch::x86_64::_mm_prefetch(
data as *const T as *const i8,
core::arch::x86_64::_MM_HINT_T0,
);
}
#[cfg(not(target_arch = "x86_64"))]
{
#[cfg(feature = "std")]
unsafe {
std::hint::prefetch_read_data(data as *const T as *const _, core::mem::size_of::<T>());
}
}
}
#[inline]
pub fn prefetch_write<T>(data: &mut T) {
#[cfg(target_arch = "x86_64")]
unsafe {
core::arch::x86_64::_mm_prefetch(
data as *mut T as *const i8,
core::arch::x86_64::_MM_HINT_T0,
);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_padded_size() {
assert!(Padded::<u8>::size() >= 64);
}
#[test]
fn test_padded_deref() {
let padded = Padded::new(42);
assert_eq!(*padded, 42);
let mut padded = Padded::new(42);
*padded = 43;
assert_eq!(padded.data, 43);
}
}