michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/Assertions.h" michael@0: #include "mozilla/Atomics.h" michael@0: michael@0: #include michael@0: michael@0: using mozilla::Atomic; michael@0: using mozilla::MemoryOrdering; michael@0: using mozilla::Relaxed; michael@0: using mozilla::ReleaseAcquire; michael@0: using mozilla::SequentiallyConsistent; michael@0: michael@0: template michael@0: static void michael@0: TestTypeWithOrdering() michael@0: { michael@0: Atomic atomic(5); michael@0: MOZ_RELEASE_ASSERT(atomic == 5, "Atomic variable did not initialize"); michael@0: michael@0: // Test atomic increment michael@0: MOZ_RELEASE_ASSERT(++atomic == T(6), "Atomic increment did not work"); michael@0: MOZ_RELEASE_ASSERT(atomic++ == T(6), "Atomic post-increment did not work"); michael@0: MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic post-increment did not work"); michael@0: michael@0: // Test atomic decrement michael@0: MOZ_RELEASE_ASSERT(--atomic == 6, "Atomic decrement did not work"); michael@0: MOZ_RELEASE_ASSERT(atomic-- == 6, "Atomic post-decrement did not work"); michael@0: MOZ_RELEASE_ASSERT(atomic == 5, "Atomic post-decrement did not work"); michael@0: michael@0: // Test other arithmetic. michael@0: T result; michael@0: result = (atomic += T(5)); michael@0: MOZ_RELEASE_ASSERT(atomic == T(10), "Atomic += did not work"); michael@0: MOZ_RELEASE_ASSERT(result == T(10), "Atomic += returned the wrong value"); michael@0: result = (atomic -= T(3)); michael@0: MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic -= did not work"); michael@0: MOZ_RELEASE_ASSERT(result == T(7), "Atomic -= returned the wrong value"); michael@0: michael@0: // Test assignment michael@0: result = (atomic = T(5)); michael@0: MOZ_RELEASE_ASSERT(atomic == T(5), "Atomic assignment failed"); michael@0: MOZ_RELEASE_ASSERT(result == T(5), "Atomic assignment returned the wrong value"); michael@0: michael@0: // Test logical operations. michael@0: result = (atomic ^= T(2)); michael@0: MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic ^= did not work"); michael@0: MOZ_RELEASE_ASSERT(result == T(7), "Atomic ^= returned the wrong value"); michael@0: result = (atomic ^= T(4)); michael@0: MOZ_RELEASE_ASSERT(atomic == T(3), "Atomic ^= did not work"); michael@0: MOZ_RELEASE_ASSERT(result == T(3), "Atomic ^= returned the wrong value"); michael@0: result = (atomic |= T(8)); michael@0: MOZ_RELEASE_ASSERT(atomic == T(11), "Atomic |= did not work"); michael@0: MOZ_RELEASE_ASSERT(result == T(11), "Atomic |= returned the wrong value"); michael@0: result = (atomic |= T(8)); michael@0: MOZ_RELEASE_ASSERT(atomic == T(11), "Atomic |= did not work"); michael@0: MOZ_RELEASE_ASSERT(result == T(11), "Atomic |= returned the wrong value"); michael@0: result = (atomic &= T(12)); michael@0: MOZ_RELEASE_ASSERT(atomic == T(8), "Atomic &= did not work"); michael@0: MOZ_RELEASE_ASSERT(result == T(8), "Atomic &= returned the wrong value"); michael@0: michael@0: // Test exchange. michael@0: atomic = T(30); michael@0: result = atomic.exchange(42); michael@0: MOZ_RELEASE_ASSERT(atomic == T(42), "Atomic exchange did not work"); michael@0: MOZ_RELEASE_ASSERT(result == T(30), "Atomic exchange returned the wrong value"); michael@0: michael@0: // Test CAS. michael@0: atomic = T(1); michael@0: bool boolResult = atomic.compareExchange(0, 2); michael@0: MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); michael@0: MOZ_RELEASE_ASSERT(atomic == T(1), "CAS shouldn't have done anything."); michael@0: michael@0: boolResult = atomic.compareExchange(1, 42); michael@0: MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); michael@0: MOZ_RELEASE_ASSERT(atomic == T(42), "CAS should have changed atomic's value."); michael@0: } michael@0: michael@0: template michael@0: static void michael@0: TestPointerWithOrdering() michael@0: { michael@0: T array1[10]; michael@0: Atomic atomic(array1); michael@0: MOZ_RELEASE_ASSERT(atomic == array1, "Atomic variable did not initialize"); michael@0: michael@0: // Test atomic increment michael@0: MOZ_RELEASE_ASSERT(++atomic == array1 + 1, "Atomic increment did not work"); michael@0: MOZ_RELEASE_ASSERT(atomic++ == array1 + 1, "Atomic post-increment did not work"); michael@0: MOZ_RELEASE_ASSERT(atomic == array1 + 2, "Atomic post-increment did not work"); michael@0: michael@0: // Test atomic decrement michael@0: MOZ_RELEASE_ASSERT(--atomic == array1 + 1, "Atomic decrement did not work"); michael@0: MOZ_RELEASE_ASSERT(atomic-- == array1 + 1, "Atomic post-decrement did not work"); michael@0: MOZ_RELEASE_ASSERT(atomic == array1, "Atomic post-decrement did not work"); michael@0: michael@0: // Test other arithmetic operations michael@0: T* result; michael@0: result = (atomic += 2); michael@0: MOZ_RELEASE_ASSERT(atomic == array1 + 2, "Atomic += did not work"); michael@0: MOZ_RELEASE_ASSERT(result == array1 + 2, "Atomic += returned the wrong value"); michael@0: result = (atomic -= 1); michael@0: MOZ_RELEASE_ASSERT(atomic == array1 + 1, "Atomic -= did not work"); michael@0: MOZ_RELEASE_ASSERT(result == array1 + 1, "Atomic -= returned the wrong value"); michael@0: michael@0: // Test stores michael@0: result = (atomic = array1); michael@0: MOZ_RELEASE_ASSERT(atomic == array1, "Atomic assignment did not work"); michael@0: MOZ_RELEASE_ASSERT(result == array1, "Atomic assignment returned the wrong value"); michael@0: michael@0: // Test exchange michael@0: atomic = array1 + 2; michael@0: result = atomic.exchange(array1); michael@0: MOZ_RELEASE_ASSERT(atomic == array1, "Atomic exchange did not work"); michael@0: MOZ_RELEASE_ASSERT(result == array1 + 2, "Atomic exchange returned the wrong value"); michael@0: michael@0: atomic = array1; michael@0: bool boolResult = atomic.compareExchange(array1 + 1, array1 + 2); michael@0: MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); michael@0: MOZ_RELEASE_ASSERT(atomic == array1, "CAS shouldn't have done anything."); michael@0: michael@0: boolResult = atomic.compareExchange(array1, array1 + 3); michael@0: MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); michael@0: MOZ_RELEASE_ASSERT(atomic == array1 + 3, "CAS should have changed atomic's value."); michael@0: } michael@0: michael@0: enum EnumType { michael@0: EnumType_0 = 0, michael@0: EnumType_1 = 1, michael@0: EnumType_2 = 2, michael@0: EnumType_3 = 3 michael@0: }; michael@0: michael@0: template michael@0: static void michael@0: TestEnumWithOrdering() michael@0: { michael@0: Atomic atomic(EnumType_2); michael@0: MOZ_RELEASE_ASSERT(atomic == EnumType_2, "Atomic variable did not initialize"); michael@0: michael@0: // Test assignment michael@0: EnumType result; michael@0: result = (atomic = EnumType_3); michael@0: MOZ_RELEASE_ASSERT(atomic == EnumType_3, "Atomic assignment failed"); michael@0: MOZ_RELEASE_ASSERT(result == EnumType_3, "Atomic assignment returned the wrong value"); michael@0: michael@0: // Test exchange. michael@0: atomic = EnumType_1; michael@0: result = atomic.exchange(EnumType_2); michael@0: MOZ_RELEASE_ASSERT(atomic == EnumType_2, "Atomic exchange did not work"); michael@0: MOZ_RELEASE_ASSERT(result == EnumType_1, "Atomic exchange returned the wrong value"); michael@0: michael@0: // Test CAS. michael@0: atomic = EnumType_1; michael@0: bool boolResult = atomic.compareExchange(EnumType_0, EnumType_2); michael@0: MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); michael@0: MOZ_RELEASE_ASSERT(atomic == EnumType_1, "CAS shouldn't have done anything."); michael@0: michael@0: boolResult = atomic.compareExchange(EnumType_1, EnumType_3); michael@0: MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); michael@0: MOZ_RELEASE_ASSERT(atomic == EnumType_3, "CAS should have changed atomic's value."); michael@0: } michael@0: michael@0: template michael@0: static void michael@0: TestBoolWithOrdering() michael@0: { michael@0: Atomic atomic(false); michael@0: MOZ_RELEASE_ASSERT(atomic == false, "Atomic variable did not initialize"); michael@0: michael@0: // Test assignment michael@0: bool result; michael@0: result = (atomic = true); michael@0: MOZ_RELEASE_ASSERT(atomic == true, "Atomic assignment failed"); michael@0: MOZ_RELEASE_ASSERT(result == true, "Atomic assignment returned the wrong value"); michael@0: michael@0: // Test exchange. michael@0: atomic = false; michael@0: result = atomic.exchange(true); michael@0: MOZ_RELEASE_ASSERT(atomic == true, "Atomic exchange did not work"); michael@0: MOZ_RELEASE_ASSERT(result == false, "Atomic exchange returned the wrong value"); michael@0: michael@0: // Test CAS. michael@0: atomic = false; michael@0: bool boolResult = atomic.compareExchange(true, false); michael@0: MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); michael@0: MOZ_RELEASE_ASSERT(atomic == false, "CAS shouldn't have done anything."); michael@0: michael@0: boolResult = atomic.compareExchange(false, true); michael@0: MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); michael@0: MOZ_RELEASE_ASSERT(atomic == true, "CAS should have changed atomic's value."); michael@0: } michael@0: michael@0: template michael@0: static void michael@0: TestType() michael@0: { michael@0: TestTypeWithOrdering(); michael@0: TestTypeWithOrdering(); michael@0: TestTypeWithOrdering(); michael@0: } michael@0: michael@0: template michael@0: static void michael@0: TestPointer() michael@0: { michael@0: TestPointerWithOrdering(); michael@0: TestPointerWithOrdering(); michael@0: TestPointerWithOrdering(); michael@0: } michael@0: michael@0: static void michael@0: TestEnum() michael@0: { michael@0: TestEnumWithOrdering(); michael@0: TestEnumWithOrdering(); michael@0: TestEnumWithOrdering(); michael@0: } michael@0: michael@0: static void michael@0: TestBool() michael@0: { michael@0: TestBoolWithOrdering(); michael@0: TestBoolWithOrdering(); michael@0: TestBoolWithOrdering(); michael@0: } michael@0: michael@0: int main() michael@0: { michael@0: TestType(); michael@0: TestType(); michael@0: TestType(); michael@0: TestType(); michael@0: TestPointer(); michael@0: TestPointer(); michael@0: TestPointer(); michael@0: TestPointer(); michael@0: TestEnum(); michael@0: TestBool(); michael@0: }