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"
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.
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");
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");
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");
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() {
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
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");
109 result
= (atomic
= array1
);
110 A(atomic
== array1
, "Atomic assignment did not work");
111 A(result
== array1
, "Atomic assignment returned the wrong value");
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");
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.");
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");
143 result
= (atomic
= EnumType_3
);
144 A(atomic
== EnumType_3
, "Atomic assignment failed");
145 A(result
== EnumType_3
, "Atomic assignment returned the wrong value");
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");
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 {
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");
178 result
= (atomic
= EnumClass::Value3
);
179 A(atomic
== EnumClass::Value3
, "Atomic assignment failed");
180 A(result
== EnumClass::Value3
, "Atomic assignment returned the wrong value");
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");
189 atomic
= EnumClass::Value1
;
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");
207 result
= (atomic
= true);
208 A(atomic
== true, "Atomic assignment failed");
209 A(result
== true, "Atomic assignment returned the wrong value");
213 result
= atomic
.exchange(true);
214 A(atomic
== true, "Atomic exchange did not work");
215 A(result
== false, "Atomic exchange returned the wrong value");
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
>();
261 TestType
<uint32_t>();
263 TestType
<uint64_t>();
265 TestType
<intptr_t>();
266 TestType
<uintptr_t>();
268 TestPointer
<float>();
269 TestPointer
<uint16_t*>();
270 TestPointer
<uint32_t*>();