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