1mod atomic {
5 use crate::{assume_accessed, pessimize_cast, BorrowPessimize};
6 use core::sync::atomic;
7
8 macro_rules! pessimize_atomics {
9 (
10 $doc_cfg:meta
11 {
12 $(
13 $inner:ty : $outer:ident $(<$param:ident>)?
14 ),*
15 }
16 ) => {
17 use atomic::{ $($outer),* };
18 pessimize_cast!(
20 $doc_cfg
21 {
22 $(
23 $inner : (
24 $(|$param|)? $outer $(<$param>)? : (Self::into_inner, Self::new)
25 )
26 ),*
27 }
28 );
29 $(
31 #[cfg_attr(feature = "nightly", $doc_cfg)]
32 impl $(<$param>)? BorrowPessimize for $outer $(<$param>)? {
33 type BorrowedPessimize = *const Self;
34
35 #[inline]
36 fn with_pessimize(&self, f: impl FnOnce(&Self::BorrowedPessimize)) {
37 f(&(self as *const Self))
42 }
43
44 #[inline]
45 fn assume_accessed_impl(&mut self) {
46 assume_accessed::<$inner>(self.get_mut())
47 }
48 }
49 )*
50 };
51 }
52 #[cfg(target_has_atomic = "8")]
54 pessimize_atomics!(
55 doc(cfg(target_has_atomic = "8"))
56 {
57 bool: AtomicBool,
58 i8: AtomicI8,
59 u8: AtomicU8
60 }
61 );
62 #[cfg(target_has_atomic = "16")]
63 pessimize_atomics!(
64 doc(cfg(target_has_atomic = "16"))
65 {
66 i16: AtomicI16,
67 u16: AtomicU16
68 }
69 );
70 #[cfg(target_has_atomic = "32")]
71 pessimize_atomics!(
72 doc(cfg(target_has_atomic = "32"))
73 {
74 i32: AtomicI32,
75 u32: AtomicU32
76 }
77 );
78 #[cfg(all(target_has_atomic = "64", target_pointer_width = "64"))]
82 pessimize_atomics!(
83 doc(cfg(all(target_has_atomic = "64", target_pointer_width = "64")))
84 {
85 i64: AtomicI64,
86 u64: AtomicU64
87 }
88 );
89 #[cfg(target_has_atomic = "ptr")]
90 pessimize_atomics!(
91 doc(cfg(target_has_atomic = "ptr"))
92 {
93 isize: AtomicIsize,
94 usize: AtomicUsize,
95 *mut T: AtomicPtr<T>
96 }
97 );
98
99 #[allow(non_snake_case)]
100 #[cfg(test)]
101 mod tests {
102 use super::*;
103 use crate::{
104 cell::tests::test_unoptimized_cell,
105 pessimize_newtypes,
106 tests::{test_unoptimized_value_type, test_value, test_value_type},
107 };
108 use std::sync::atomic::Ordering;
109
110 macro_rules! make_testable_atomics {
111 (
112 $(
113 ($inner:ty, $outer:ty, $testable:ident)
114 ),*
115 ) => {
116 $(
117 #[derive(Debug, Default)]
118 struct $testable($outer);
119
120 impl $testable {
121 fn new(inner: $inner) -> Self {
122 Self(<$outer>::new(inner))
123 }
124
125 fn load(&self) -> $inner {
126 self.0.load(Ordering::Relaxed)
127 }
128 }
129
130 impl Clone for $testable {
131 fn clone(&self) -> Self {
132 $testable::new(self.load())
133 }
134 }
135
136 impl PartialEq for $testable {
137 fn eq(&self, other: &Self) -> bool {
138 self.load() == other.load()
139 }
140 }
141
142 pessimize_newtypes!( allow(missing_docs) { $testable{ $outer } } );
143 )*
144 };
145 }
146 macro_rules! test_scalar_atomics {
148 (
149 $(
150 ($inner:ty, $outer:ty, $testable:ident, $basic_test:ident, $optim_test:ident, $min:expr, $max:expr)
151 ),*
152 ) => {
153 make_testable_atomics!(
154 $(
155 ($inner, $outer, $testable)
156 ),*
157 );
158 $(
159 #[test]
160 fn $basic_test() {
161 test_value_type($testable::new($min), $testable::new($max));
162 }
163
164 #[test]
165 #[ignore]
166 fn $optim_test() {
167 test_unoptimized_value_type::<$testable>();
168 test_unoptimized_cell(<$outer>::new(<$inner>::default()), <$outer>::get_mut);
169 }
170 )*
171 };
172 }
173 macro_rules! test_int_atomics {
175 (
176 $(
177 ($inner:ty, $outer:ident, $testable:ident, $basic_test:ident, $optim_test:ident)
178 ),*
179 ) => {
180 test_scalar_atomics!(
181 $(
182 ($inner, $outer, $testable, $basic_test, $optim_test, <$inner>::MIN, <$inner>::MAX)
183 ),*
184 );
185 };
186 }
187 #[cfg(target_has_atomic = "8")]
189 test_scalar_atomics!((
190 bool,
191 AtomicBool,
192 TestableAtomicBool,
193 atomic_bool,
194 atomic_bool_optim,
195 false,
196 true
197 ));
198 #[cfg(target_has_atomic = "8")]
199 test_int_atomics!(
200 (i8, AtomicI8, TestableAtomicI8, atomic_i8, atomic_i8_optim),
201 (u8, AtomicU8, TestableAtomicU8, atomic_u8, atomic_u8_optim)
202 );
203 #[cfg(target_has_atomic = "16")]
204 test_int_atomics!(
205 (
206 i16,
207 AtomicI16,
208 TestableAtomicI16,
209 atomic_i16,
210 atomic_i16_optim
211 ),
212 (
213 u16,
214 AtomicU16,
215 TestableAtomicU16,
216 atomic_u16,
217 atomic_u16_optim
218 )
219 );
220 #[cfg(target_has_atomic = "32")]
221 test_int_atomics!(
222 (
223 i32,
224 AtomicI32,
225 TestableAtomicI32,
226 atomic_i32,
227 atomic_i32_optim
228 ),
229 (
230 u32,
231 AtomicU32,
232 TestableAtomicU32,
233 atomic_u32,
234 atomic_u32_optim
235 )
236 );
237 #[cfg(all(target_has_atomic = "64", target_pointer_width = "64"))]
238 test_int_atomics!(
239 (
240 i64,
241 AtomicI64,
242 TestableAtomicI64,
243 atomic_i64,
244 atomic_i64_optim
245 ),
246 (
247 u64,
248 AtomicU64,
249 TestableAtomicU64,
250 atomic_u64,
251 atomic_u64_optim
252 )
253 );
254 #[cfg(target_has_atomic = "ptr")]
255 test_int_atomics!(
256 (
257 isize,
258 AtomicIsize,
259 TestableAtomicIsize,
260 atomic_isize,
261 atomic_isize_optim
262 ),
263 (
264 usize,
265 AtomicUsize,
266 TestableAtomicUsize,
267 atomic_usize,
268 atomic_usize_optim
269 )
270 );
271
272 make_testable_atomics!((*mut (), AtomicPtr<()>, TestableAtomicPtr));
273 #[test]
275 fn atomic_ptr() {
276 test_value(TestableAtomicPtr::default());
277 }
278 #[test]
280 #[ignore]
281 fn atomic_ptr_optim() {
282 test_unoptimized_value_type::<TestableAtomicPtr>();
283 test_unoptimized_cell(
284 AtomicPtr::<()>::new(core::ptr::null_mut()),
285 AtomicPtr::get_mut,
286 );
287 }
288 }
289}