use core::fmt;
use core::ops::{Deref, DerefMut};
pub const CACHE_LINE_SIZE: usize = 64;
#[repr(C, align(64))]
pub struct CachePadded<T> {
value: T,
}
impl<T> CachePadded<T> {
#[inline]
pub const fn new(value: T) -> Self {
Self { value }
}
#[inline]
pub fn into_inner(self) -> T {
self.value
}
#[inline]
pub fn get_mut(&mut self) -> &mut T {
&mut self.value
}
}
impl<T> Deref for CachePadded<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.value
}
}
impl<T> DerefMut for CachePadded<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
&mut self.value
}
}
impl<T: Default> Default for CachePadded<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: Clone> Clone for CachePadded<T> {
fn clone(&self) -> Self {
Self::new(self.value.clone())
}
}
impl<T: Copy> Copy for CachePadded<T> {}
impl<T: fmt::Debug> fmt::Debug for CachePadded<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CachePadded")
.field("value", &self.value)
.finish()
}
}
impl<T: PartialEq> PartialEq for CachePadded<T> {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl<T: Eq> Eq for CachePadded<T> {}
impl<T> From<T> for CachePadded<T> {
fn from(value: T) -> Self {
Self::new(value)
}
}
#[cfg(test)]
mod tests {
use super::{CACHE_LINE_SIZE, CachePadded};
use core::mem::{align_of, size_of};
#[test]
fn aligns_to_cache_line() {
assert_eq!(align_of::<CachePadded<u8>>(), CACHE_LINE_SIZE);
}
#[test]
fn size_is_cache_line_multiple() {
assert_eq!(size_of::<CachePadded<u8>>() % CACHE_LINE_SIZE, 0);
assert_eq!(size_of::<CachePadded<[u8; 65]>>() % CACHE_LINE_SIZE, 0);
}
#[test]
fn derefs_to_inner_value() {
let padded = CachePadded::new(11u32);
assert_eq!(*padded, 11);
}
}