Backed out changeset ebc60855035e (bug 1829026) as requested for causing Bug 1869760...
[gecko.git] / mfbt / tests / TestAtomics.cpp
blob7d333d37c1fcfea122805d2118380cd22176d8ee
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/Assertions.h"
8 #include "mozilla/Atomics.h"
10 #include <stdint.h>
12 using mozilla::Atomic;
13 using mozilla::MemoryOrdering;
14 using mozilla::Relaxed;
15 using mozilla::ReleaseAcquire;
16 using mozilla::SequentiallyConsistent;
18 #define A(a, b) MOZ_RELEASE_ASSERT(a, b)
20 template <typename T, MemoryOrdering Order>
21 static void TestTypeWithOrdering() {
22 Atomic<T, Order> atomic(5);
23 A(atomic == 5, "Atomic variable did not initialize");
25 // Test atomic increment
26 A(++atomic == T(6), "Atomic increment did not work");
27 A(atomic++ == T(6), "Atomic post-increment did not work");
28 A(atomic == T(7), "Atomic post-increment did not work");
30 // Test atomic decrement
31 A(--atomic == 6, "Atomic decrement did not work");
32 A(atomic-- == 6, "Atomic post-decrement did not work");
33 A(atomic == 5, "Atomic post-decrement did not work");
35 // Test other arithmetic.
36 T result;
37 result = (atomic += T(5));
38 A(atomic == T(10), "Atomic += did not work");
39 A(result == T(10), "Atomic += returned the wrong value");
40 result = (atomic -= T(3));
41 A(atomic == T(7), "Atomic -= did not work");
42 A(result == T(7), "Atomic -= returned the wrong value");
44 // Test assignment
45 result = (atomic = T(5));
46 A(atomic == T(5), "Atomic assignment failed");
47 A(result == T(5), "Atomic assignment returned the wrong value");
49 // Test logical operations.
50 result = (atomic ^= T(2));
51 A(atomic == T(7), "Atomic ^= did not work");
52 A(result == T(7), "Atomic ^= returned the wrong value");
53 result = (atomic ^= T(4));
54 A(atomic == T(3), "Atomic ^= did not work");
55 A(result == T(3), "Atomic ^= returned the wrong value");
56 result = (atomic |= T(8));
57 A(atomic == T(11), "Atomic |= did not work");
58 A(result == T(11), "Atomic |= returned the wrong value");
59 result = (atomic |= T(8));
60 A(atomic == T(11), "Atomic |= did not work");
61 A(result == T(11), "Atomic |= returned the wrong value");
62 result = (atomic &= T(12));
63 A(atomic == T(8), "Atomic &= did not work");
64 A(result == T(8), "Atomic &= returned the wrong value");
66 // Test exchange.
67 atomic = T(30);
68 result = atomic.exchange(42);
69 A(atomic == T(42), "Atomic exchange did not work");
70 A(result == T(30), "Atomic exchange returned the wrong value");
72 // Test CAS.
73 atomic = T(1);
74 bool boolResult = atomic.compareExchange(0, 2);
75 A(!boolResult, "CAS should have returned false.");
76 A(atomic == T(1), "CAS shouldn't have done anything.");
78 boolResult = atomic.compareExchange(1, 42);
79 A(boolResult, "CAS should have succeeded.");
80 A(atomic == T(42), "CAS should have changed atomic's value.");
83 template <typename T, MemoryOrdering Order>
84 static void TestPointerWithOrdering() {
85 T array1[10];
86 Atomic<T*, Order> atomic(array1);
87 A(atomic == array1, "Atomic variable did not initialize");
89 // Test atomic increment
90 A(++atomic == array1 + 1, "Atomic increment did not work");
91 A(atomic++ == array1 + 1, "Atomic post-increment did not work");
92 A(atomic == array1 + 2, "Atomic post-increment did not work");
94 // Test atomic decrement
95 A(--atomic == array1 + 1, "Atomic decrement did not work");
96 A(atomic-- == array1 + 1, "Atomic post-decrement did not work");
97 A(atomic == array1, "Atomic post-decrement did not work");
99 // Test other arithmetic operations
100 T* result;
101 result = (atomic += 2);
102 A(atomic == array1 + 2, "Atomic += did not work");
103 A(result == array1 + 2, "Atomic += returned the wrong value");
104 result = (atomic -= 1);
105 A(atomic == array1 + 1, "Atomic -= did not work");
106 A(result == array1 + 1, "Atomic -= returned the wrong value");
108 // Test stores
109 result = (atomic = array1);
110 A(atomic == array1, "Atomic assignment did not work");
111 A(result == array1, "Atomic assignment returned the wrong value");
113 // Test exchange
114 atomic = array1 + 2;
115 result = atomic.exchange(array1);
116 A(atomic == array1, "Atomic exchange did not work");
117 A(result == array1 + 2, "Atomic exchange returned the wrong value");
119 atomic = array1;
120 bool boolResult = atomic.compareExchange(array1 + 1, array1 + 2);
121 A(!boolResult, "CAS should have returned false.");
122 A(atomic == array1, "CAS shouldn't have done anything.");
124 boolResult = atomic.compareExchange(array1, array1 + 3);
125 A(boolResult, "CAS should have succeeded.");
126 A(atomic == array1 + 3, "CAS should have changed atomic's value.");
129 enum EnumType {
130 EnumType_0 = 0,
131 EnumType_1 = 1,
132 EnumType_2 = 2,
133 EnumType_3 = 3
136 template <MemoryOrdering Order>
137 static void TestEnumWithOrdering() {
138 Atomic<EnumType, Order> atomic(EnumType_2);
139 A(atomic == EnumType_2, "Atomic variable did not initialize");
141 // Test assignment
142 EnumType result;
143 result = (atomic = EnumType_3);
144 A(atomic == EnumType_3, "Atomic assignment failed");
145 A(result == EnumType_3, "Atomic assignment returned the wrong value");
147 // Test exchange.
148 atomic = EnumType_1;
149 result = atomic.exchange(EnumType_2);
150 A(atomic == EnumType_2, "Atomic exchange did not work");
151 A(result == EnumType_1, "Atomic exchange returned the wrong value");
153 // Test CAS.
154 atomic = EnumType_1;
155 bool boolResult = atomic.compareExchange(EnumType_0, EnumType_2);
156 A(!boolResult, "CAS should have returned false.");
157 A(atomic == EnumType_1, "CAS shouldn't have done anything.");
159 boolResult = atomic.compareExchange(EnumType_1, EnumType_3);
160 A(boolResult, "CAS should have succeeded.");
161 A(atomic == EnumType_3, "CAS should have changed atomic's value.");
164 enum class EnumClass : uint32_t {
165 Value0 = 0,
166 Value1 = 1,
167 Value2 = 2,
168 Value3 = 3
171 template <MemoryOrdering Order>
172 static void TestEnumClassWithOrdering() {
173 Atomic<EnumClass, Order> atomic(EnumClass::Value2);
174 A(atomic == EnumClass::Value2, "Atomic variable did not initialize");
176 // Test assignment
177 EnumClass result;
178 result = (atomic = EnumClass::Value3);
179 A(atomic == EnumClass::Value3, "Atomic assignment failed");
180 A(result == EnumClass::Value3, "Atomic assignment returned the wrong value");
182 // Test exchange.
183 atomic = EnumClass::Value1;
184 result = atomic.exchange(EnumClass::Value2);
185 A(atomic == EnumClass::Value2, "Atomic exchange did not work");
186 A(result == EnumClass::Value1, "Atomic exchange returned the wrong value");
188 // Test CAS.
189 atomic = EnumClass::Value1;
190 bool boolResult =
191 atomic.compareExchange(EnumClass::Value0, EnumClass::Value2);
192 A(!boolResult, "CAS should have returned false.");
193 A(atomic == EnumClass::Value1, "CAS shouldn't have done anything.");
195 boolResult = atomic.compareExchange(EnumClass::Value1, EnumClass::Value3);
196 A(boolResult, "CAS should have succeeded.");
197 A(atomic == EnumClass::Value3, "CAS should have changed atomic's value.");
200 template <MemoryOrdering Order>
201 static void TestBoolWithOrdering() {
202 Atomic<bool, Order> atomic(false);
203 A(atomic == false, "Atomic variable did not initialize");
205 // Test assignment
206 bool result;
207 result = (atomic = true);
208 A(atomic == true, "Atomic assignment failed");
209 A(result == true, "Atomic assignment returned the wrong value");
211 // Test exchange.
212 atomic = false;
213 result = atomic.exchange(true);
214 A(atomic == true, "Atomic exchange did not work");
215 A(result == false, "Atomic exchange returned the wrong value");
217 // Test CAS.
218 atomic = false;
219 bool boolResult = atomic.compareExchange(true, false);
220 A(!boolResult, "CAS should have returned false.");
221 A(atomic == false, "CAS shouldn't have done anything.");
223 boolResult = atomic.compareExchange(false, true);
224 A(boolResult, "CAS should have succeeded.");
225 A(atomic == true, "CAS should have changed atomic's value.");
228 template <typename T>
229 static void TestType() {
230 TestTypeWithOrdering<T, SequentiallyConsistent>();
231 TestTypeWithOrdering<T, ReleaseAcquire>();
232 TestTypeWithOrdering<T, Relaxed>();
235 template <typename T>
236 static void TestPointer() {
237 TestPointerWithOrdering<T, SequentiallyConsistent>();
238 TestPointerWithOrdering<T, ReleaseAcquire>();
239 TestPointerWithOrdering<T, Relaxed>();
242 static void TestEnum() {
243 TestEnumWithOrdering<SequentiallyConsistent>();
244 TestEnumWithOrdering<ReleaseAcquire>();
245 TestEnumWithOrdering<Relaxed>();
247 TestEnumClassWithOrdering<SequentiallyConsistent>();
248 TestEnumClassWithOrdering<ReleaseAcquire>();
249 TestEnumClassWithOrdering<Relaxed>();
252 static void TestBool() {
253 TestBoolWithOrdering<SequentiallyConsistent>();
254 TestBoolWithOrdering<ReleaseAcquire>();
255 TestBoolWithOrdering<Relaxed>();
258 #undef A
260 int main() {
261 TestType<uint32_t>();
262 TestType<int32_t>();
263 TestType<uint64_t>();
264 TestType<int64_t>();
265 TestType<intptr_t>();
266 TestType<uintptr_t>();
267 TestPointer<int>();
268 TestPointer<float>();
269 TestPointer<uint16_t*>();
270 TestPointer<uint32_t*>();
271 TestEnum();
272 TestBool();
273 return 0;