xref: /llvm-project/libcxx/test/std/atomics/atomics.types.generic/integral.pass.cpp (revision 8aeacebf288b2f5dc9d3f23e9ac9a4f910238504)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // XFAIL: !has-64-bit-atomics
10 
11 // <atomic>
12 
13 // template <>
14 // struct atomic<integral>
15 // {
16 //     bool is_lock_free() const volatile;
17 //     bool is_lock_free() const;
18 //     void store(integral desr, memory_order m = memory_order_seq_cst) volatile;
19 //     void store(integral desr, memory_order m = memory_order_seq_cst);
20 //     integral load(memory_order m = memory_order_seq_cst) const volatile;
21 //     integral load(memory_order m = memory_order_seq_cst) const;
22 //     operator integral() const volatile;
23 //     operator integral() const;
24 //     integral exchange(integral desr,
25 //                       memory_order m = memory_order_seq_cst) volatile;
26 //     integral exchange(integral desr, memory_order m = memory_order_seq_cst);
27 //     bool compare_exchange_weak(integral& expc, integral desr,
28 //                                memory_order s, memory_order f) volatile;
29 //     bool compare_exchange_weak(integral& expc, integral desr,
30 //                                memory_order s, memory_order f);
31 //     bool compare_exchange_strong(integral& expc, integral desr,
32 //                                  memory_order s, memory_order f) volatile;
33 //     bool compare_exchange_strong(integral& expc, integral desr,
34 //                                  memory_order s, memory_order f);
35 //     bool compare_exchange_weak(integral& expc, integral desr,
36 //                                memory_order m = memory_order_seq_cst) volatile;
37 //     bool compare_exchange_weak(integral& expc, integral desr,
38 //                                memory_order m = memory_order_seq_cst);
39 //     bool compare_exchange_strong(integral& expc, integral desr,
40 //                                 memory_order m = memory_order_seq_cst) volatile;
41 //     bool compare_exchange_strong(integral& expc, integral desr,
42 //                                  memory_order m = memory_order_seq_cst);
43 //
44 //     integral
45 //         fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile;
46 //     integral fetch_add(integral op, memory_order m = memory_order_seq_cst);
47 //     integral
48 //         fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile;
49 //     integral fetch_sub(integral op, memory_order m = memory_order_seq_cst);
50 //     integral
51 //         fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile;
52 //     integral fetch_and(integral op, memory_order m = memory_order_seq_cst);
53 //     integral
54 //         fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile;
55 //     integral fetch_or(integral op, memory_order m = memory_order_seq_cst);
56 //     integral
57 //         fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile;
58 //     integral fetch_xor(integral op, memory_order m = memory_order_seq_cst);
59 //
60 //     atomic() = default;
61 //     constexpr atomic(integral desr);
62 //     atomic(const atomic&) = delete;
63 //     atomic& operator=(const atomic&) = delete;
64 //     atomic& operator=(const atomic&) volatile = delete;
65 //     integral operator=(integral desr) volatile;
66 //     integral operator=(integral desr);
67 //
68 //     integral operator++(int) volatile;
69 //     integral operator++(int);
70 //     integral operator--(int) volatile;
71 //     integral operator--(int);
72 //     integral operator++() volatile;
73 //     integral operator++();
74 //     integral operator--() volatile;
75 //     integral operator--();
76 //     integral operator+=(integral op) volatile;
77 //     integral operator+=(integral op);
78 //     integral operator-=(integral op) volatile;
79 //     integral operator-=(integral op);
80 //     integral operator&=(integral op) volatile;
81 //     integral operator&=(integral op);
82 //     integral operator|=(integral op) volatile;
83 //     integral operator|=(integral op);
84 //     integral operator^=(integral op) volatile;
85 //     integral operator^=(integral op);
86 // };
87 
88 #include <atomic>
89 #include <cassert>
90 #include <cstdint>
91 #include <new>
92 
93 #include <cmpxchg_loop.h>
94 
95 #include "test_macros.h"
96 
97 template <class A, class T>
98 void
do_test()99 do_test()
100 {
101     A obj(T(0));
102     assert(obj == T(0));
103     {
104         bool lockfree = obj.is_lock_free();
105         (void)lockfree;
106 #if TEST_STD_VER >= 17
107         if (A::is_always_lock_free)
108             assert(lockfree);
109 #endif
110     }
111     obj.store(T(0));
112     assert(obj == T(0));
113     obj.store(T(1), std::memory_order_release);
114     assert(obj == T(1));
115     assert(obj.load() == T(1));
116     assert(obj.load(std::memory_order_acquire) == T(1));
117     assert(obj.exchange(T(2)) == T(1));
118     assert(obj == T(2));
119     assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2));
120     assert(obj == T(3));
121     T x = obj;
122     assert(cmpxchg_weak_loop(obj, x, T(2)) == true);
123     assert(obj == T(2));
124     assert(x == T(3));
125     assert(obj.compare_exchange_weak(x, T(1)) == false);
126     assert(obj == T(2));
127     assert(x == T(2));
128     x = T(2);
129     assert(obj.compare_exchange_strong(x, T(1)) == true);
130     assert(obj == T(1));
131     assert(x == T(2));
132     assert(obj.compare_exchange_strong(x, T(0)) == false);
133     assert(obj == T(1));
134     assert(x == T(1));
135     assert((obj = T(0)) == T(0));
136     assert(obj == T(0));
137     assert(obj++ == T(0));
138     assert(obj == T(1));
139     assert(++obj == T(2));
140     assert(obj == T(2));
141     assert(--obj == T(1));
142     assert(obj == T(1));
143     assert(obj-- == T(1));
144     assert(obj == T(0));
145     obj = T(2);
146     assert((obj += T(3)) == T(5));
147     assert(obj == T(5));
148     assert((obj -= T(3)) == T(2));
149     assert(obj == T(2));
150     assert((obj |= T(5)) == T(7));
151     assert(obj == T(7));
152     assert((obj &= T(0xF)) == T(7));
153     assert(obj == T(7));
154     assert((obj ^= T(0xF)) == T(8));
155     assert(obj == T(8));
156 
157     {
158         TEST_ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23};
159         A& zero = *new (storage) A();
160         assert(zero == 0);
161         zero.~A();
162     }
163 }
164 
165 template <class A, class T>
test()166 void test()
167 {
168     do_test<A, T>();
169     do_test<volatile A, T>();
170 }
171 
172 
main(int,char **)173 int main(int, char**)
174 {
175     test<std::atomic_char, char>();
176     test<std::atomic_schar, signed char>();
177     test<std::atomic_uchar, unsigned char>();
178     test<std::atomic_short, short>();
179     test<std::atomic_ushort, unsigned short>();
180     test<std::atomic_int, int>();
181     test<std::atomic_uint, unsigned int>();
182     test<std::atomic_long, long>();
183     test<std::atomic_ulong, unsigned long>();
184     test<std::atomic_llong, long long>();
185     test<std::atomic_ullong, unsigned long long>();
186 #if TEST_STD_VER > 17 && defined(__cpp_char8_t)
187     test<std::atomic_char8_t, char8_t>();
188 #endif
189     test<std::atomic_char16_t, char16_t>();
190     test<std::atomic_char32_t, char32_t>();
191 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
192     test<std::atomic_wchar_t, wchar_t>();
193 #endif
194 
195     test<std::atomic_int8_t,    int8_t>();
196     test<std::atomic_uint8_t,  uint8_t>();
197     test<std::atomic_int16_t,   int16_t>();
198     test<std::atomic_uint16_t, uint16_t>();
199     test<std::atomic_int32_t,   int32_t>();
200     test<std::atomic_uint32_t, uint32_t>();
201     test<std::atomic_int64_t,   int64_t>();
202     test<std::atomic_uint64_t, uint64_t>();
203 
204     test<volatile std::atomic_char, char>();
205     test<volatile std::atomic_schar, signed char>();
206     test<volatile std::atomic_uchar, unsigned char>();
207     test<volatile std::atomic_short, short>();
208     test<volatile std::atomic_ushort, unsigned short>();
209     test<volatile std::atomic_int, int>();
210     test<volatile std::atomic_uint, unsigned int>();
211     test<volatile std::atomic_long, long>();
212     test<volatile std::atomic_ulong, unsigned long>();
213     test<volatile std::atomic_llong, long long>();
214     test<volatile std::atomic_ullong, unsigned long long>();
215     test<volatile std::atomic_char16_t, char16_t>();
216     test<volatile std::atomic_char32_t, char32_t>();
217 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
218     test<volatile std::atomic_wchar_t, wchar_t>();
219 #endif
220 
221     test<volatile std::atomic_int8_t,    int8_t>();
222     test<volatile std::atomic_uint8_t,  uint8_t>();
223     test<volatile std::atomic_int16_t,   int16_t>();
224     test<volatile std::atomic_uint16_t, uint16_t>();
225     test<volatile std::atomic_int32_t,   int32_t>();
226     test<volatile std::atomic_uint32_t, uint32_t>();
227     test<volatile std::atomic_int64_t,   int64_t>();
228     test<volatile std::atomic_uint64_t, uint64_t>();
229 
230   return 0;
231 }
232