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