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 <class T>
15 // struct atomic
16 // {
17 //     bool is_lock_free() const volatile;
18 //     bool is_lock_free() const;
19 //     void store(T desr, memory_order m = memory_order_seq_cst) volatile;
20 //     void store(T desr, memory_order m = memory_order_seq_cst);
21 //     T load(memory_order m = memory_order_seq_cst) const volatile;
22 //     T load(memory_order m = memory_order_seq_cst) const;
23 //     operator T() const volatile;
24 //     operator T() const;
25 //     T exchange(T desr, memory_order m = memory_order_seq_cst) volatile;
26 //     T exchange(T desr, memory_order m = memory_order_seq_cst);
27 //     bool compare_exchange_weak(T& expc, T desr,
28 //                                memory_order s, memory_order f) volatile;
29 //     bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f);
30 //     bool compare_exchange_strong(T& expc, T desr,
31 //                                  memory_order s, memory_order f) volatile;
32 //     bool compare_exchange_strong(T& expc, T desr,
33 //                                  memory_order s, memory_order f);
34 //     bool compare_exchange_weak(T& expc, T desr,
35 //                                memory_order m = memory_order_seq_cst) volatile;
36 //     bool compare_exchange_weak(T& expc, T desr,
37 //                                memory_order m = memory_order_seq_cst);
38 //     bool compare_exchange_strong(T& expc, T desr,
39 //                                 memory_order m = memory_order_seq_cst) volatile;
40 //     bool compare_exchange_strong(T& expc, T desr,
41 //                                  memory_order m = memory_order_seq_cst);
42 //
43 //     atomic() = default;
44 //     constexpr atomic(T desr);
45 //     atomic(const atomic&) = delete;
46 //     atomic& operator=(const atomic&) = delete;
47 //     atomic& operator=(const atomic&) volatile = delete;
48 //     T operator=(T) volatile;
49 //     T operator=(T);
50 // };
51 //
52 // typedef atomic<bool> atomic_bool;
53 
54 #include <atomic>
55 #include <new>
56 #include <cassert>
57 
58 #include <cmpxchg_loop.h>
59 
main()60 int main()
61 {
62     {
63         volatile std::atomic<bool> obj(true);
64         assert(obj == true);
65         std::atomic_init(&obj, false);
66         assert(obj == false);
67         std::atomic_init(&obj, true);
68         assert(obj == true);
69         bool b0 = obj.is_lock_free();
70         (void)b0; // to placate scan-build
71         obj.store(false);
72         assert(obj == false);
73         obj.store(true, std::memory_order_release);
74         assert(obj == true);
75         assert(obj.load() == true);
76         assert(obj.load(std::memory_order_acquire) == true);
77         assert(obj.exchange(false) == true);
78         assert(obj == false);
79         assert(obj.exchange(true, std::memory_order_relaxed) == false);
80         assert(obj == true);
81         bool x = obj;
82         assert(cmpxchg_weak_loop(obj, x, false) == true);
83         assert(obj == false);
84         assert(x == true);
85         assert(obj.compare_exchange_weak(x, true,
86                                          std::memory_order_seq_cst) == false);
87         assert(obj == false);
88         assert(x == false);
89         obj.store(true);
90         x = true;
91         assert(cmpxchg_weak_loop(obj, x, false,
92                                  std::memory_order_seq_cst,
93                                  std::memory_order_seq_cst) == true);
94         assert(obj == false);
95         assert(x == true);
96         x = true;
97         obj.store(true);
98         assert(obj.compare_exchange_strong(x, false) == true);
99         assert(obj == false);
100         assert(x == true);
101         assert(obj.compare_exchange_strong(x, true,
102                                          std::memory_order_seq_cst) == false);
103         assert(obj == false);
104         assert(x == false);
105         x = true;
106         obj.store(true);
107         assert(obj.compare_exchange_strong(x, false,
108                                            std::memory_order_seq_cst,
109                                            std::memory_order_seq_cst) == true);
110         assert(obj == false);
111         assert(x == true);
112         assert((obj = false) == false);
113         assert(obj == false);
114         assert((obj = true) == true);
115         assert(obj == true);
116     }
117     {
118         std::atomic<bool> obj(true);
119         assert(obj == true);
120         std::atomic_init(&obj, false);
121         assert(obj == false);
122         std::atomic_init(&obj, true);
123         assert(obj == true);
124         bool b0 = obj.is_lock_free();
125         (void)b0; // to placate scan-build
126         obj.store(false);
127         assert(obj == false);
128         obj.store(true, std::memory_order_release);
129         assert(obj == true);
130         assert(obj.load() == true);
131         assert(obj.load(std::memory_order_acquire) == true);
132         assert(obj.exchange(false) == true);
133         assert(obj == false);
134         assert(obj.exchange(true, std::memory_order_relaxed) == false);
135         assert(obj == true);
136         bool x = obj;
137         assert(cmpxchg_weak_loop(obj, x, false) == true);
138         assert(obj == false);
139         assert(x == true);
140         assert(obj.compare_exchange_weak(x, true,
141                                          std::memory_order_seq_cst) == false);
142         assert(obj == false);
143         assert(x == false);
144         obj.store(true);
145         x = true;
146         assert(cmpxchg_weak_loop(obj, x, false,
147                                  std::memory_order_seq_cst,
148                                  std::memory_order_seq_cst) == true);
149         assert(obj == false);
150         assert(x == true);
151         x = true;
152         obj.store(true);
153         assert(obj.compare_exchange_strong(x, false) == true);
154         assert(obj == false);
155         assert(x == true);
156         assert(obj.compare_exchange_strong(x, true,
157                                          std::memory_order_seq_cst) == false);
158         assert(obj == false);
159         assert(x == false);
160         x = true;
161         obj.store(true);
162         assert(obj.compare_exchange_strong(x, false,
163                                            std::memory_order_seq_cst,
164                                            std::memory_order_seq_cst) == true);
165         assert(obj == false);
166         assert(x == true);
167         assert((obj = false) == false);
168         assert(obj == false);
169         assert((obj = true) == true);
170         assert(obj == true);
171     }
172     {
173         std::atomic_bool obj(true);
174         assert(obj == true);
175         std::atomic_init(&obj, false);
176         assert(obj == false);
177         std::atomic_init(&obj, true);
178         assert(obj == true);
179         bool b0 = obj.is_lock_free();
180         (void)b0; // to placate scan-build
181         obj.store(false);
182         assert(obj == false);
183         obj.store(true, std::memory_order_release);
184         assert(obj == true);
185         assert(obj.load() == true);
186         assert(obj.load(std::memory_order_acquire) == true);
187         assert(obj.exchange(false) == true);
188         assert(obj == false);
189         assert(obj.exchange(true, std::memory_order_relaxed) == false);
190         assert(obj == true);
191         bool x = obj;
192         assert(cmpxchg_weak_loop(obj, x, false) == true);
193         assert(obj == false);
194         assert(x == true);
195         assert(obj.compare_exchange_weak(x, true,
196                                          std::memory_order_seq_cst) == false);
197         assert(obj == false);
198         assert(x == false);
199         obj.store(true);
200         x = true;
201         assert(cmpxchg_weak_loop(obj, x, false,
202                                  std::memory_order_seq_cst,
203                                  std::memory_order_seq_cst) == true);
204         assert(obj == false);
205         assert(x == true);
206         x = true;
207         obj.store(true);
208         assert(obj.compare_exchange_strong(x, false) == true);
209         assert(obj == false);
210         assert(x == true);
211         assert(obj.compare_exchange_strong(x, true,
212                                          std::memory_order_seq_cst) == false);
213         assert(obj == false);
214         assert(x == false);
215         x = true;
216         obj.store(true);
217         assert(obj.compare_exchange_strong(x, false,
218                                            std::memory_order_seq_cst,
219                                            std::memory_order_seq_cst) == true);
220         assert(obj == false);
221         assert(x == true);
222         assert((obj = false) == false);
223         assert(obj == false);
224         assert((obj = true) == true);
225         assert(obj == true);
226     }
227     {
228         typedef std::atomic<bool> A;
229         _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {1};
230         A& zero = *new (storage) A();
231         assert(zero == false);
232         zero.~A();
233     }
234 }
235