TestAtomics.cpp (9016B)
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/. */ 6 7 #include "mozilla/Assertions.h" 8 #include "mozilla/Atomics.h" 9 10 #include <stdint.h> 11 12 using mozilla::Atomic; 13 using mozilla::MemoryOrdering; 14 using mozilla::Relaxed; 15 using mozilla::ReleaseAcquire; 16 using mozilla::SequentiallyConsistent; 17 18 #define A(a, b) MOZ_RELEASE_ASSERT(a, b) 19 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"); 24 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"); 29 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"); 34 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"); 43 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"); 48 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"); 65 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"); 71 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."); 77 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."); 81 } 82 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"); 88 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"); 93 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"); 98 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"); 107 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"); 112 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"); 118 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."); 123 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."); 127 } 128 129 enum EnumType { 130 EnumType_0 = 0, 131 EnumType_1 = 1, 132 EnumType_2 = 2, 133 EnumType_3 = 3 134 }; 135 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"); 140 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"); 146 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"); 152 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."); 158 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."); 162 } 163 164 enum class EnumClass : uint32_t { 165 Value0 = 0, 166 Value1 = 1, 167 Value2 = 2, 168 Value3 = 3 169 }; 170 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"); 175 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"); 181 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"); 187 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."); 194 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."); 198 } 199 200 template <MemoryOrdering Order> 201 static void TestBoolWithOrdering() { 202 Atomic<bool, Order> atomic(false); 203 A(atomic == false, "Atomic variable did not initialize"); 204 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"); 210 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"); 216 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."); 222 223 boolResult = atomic.compareExchange(false, true); 224 A(boolResult, "CAS should have succeeded."); 225 A(atomic == true, "CAS should have changed atomic's value."); 226 } 227 228 template <typename T> 229 static void TestType() { 230 TestTypeWithOrdering<T, SequentiallyConsistent>(); 231 TestTypeWithOrdering<T, ReleaseAcquire>(); 232 TestTypeWithOrdering<T, Relaxed>(); 233 } 234 235 template <typename T> 236 static void TestPointer() { 237 TestPointerWithOrdering<T, SequentiallyConsistent>(); 238 TestPointerWithOrdering<T, ReleaseAcquire>(); 239 TestPointerWithOrdering<T, Relaxed>(); 240 } 241 242 static void TestEnum() { 243 TestEnumWithOrdering<SequentiallyConsistent>(); 244 TestEnumWithOrdering<ReleaseAcquire>(); 245 TestEnumWithOrdering<Relaxed>(); 246 247 TestEnumClassWithOrdering<SequentiallyConsistent>(); 248 TestEnumClassWithOrdering<ReleaseAcquire>(); 249 TestEnumClassWithOrdering<Relaxed>(); 250 } 251 252 static void TestBool() { 253 TestBoolWithOrdering<SequentiallyConsistent>(); 254 TestBoolWithOrdering<ReleaseAcquire>(); 255 TestBoolWithOrdering<Relaxed>(); 256 } 257 258 #undef A 259 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; 274 }