2 use std
::cell
::UnsafeCell
;
6 use std
::ops
::{Deref, DerefMut}
;
8 // For now, treat this as an arch-independent constant.
9 const CACHE_LINE
: usize = 32;
11 #[cfg_attr(feature = "nightly",
14 struct Padding(u64, u64, u64, u64);
16 /// Pad `T` to the length of a cacheline.
18 /// Sometimes concurrent programming requires a piece of data to be padded out
19 /// to the size of a cacheline to avoid "false sharing": cachelines being
20 /// invalidated due to unrelated concurrent activity. Use the `CachePadded` type
21 /// when you want to *avoid* cache locality.
23 /// At the moment, cache lines are assumed to be 32 * sizeof(usize) on all
26 /// **Warning**: the wrapped data is never dropped; move out using `ptr::read`
27 /// if you need to run dtors.
28 pub struct CachePadded
<T
> {
29 data
: UnsafeCell
<[usize; CACHE_LINE
]>,
30 _marker
: ([Padding
; 0], marker
::PhantomData
<T
>),
33 impl<T
> fmt
::Debug
for CachePadded
<T
> {
34 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
35 write
!(f
, "CachePadded {{ ... }}")
39 unsafe impl<T
: Send
> Send
for CachePadded
<T
> {}
40 unsafe impl<T
: Sync
> Sync
for CachePadded
<T
> {}
42 #[cfg(not(feature = "nightly"))]
43 macro_rules
! declare_zeros_valid
{
45 /// Types for which mem::zeroed() is safe.
47 /// If a type `T: ZerosValid`, then a sequence of zeros the size of `T` must be
48 /// a valid member of the type `T`.
49 pub unsafe trait ZerosValid {}
53 #[cfg(feature = "nightly")]
54 macro_rules
! declare_zeros_valid
{
56 /// Types for which mem::zeroed() is safe.
58 /// If a type `T: ZerosValid`, then a sequence of zeros the size of `T` must be
59 /// a valid member of the type `T`.
60 pub unsafe auto trait ZerosValid {}
64 declare_zeros_valid
!();
66 macro_rules
! zeros_valid
{ ($
( $T
:ty
)*) => ($
(
67 unsafe impl ZerosValid
for $T {}
70 zeros_valid
!(u8 u16 u32 u64 usize);
71 zeros_valid
!(i8 i16 i32 i64 isize);
73 unsafe impl ZerosValid
for ::std
::sync
::atomic
::AtomicUsize {}
74 unsafe impl<T
> ZerosValid
for ::std
::sync
::atomic
::AtomicPtr
<T
> {}
76 impl<T
: ZerosValid
> CachePadded
<T
> {
77 /// A const fn equivalent to mem::zeroed().
78 #[cfg(not(feature = "nightly"))]
79 pub fn zeroed() -> CachePadded
<T
> {
81 data
: UnsafeCell
::new(([0; CACHE_LINE
])),
82 _marker
: ([], marker
::PhantomData
),
86 /// A const fn equivalent to mem::zeroed().
87 #[cfg(feature = "nightly")]
88 pub const fn zeroed() -> CachePadded
<T
> {
90 data
: UnsafeCell
::new(([0; CACHE_LINE
])),
91 _marker
: ([], marker
::PhantomData
),
97 /// Assert that the size and alignment of `T` are consistent with `CachePadded<T>`.
98 fn assert_valid
<T
>() {
99 assert
!(mem
::size_of
::<T
>() <= mem
::size_of
::<CachePadded
<T
>>());
100 assert
!(mem
::align_of
::<T
>() <= mem
::align_of
::<CachePadded
<T
>>());
103 impl<T
> CachePadded
<T
> {
104 /// Wrap `t` with cacheline padding.
106 /// **Warning**: the wrapped data is never dropped; move out using
107 /// `ptr:read` if you need to run dtors.
108 pub fn new(t
: T
) -> CachePadded
<T
> {
110 let ret
= CachePadded
{
111 data
: UnsafeCell
::new(([0; CACHE_LINE
])),
112 _marker
: ([], marker
::PhantomData
),
115 let p
: *mut T
= mem
::transmute(&ret
.data
);
122 impl<T
> Deref
for CachePadded
<T
> {
124 fn deref(&self) -> &T
{
126 unsafe { mem::transmute(&self.data) }
130 impl<T
> DerefMut
for CachePadded
<T
> {
131 fn deref_mut(&mut self) -> &mut T
{
133 unsafe { mem::transmute(&mut self.data) }
137 // FIXME: support Drop by pulling out a version usable for statics
139 impl<T> Drop for CachePadded<T> {
142 let p: *mut T = mem::transmute(&self.data);
143 mem::drop(ptr::read(p));
153 fn cache_padded_store_u64() {
154 let x
: CachePadded
<u64> = CachePadded
::new(17);
159 fn cache_padded_store_pair() {
160 let x
: CachePadded
<(u64, u64)> = CachePadded
::new((17, 37));