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 template <class A, class T>
96 void
do_test()97 do_test()
98 {
99 A obj(T(0));
100 assert(obj == T(0));
101 std::atomic_init(&obj, T(1));
102 assert(obj == T(1));
103 std::atomic_init(&obj, T(2));
104 assert(obj == T(2));
105 bool b0 = obj.is_lock_free();
106 ((void)b0); // mark as unused
107 obj.store(T(0));
108 assert(obj == T(0));
109 obj.store(T(1), std::memory_order_release);
110 assert(obj == T(1));
111 assert(obj.load() == T(1));
112 assert(obj.load(std::memory_order_acquire) == T(1));
113 assert(obj.exchange(T(2)) == T(1));
114 assert(obj == T(2));
115 assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2));
116 assert(obj == T(3));
117 T x = obj;
118 assert(cmpxchg_weak_loop(obj, x, T(2)) == true);
119 assert(obj == T(2));
120 assert(x == T(3));
121 assert(obj.compare_exchange_weak(x, T(1)) == false);
122 assert(obj == T(2));
123 assert(x == T(2));
124 x = T(2);
125 assert(obj.compare_exchange_strong(x, T(1)) == true);
126 assert(obj == T(1));
127 assert(x == T(2));
128 assert(obj.compare_exchange_strong(x, T(0)) == false);
129 assert(obj == T(1));
130 assert(x == T(1));
131 assert((obj = T(0)) == T(0));
132 assert(obj == T(0));
133 assert(obj++ == T(0));
134 assert(obj == T(1));
135 assert(++obj == T(2));
136 assert(obj == T(2));
137 assert(--obj == T(1));
138 assert(obj == T(1));
139 assert(obj-- == T(1));
140 assert(obj == T(0));
141 obj = T(2);
142 assert((obj += T(3)) == T(5));
143 assert(obj == T(5));
144 assert((obj -= T(3)) == T(2));
145 assert(obj == T(2));
146 assert((obj |= T(5)) == T(7));
147 assert(obj == T(7));
148 assert((obj &= T(0xF)) == T(7));
149 assert(obj == T(7));
150 assert((obj ^= T(0xF)) == T(8));
151 assert(obj == T(8));
152
153 {
154 _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23};
155 A& zero = *new (storage) A();
156 assert(zero == 0);
157 zero.~A();
158 }
159 }
160
161 template <class A, class T>
test()162 void test()
163 {
164 do_test<A, T>();
165 do_test<volatile A, T>();
166 }
167
168
main()169 int main()
170 {
171 test<std::atomic_char, char>();
172 test<std::atomic_schar, signed char>();
173 test<std::atomic_uchar, unsigned char>();
174 test<std::atomic_short, short>();
175 test<std::atomic_ushort, unsigned short>();
176 test<std::atomic_int, int>();
177 test<std::atomic_uint, unsigned int>();
178 test<std::atomic_long, long>();
179 test<std::atomic_ulong, unsigned long>();
180 test<std::atomic_llong, long long>();
181 test<std::atomic_ullong, unsigned long long>();
182 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
183 test<std::atomic_char16_t, char16_t>();
184 test<std::atomic_char32_t, char32_t>();
185 #endif // _LIBCPP_HAS_NO_UNICODE_CHARS
186 test<std::atomic_wchar_t, wchar_t>();
187
188 test<volatile std::atomic_char, char>();
189 test<volatile std::atomic_schar, signed char>();
190 test<volatile std::atomic_uchar, unsigned char>();
191 test<volatile std::atomic_short, short>();
192 test<volatile std::atomic_ushort, unsigned short>();
193 test<volatile std::atomic_int, int>();
194 test<volatile std::atomic_uint, unsigned int>();
195 test<volatile std::atomic_long, long>();
196 test<volatile std::atomic_ulong, unsigned long>();
197 test<volatile std::atomic_llong, long long>();
198 test<volatile std::atomic_ullong, unsigned long long>();
199 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
200 test<volatile std::atomic_char16_t, char16_t>();
201 test<volatile std::atomic_char32_t, char32_t>();
202 #endif // _LIBCPP_HAS_NO_UNICODE_CHARS
203 test<volatile std::atomic_wchar_t, wchar_t>();
204 }
205