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