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