aboutsummaryrefslogtreecommitdiff
path: root/test/source/TestAtomicBasic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/source/TestAtomicBasic.cpp')
-rw-r--r--test/source/TestAtomicBasic.cpp4083
1 files changed, 4083 insertions, 0 deletions
diff --git a/test/source/TestAtomicBasic.cpp b/test/source/TestAtomicBasic.cpp
new file mode 100644
index 0000000..166b030
--- /dev/null
+++ b/test/source/TestAtomicBasic.cpp
@@ -0,0 +1,4083 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "EASTLTest.h"
+
+#include <EASTL/atomic.h>
+
+
+/**
+ * This is a basic test suite that tests all functionality is implemented
+ * and that all operations do as expected.
+ * I.E. fetch_add returns the previous value and add_fetch returns the current value
+ */
+
+static eastl::atomic<int> sAtomicInt{ 4 };
+static eastl::atomic<void*> sAtomicPtr{ nullptr };
+
+static int TestAtomicConstantInitialization()
+{
+ int nErrorCount;
+
+ EATEST_VERIFY(sAtomicInt.load() == 4);
+ EATEST_VERIFY(sAtomicPtr == nullptr);
+
+ return 0;
+}
+
+class AtomicStandaloneBasicTest
+{
+public:
+
+ int RunTest()
+ {
+ AtomicSignalFence();
+
+ AtomicThreadFence();
+
+ AtomicCpuPause();
+
+ AtomicCompilerBarrier();
+
+ return nErrorCount;
+ }
+
+private:
+
+ void AtomicSignalFence();
+
+ void AtomicThreadFence();
+
+ void AtomicCpuPause();
+
+ void AtomicCompilerBarrier();
+
+private:
+
+ int nErrorCount = 0;
+};
+
+void AtomicStandaloneBasicTest::AtomicSignalFence()
+{
+ eastl::atomic_signal_fence(eastl::memory_order_relaxed);
+
+ eastl::atomic_signal_fence(eastl::memory_order_acquire);
+
+ eastl::atomic_signal_fence(eastl::memory_order_release);
+
+ eastl::atomic_signal_fence(eastl::memory_order_acq_rel);
+
+ eastl::atomic_signal_fence(eastl::memory_order_seq_cst);
+}
+
+void AtomicStandaloneBasicTest::AtomicThreadFence()
+{
+ eastl::atomic_thread_fence(eastl::memory_order_relaxed);
+
+ eastl::atomic_thread_fence(eastl::memory_order_acquire);
+
+ eastl::atomic_thread_fence(eastl::memory_order_release);
+
+ eastl::atomic_thread_fence(eastl::memory_order_acq_rel);
+
+ eastl::atomic_thread_fence(eastl::memory_order_seq_cst);
+}
+
+void AtomicStandaloneBasicTest::AtomicCpuPause()
+{
+ eastl::cpu_pause();
+}
+
+void AtomicStandaloneBasicTest::AtomicCompilerBarrier()
+{
+ eastl::compiler_barrier();
+
+ {
+ bool ret = false;
+ eastl::compiler_barrier_data_dependency(ret);
+ }
+}
+
+class AtomicFlagBasicTest
+{
+public:
+
+ using AtomicType = eastl::atomic_flag;
+ using BoolType = bool;
+
+ int RunTest()
+ {
+ TestAtomicFlagCtor();
+
+ TestAtomicFlagClear();
+
+ TestAtomicFlagTestAndSet();
+
+ TestAtomicFlagTest();
+
+ TestAllMemoryOrders();
+
+ TestAtomicFlagStandalone();
+
+ return nErrorCount;
+ }
+
+private:
+
+ void TestAtomicFlagCtor();
+
+ void TestAtomicFlagClear();
+
+ void TestAtomicFlagTestAndSet();
+
+ void TestAtomicFlagTest();
+
+ void TestAllMemoryOrders();
+
+ void TestAtomicFlagStandalone();
+
+private:
+
+ int nErrorCount = 0;
+};
+
+void AtomicFlagBasicTest::TestAtomicFlagCtor()
+{
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == false);
+ }
+
+ {
+ AtomicType atomic{ false };
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == false);
+ }
+
+ {
+ AtomicType atomic{ true };
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == true);
+ }
+}
+
+void AtomicFlagBasicTest::TestAtomicFlagClear()
+{
+ {
+ AtomicType atomic;
+
+ atomic.clear(eastl::memory_order_relaxed);
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == false);
+ }
+
+ {
+ AtomicType atomic{ true };
+
+ atomic.clear(eastl::memory_order_relaxed);
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == false);
+ }
+}
+
+void AtomicFlagBasicTest::TestAtomicFlagTestAndSet()
+{
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic.test_and_set(eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == true);
+ }
+
+ {
+ AtomicType atomic{ true };
+
+ BoolType ret = atomic.test_and_set(eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == true);
+ }
+}
+
+void AtomicFlagBasicTest::TestAtomicFlagTest()
+{
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == false);
+ }
+
+ {
+ AtomicType atomic{ true };
+
+ VERIFY(atomic.test(eastl::memory_order_relaxed) == true);
+ }
+}
+
+void AtomicFlagBasicTest::TestAllMemoryOrders()
+{
+ {
+ AtomicType atomic;
+
+ atomic.clear();
+
+ atomic.clear(eastl::memory_order_relaxed);
+
+ atomic.clear(eastl::memory_order_release);
+
+ atomic.clear(eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ atomic.test_and_set();
+
+ atomic.test_and_set(eastl::memory_order_relaxed);
+
+ atomic.test_and_set(eastl::memory_order_acquire);
+
+ atomic.test_and_set(eastl::memory_order_release);
+
+ atomic.test_and_set(eastl::memory_order_acq_rel);
+
+ atomic.test_and_set(eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic.test();
+
+ ret = atomic.test(eastl::memory_order_relaxed);
+
+ ret = atomic.test(eastl::memory_order_acquire);
+
+ ret = atomic.test(eastl::memory_order_seq_cst);
+ }
+}
+
+void AtomicFlagBasicTest::TestAtomicFlagStandalone()
+{
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic_flag_test_and_set(&atomic);
+
+ ret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_relaxed);
+
+ ret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_acquire);
+
+ ret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_release);
+
+ ret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_acq_rel);
+
+ ret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ atomic_flag_clear(&atomic);
+
+ atomic_flag_clear_explicit(&atomic, eastl::memory_order_relaxed);
+
+ atomic_flag_clear_explicit(&atomic, eastl::memory_order_release);
+
+ atomic_flag_clear_explicit(&atomic, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic_flag_test(&atomic);
+
+ ret = atomic_flag_test_explicit(&atomic, eastl::memory_order_relaxed);
+
+ ret = atomic_flag_test_explicit(&atomic, eastl::memory_order_acquire);
+
+ ret = atomic_flag_test_explicit(&atomic, eastl::memory_order_seq_cst);
+ }
+}
+
+class AtomicVoidPointerBasicTest
+{
+public:
+
+ using AtomicType = eastl::atomic<void*>;
+ using PtrType = void*;
+
+ int RunTest()
+ {
+ TestAtomicCtor();
+
+ TestAssignmentOperators();
+
+ TestIsLockFree();
+
+ TestStore();
+
+ TestLoad();
+
+ TestExchange();
+
+ TestCompareExchangeWeak();
+
+ TestCompareExchangeStrong();
+
+ TestAllMemoryOrders();
+
+ return nErrorCount;
+ }
+
+private:
+
+ void TestAtomicCtor();
+
+ void TestAssignmentOperators();
+
+ void TestIsLockFree();
+
+ void TestStore();
+
+ void TestLoad();
+
+ void TestExchange();
+
+ void TestCompareExchangeWeak();
+
+ void TestCompareExchangeStrong();
+
+ void TestAllMemoryOrders();
+
+private:
+
+ int nErrorCount = 0;
+};
+
+void AtomicVoidPointerBasicTest::TestAtomicCtor()
+{
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic{ (PtrType)0x04 };
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x04);
+ }
+}
+
+void AtomicVoidPointerBasicTest::TestAssignmentOperators()
+{
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic = (PtrType)0x04;
+
+ VERIFY(ret == (PtrType)0x04);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x04);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic = (PtrType)0x0;
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+}
+
+void AtomicVoidPointerBasicTest::TestIsLockFree()
+{
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic.is_lock_free() == true);
+
+ VERIFY(atomic.is_always_lock_free == true);
+ }
+}
+
+void AtomicVoidPointerBasicTest::TestStore()
+{
+ {
+ PtrType val = (PtrType)0x0;
+ AtomicType atomic;
+
+ atomic.store(val, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == val);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic;
+
+ atomic.store(val, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == val);
+ }
+}
+
+void AtomicVoidPointerBasicTest::TestLoad()
+{
+ {
+ AtomicType atomic{ (PtrType)0x4 };
+
+ PtrType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic == (PtrType)0x4);
+ }
+}
+
+void AtomicVoidPointerBasicTest::TestExchange()
+{
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.exchange((PtrType)0x4, eastl::memory_order_release);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+}
+
+void AtomicVoidPointerBasicTest::TestCompareExchangeWeak()
+{
+ {
+ AtomicType atomic;
+
+ PtrType observed = (PtrType)0x0;
+ bool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ if (ret)
+ {
+ VERIFY(ret == true);
+ VERIFY(observed == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType observed = (PtrType)0x4;
+ bool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ VERIFY(observed == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+}
+
+void AtomicVoidPointerBasicTest::TestCompareExchangeStrong()
+{
+ {
+ AtomicType atomic;
+
+ PtrType observed = (PtrType)0x0;
+ bool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+ VERIFY(observed == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType observed = (PtrType)0x4;
+ bool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ VERIFY(observed == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+}
+
+void AtomicVoidPointerBasicTest::TestAllMemoryOrders()
+{
+ {
+ AtomicType atomic;
+ PtrType val = (PtrType)0x4;
+
+ atomic.store(val);
+
+ atomic.store(val, eastl::memory_order_relaxed);
+
+ atomic.store(val, eastl::memory_order_release);
+
+ atomic.store(val, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.load();
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ ret = atomic.load(eastl::memory_order_acquire);
+
+ ret = atomic.load(eastl::memory_order_seq_cst);
+
+ ret = atomic.load(eastl::memory_order_read_depends);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.exchange((PtrType)0x4);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_relaxed);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_acquire);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_release);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_acq_rel);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType observed = (PtrType)0x0;
+
+ bool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType observed = (PtrType)0x0;
+
+ bool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType observed = (PtrType)0x0;
+ bool ret;
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_release, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType observed = (PtrType)0x0;
+ bool ret;
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_release, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);
+ }
+}
+
+class AtomicPointerBasicTest
+{
+public:
+
+ using AtomicType = eastl::atomic<uint32_t*>;
+ using PtrType = uint32_t*;
+
+ int RunTest()
+ {
+ TestAtomicCtor();
+
+ TestAssignmentOperators();
+
+ TestIsLockFree();
+
+ TestStore();
+
+ TestLoad();
+
+ TestExchange();
+
+ TestCompareExchangeWeak();
+
+ TestCompareExchangeStrong();
+
+ TestAllMemoryOrders();
+
+ TestFetchAdd();
+ TestAddFetch();
+
+ TestFetchSub();
+ TestSubFetch();
+
+ TestAtomicPointerStandalone();
+
+ return nErrorCount;
+ }
+
+private:
+
+ void TestAtomicCtor();
+
+ void TestAssignmentOperators();
+
+ void TestIsLockFree();
+
+ void TestStore();
+
+ void TestLoad();
+
+ void TestExchange();
+
+ void TestCompareExchangeWeak();
+
+ void TestCompareExchangeStrong();
+
+ void TestAllMemoryOrders();
+
+ void TestFetchAdd();
+ void TestAddFetch();
+
+ void TestFetchSub();
+ void TestSubFetch();
+
+ void TestAtomicPointerStandalone();
+
+private:
+
+ int nErrorCount = 0;
+};
+
+void AtomicPointerBasicTest::TestAtomicCtor()
+{
+ {
+ AtomicType atomic{};
+
+ PtrType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == nullptr);
+ }
+
+ {
+ AtomicType atomic{ (PtrType)0x4 };
+
+ PtrType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+ }
+}
+
+void AtomicPointerBasicTest::TestAssignmentOperators()
+{
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{val};
+
+ PtrType expected = (PtrType)0x8;
+
+ PtrType ret = atomic = expected;
+
+ VERIFY(ret == expected);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ PtrType val = (PtrType)0x0;
+ AtomicType atomic{val};
+
+ PtrType ret = atomic = val;
+
+ VERIFY(ret == val);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == val);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{val};
+
+ PtrType expected = (PtrType)0x8;
+ PtrType ret = ++atomic;
+
+ VERIFY(ret == expected);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+
+ AtomicType atomic{val};
+
+ PtrType expected = (PtrType)0x8;
+ PtrType ret = atomic++;
+
+ VERIFY(ret == val);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{val};
+
+ PtrType expected = (PtrType)0x10;
+ PtrType ret = atomic += 3;
+
+ VERIFY(ret == expected);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{val};
+
+ PtrType expected = (PtrType)0x4;
+ PtrType ret = atomic += 0;
+
+ VERIFY(ret == expected);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{val};
+
+ PtrType expected = (PtrType)0x0;
+ PtrType ret = atomic -= 1;
+
+ VERIFY(ret == expected);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{val};
+
+ PtrType expected = (PtrType)0x4;
+ PtrType ret = atomic -= 0;
+
+ VERIFY(ret == expected);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+}
+
+void AtomicPointerBasicTest::TestIsLockFree()
+{
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic.is_lock_free() == true);
+
+ VERIFY(atomic.is_always_lock_free == true);
+ }
+}
+
+void AtomicPointerBasicTest::TestStore()
+{
+ {
+ PtrType val = (PtrType)0x0;
+ AtomicType atomic;
+
+ atomic.store(val, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == val);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic;
+
+ atomic.store(val, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == val);
+ }
+}
+
+void AtomicPointerBasicTest::TestLoad()
+{
+ {
+ AtomicType atomic{ (PtrType)0x4 };
+
+ PtrType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic == (PtrType)0x4);
+ }
+}
+
+void AtomicPointerBasicTest::TestCompareExchangeWeak()
+{
+ {
+ AtomicType atomic;
+
+ PtrType observed = (PtrType)0x0;
+ bool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ if (ret)
+ {
+ VERIFY(ret == true);
+ VERIFY(observed == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType observed = (PtrType)0x4;
+ bool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ VERIFY(observed == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+}
+
+void AtomicPointerBasicTest::TestCompareExchangeStrong()
+{
+ {
+ AtomicType atomic;
+
+ PtrType observed = (PtrType)0x0;
+ bool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+ VERIFY(observed == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType observed = (PtrType)0x4;
+ bool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ VERIFY(observed == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+}
+
+void AtomicPointerBasicTest::TestExchange()
+{
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.exchange((PtrType)0x4, eastl::memory_order_release);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+}
+
+void AtomicPointerBasicTest::TestAllMemoryOrders()
+{
+ {
+ AtomicType atomic;
+ PtrType val = (PtrType)0x4;
+
+ atomic.store(val);
+
+ atomic.store(val, eastl::memory_order_relaxed);
+
+ atomic.store(val, eastl::memory_order_release);
+
+ atomic.store(val, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.load();
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ ret = atomic.load(eastl::memory_order_acquire);
+
+ ret = atomic.load(eastl::memory_order_seq_cst);
+
+ ret = atomic.load(eastl::memory_order_read_depends);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.fetch_add(0);
+
+ ret = atomic.fetch_add(0, eastl::memory_order_relaxed);
+
+ ret = atomic.fetch_add(0, eastl::memory_order_acquire);
+
+ ret = atomic.fetch_add(0, eastl::memory_order_release);
+
+ ret = atomic.fetch_add(0, eastl::memory_order_acq_rel);
+
+ ret = atomic.fetch_add(0, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.fetch_sub(0);
+
+ ret = atomic.fetch_sub(0, eastl::memory_order_relaxed);
+
+ ret = atomic.fetch_sub(0, eastl::memory_order_acquire);
+
+ ret = atomic.fetch_sub(0, eastl::memory_order_release);
+
+ ret = atomic.fetch_sub(0, eastl::memory_order_acq_rel);
+
+ ret = atomic.fetch_sub(0, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.add_fetch(0);
+
+ ret = atomic.add_fetch(0, eastl::memory_order_relaxed);
+
+ ret = atomic.add_fetch(0, eastl::memory_order_acquire);
+
+ ret = atomic.add_fetch(0, eastl::memory_order_release);
+
+ ret = atomic.add_fetch(0, eastl::memory_order_acq_rel);
+
+ ret = atomic.add_fetch(0, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.sub_fetch(0);
+
+ ret = atomic.sub_fetch(0, eastl::memory_order_relaxed);
+
+ ret = atomic.sub_fetch(0, eastl::memory_order_acquire);
+
+ ret = atomic.sub_fetch(0, eastl::memory_order_release);
+
+ ret = atomic.sub_fetch(0, eastl::memory_order_acq_rel);
+
+ ret = atomic.sub_fetch(0, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic.exchange((PtrType)0x4);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_relaxed);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_acquire);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_release);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_acq_rel);
+
+ ret = atomic.exchange((PtrType)0x4, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType observed = (PtrType)0x0;
+
+ bool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType observed = (PtrType)0x0;
+
+ bool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType observed = (PtrType)0x0;
+ bool ret;
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_release, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType observed = (PtrType)0x0;
+ bool ret;
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_release, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);
+ }
+}
+
+void AtomicPointerBasicTest::TestFetchAdd()
+{
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{ val };
+
+ PtrType ret = atomic.fetch_add(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x8);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{ val };
+
+ PtrType ret = atomic.fetch_add(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+}
+
+void AtomicPointerBasicTest::TestAddFetch()
+{
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{ val };
+
+ PtrType ret = atomic.add_fetch(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x8);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x8);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{ val };
+
+ PtrType ret = atomic.add_fetch(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+}
+
+void AtomicPointerBasicTest::TestFetchSub()
+{
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{ val };
+
+ PtrType ret = atomic.fetch_sub(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{ val };
+
+ PtrType ret = atomic.fetch_sub(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+}
+
+void AtomicPointerBasicTest::TestSubFetch()
+{
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{ val };
+
+ PtrType ret = atomic.sub_fetch(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+
+ {
+ PtrType val = (PtrType)0x4;
+ AtomicType atomic{ val };
+
+ PtrType ret = atomic.sub_fetch(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+}
+
+void AtomicPointerBasicTest::TestAtomicPointerStandalone()
+{
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic_is_lock_free(&atomic) == true);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType val = (PtrType)0x4;
+
+ atomic_store(&atomic, val);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == val);
+ }
+
+ {
+ AtomicType atomic;
+ PtrType val = (PtrType)0x4;
+
+ atomic_store_explicit(&atomic, val, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == val);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_load(&atomic);
+
+ VERIFY(ret == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_load_explicit(&atomic, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_load_cond(&atomic, [](PtrType val) { return true; });
+
+ VERIFY(ret == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_load_cond_explicit(&atomic, [](PtrType val) { return true; }, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_exchange(&atomic, (PtrType)0x4);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_exchange_explicit(&atomic, (PtrType)0x4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_add_fetch(&atomic, 1);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_add_fetch_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_fetch_add(&atomic, 1);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType ret = atomic_fetch_add_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic{ (PtrType)0x4 };
+
+ PtrType ret = atomic_fetch_sub(&atomic, 1);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic{ (PtrType)0x4 };
+
+ PtrType ret = atomic_fetch_sub_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x4);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic{ (PtrType)0x4 };
+
+ PtrType ret = atomic_sub_fetch(&atomic, 1);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic{ (PtrType)0x4 };
+
+ PtrType ret = atomic_sub_fetch_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == (PtrType)0x0);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType expected = (PtrType)0x0;
+ bool ret = atomic_compare_exchange_strong(&atomic, &expected, (PtrType)0x4);
+
+ VERIFY(ret == true);
+
+ VERIFY(expected == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType expected = (PtrType)0x0;
+ bool ret = atomic_compare_exchange_strong_explicit(&atomic, &expected, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+
+ VERIFY(expected == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType expected = (PtrType)0x0;
+ bool ret = atomic_compare_exchange_weak(&atomic, &expected, (PtrType)0x4);
+
+ if (ret)
+ {
+ VERIFY(ret == true);
+
+ VERIFY(expected == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+ }
+
+ {
+ AtomicType atomic;
+
+ PtrType expected = (PtrType)0x0;
+ bool ret = atomic_compare_exchange_weak_explicit(&atomic, &expected, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ if (ret)
+ {
+ VERIFY(ret == true);
+
+ VERIFY(expected == (PtrType)0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);
+ }
+ }
+}
+
+struct AtomicNonTriviallyConstructible
+{
+ AtomicNonTriviallyConstructible()
+ : a(0)
+ , b(0)
+ {
+ }
+
+ AtomicNonTriviallyConstructible(uint16_t a, uint16_t b)
+ : a(a)
+ , b(b)
+ {
+ }
+
+ friend bool operator==(const AtomicNonTriviallyConstructible& a, const AtomicNonTriviallyConstructible& b)
+ {
+ return a.a == b.a && a.b == b.b;
+ }
+
+ uint16_t a;
+ uint16_t b;
+};
+
+struct AtomicNonTriviallyConstructibleNoExcept
+{
+ AtomicNonTriviallyConstructibleNoExcept() noexcept
+ : a(0)
+ , b(0)
+ {
+ }
+
+ AtomicNonTriviallyConstructibleNoExcept(uint16_t a, uint16_t b) noexcept
+ : a(a)
+ , b(b)
+ {
+ }
+
+ friend bool operator==(const AtomicNonTriviallyConstructibleNoExcept& a, const AtomicNonTriviallyConstructibleNoExcept& b)
+ {
+ return a.a == b.a && a.b == b.b;
+ }
+
+ uint16_t a;
+ uint16_t b;
+};
+
+struct AtomicUserType16
+{
+ uint8_t a;
+ uint8_t b;
+
+ friend bool operator==(const AtomicUserType16& a, const AtomicUserType16& b)
+ {
+ return (a.a == b.a) && (a.b == b.b);
+ }
+};
+
+struct AtomicUserType128
+{
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ uint32_t d;
+
+ AtomicUserType128() = default;
+
+ AtomicUserType128(const AtomicUserType128&) = default;
+
+ AtomicUserType128(uint32_t a, uint32_t b)
+ : a(a)
+ , b(b)
+ , c(0)
+ , d(0)
+ {
+ }
+
+ AtomicUserType128& operator=(const AtomicUserType128&) = default;
+
+ friend bool operator==(const AtomicUserType128& a, const AtomicUserType128& b)
+ {
+ return (a.a == b.a) && (a.b == b.b) && (a.c == b.c) && (a.d == b.d);
+ }
+};
+
+template <typename T>
+class AtomicUserTypeBasicTest
+{
+public:
+
+ using AtomicType = eastl::atomic<T>;
+ using UserType = T;
+
+ int RunTest()
+ {
+ TestAtomicCtor();
+
+ TestAssignmentOperators();
+
+ TestIsLockFree();
+
+ TestStore();
+
+ TestLoad();
+
+ TestExchange();
+
+ TestCompareExchangeWeak();
+
+ TestCompareExchangeStrong();
+
+ TestAllMemoryOrders();
+
+ return nErrorCount;
+ }
+
+private:
+
+ void TestAtomicCtor();
+
+ void TestAssignmentOperators();
+
+ void TestIsLockFree();
+
+ void TestStore();
+
+ void TestLoad();
+
+ void TestExchange();
+
+ void TestCompareExchangeWeak();
+
+ void TestCompareExchangeStrong();
+
+ void TestAllMemoryOrders();
+
+private:
+
+ int nErrorCount = 0;
+};
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestAtomicCtor()
+{
+ {
+ AtomicType atomic;
+ UserType expected{0, 0};
+
+ UserType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == expected);
+ }
+
+ {
+ AtomicType atomic{ {5, 8} };
+ UserType expected{5, 8};
+
+ UserType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == expected);
+ }
+}
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestAssignmentOperators()
+{
+ {
+ AtomicType atomic;
+ UserType expected{5, 6};
+
+ atomic = {5, 6};
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ AtomicType atomic;
+ UserType expected{0, 0};
+
+ atomic = {0, 0};
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+}
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestIsLockFree()
+{
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic.is_lock_free() == true);
+
+ VERIFY(AtomicType::is_always_lock_free == true);
+ }
+}
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestStore()
+{
+ {
+ AtomicType atomic;
+ UserType expected{5, 6};
+
+ atomic.store(expected, eastl::memory_order_relaxed);
+
+ UserType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == expected);
+ }
+
+ {
+ AtomicType atomic;
+ UserType expected{5, 6};
+
+ atomic.store({5, 6}, eastl::memory_order_relaxed);
+
+ UserType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == expected);
+ }
+}
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestLoad()
+{
+ {
+ AtomicType atomic;
+ UserType expected{0, 0};
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+
+ VERIFY(atomic == expected);
+ }
+
+ {
+ AtomicType atomic{ {5, 6} };
+ UserType expected{5, 6};
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+
+ VERIFY(atomic == expected);
+ }
+}
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestExchange()
+{
+ {
+ AtomicType atomic;
+ UserType expected{0, 0};
+
+ UserType ret = atomic.exchange({0, 0}, eastl::memory_order_relaxed);
+
+ VERIFY(ret == expected);
+ }
+
+ {
+ AtomicType atomic;
+ UserType expected{0, 0};
+ UserType expected2{0, 1};
+
+ UserType ret = atomic.exchange({0, 1}, eastl::memory_order_relaxed);
+
+ VERIFY(ret == expected);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected2);
+ }
+}
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestCompareExchangeWeak()
+{
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 0};
+ bool ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_relaxed);
+
+ UserType expected{0, 0};
+ if (ret)
+ {
+ VERIFY(ret == true);
+ VERIFY(observed == expected);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 0};
+ bool ret = atomic.compare_exchange_weak(observed, {0, 1}, eastl::memory_order_relaxed);
+
+ UserType expected{0, 1};
+ UserType expected2{0, 0};
+ if (ret)
+ {
+ VERIFY(ret == true);
+ VERIFY(observed == expected2);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 1};
+ bool ret = atomic.compare_exchange_weak(observed, {0, 1}, eastl::memory_order_relaxed);
+
+ UserType expected{0, 0};
+
+ VERIFY(ret == false);
+ VERIFY(observed == expected);
+ }
+}
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestCompareExchangeStrong()
+{
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 0};
+ bool ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_relaxed);
+
+ UserType expected{0, 0};
+
+ VERIFY(ret == true);
+ VERIFY(observed == expected);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 0};
+ bool ret = atomic.compare_exchange_strong(observed, {0, 1}, eastl::memory_order_relaxed);
+
+ UserType expected{0, 1};
+ UserType expected2{0, 0};
+
+ VERIFY(ret == true);
+ VERIFY(observed == expected2);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == expected);
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 1};
+ bool ret = atomic.compare_exchange_strong(observed, {0, 1}, eastl::memory_order_relaxed);
+
+ UserType expected{0, 0};
+
+ VERIFY(ret == false);
+ VERIFY(observed == expected);
+ }
+}
+
+template <typename T>
+void AtomicUserTypeBasicTest<T>::TestAllMemoryOrders()
+{
+ {
+ AtomicType atomic;
+ UserType val{0, 1};
+
+ atomic.store(val);
+
+ atomic.store(val, eastl::memory_order_relaxed);
+
+ atomic.store(val, eastl::memory_order_release);
+
+ atomic.store(val, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType ret = atomic.load();
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ ret = atomic.load(eastl::memory_order_acquire);
+
+ ret = atomic.load(eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType ret = atomic.exchange({0, 1});
+
+ ret = atomic.exchange({0, 0}, eastl::memory_order_relaxed);
+
+ ret = atomic.exchange({0, 0}, eastl::memory_order_acquire);
+
+ ret = atomic.exchange({0, 0}, eastl::memory_order_release);
+
+ ret = atomic.exchange({0, 0}, eastl::memory_order_acq_rel);
+
+ ret = atomic.exchange({0, 0}, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 0};
+
+ bool ret = atomic.compare_exchange_weak(observed, {0, 0});
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 0};
+
+ bool ret = atomic.compare_exchange_strong(observed, {0, 0});
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 0};
+ bool ret;
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acquire, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acquire, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_release, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acq_rel, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ UserType observed{0, 0};
+ bool ret;
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acquire, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acquire, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_release, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acq_rel, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);
+ }
+}
+
+
+class AtomicBoolBasicTest
+{
+public:
+
+ using AtomicType = eastl::atomic<bool>;
+ using BoolType = bool;
+
+ int RunTest()
+ {
+ TestAtomicCtor();
+
+ TestAssignmentOperators();
+
+ TestIsLockFree();
+
+ TestStore();
+
+ TestLoad();
+
+ TestExchange();
+
+ TestCompareExchangeWeak();
+
+ TestCompareExchangeStrong();
+
+ TestAllMemoryOrders();
+
+ return nErrorCount;
+ }
+
+private:
+
+ void TestAtomicCtor();
+
+ void TestAssignmentOperators();
+
+ void TestIsLockFree();
+
+ void TestStore();
+
+ void TestLoad();
+
+ void TestExchange();
+
+ void TestCompareExchangeWeak();
+
+ void TestCompareExchangeStrong();
+
+ void TestAllMemoryOrders();
+
+private:
+
+ int nErrorCount = 0;
+};
+
+void AtomicBoolBasicTest::TestAtomicCtor()
+{
+ {
+ AtomicType atomic{ false };
+
+ BoolType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ }
+
+ {
+ AtomicType atomic{ true };
+
+ BoolType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ }
+
+ {
+ AtomicType atomic{};
+
+ BoolType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ }
+}
+
+void AtomicBoolBasicTest::TestAssignmentOperators()
+{
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic = true;
+
+ VERIFY(ret == true);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == true);
+ }
+}
+
+void AtomicBoolBasicTest::TestIsLockFree()
+{
+ {
+ AtomicType atomic;
+
+ bool ret = atomic.is_lock_free();
+
+ VERIFY(ret == true);
+
+ VERIFY(AtomicType::is_always_lock_free == true);
+ }
+}
+
+void AtomicBoolBasicTest::TestStore()
+{
+ {
+ AtomicType atomic;
+
+ atomic.store(true, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == true);
+ }
+}
+
+void AtomicBoolBasicTest::TestLoad()
+{
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == false);
+
+ VERIFY(atomic == false);
+ }
+
+ {
+ AtomicType atomic{ true };
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == true);
+
+ VERIFY(atomic == true);
+ }
+}
+
+void AtomicBoolBasicTest::TestExchange()
+{
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic.exchange(false, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == false);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic.exchange(true, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == true);
+ }
+}
+
+void AtomicBoolBasicTest::TestCompareExchangeWeak()
+{
+ {
+ AtomicType atomic{ false };
+
+ BoolType observed = false;
+ bool ret = atomic.compare_exchange_weak(observed, false, eastl::memory_order_relaxed);
+
+ if (ret)
+ {
+ VERIFY(ret == true);
+ VERIFY(observed == false);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == false);
+ }
+ }
+
+ {
+ AtomicType atomic{ false };
+
+ BoolType observed = false;
+ bool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);
+
+ if (ret)
+ {
+ VERIFY(ret == true);
+ VERIFY(observed == false);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == true);
+ }
+ }
+
+ {
+ AtomicType atomic{ false };
+
+ BoolType observed = true;
+ bool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ VERIFY(observed == false);
+ }
+}
+
+void AtomicBoolBasicTest::TestCompareExchangeStrong()
+{
+ {
+ AtomicType atomic{ false };
+
+ BoolType observed = false;
+ bool ret = atomic.compare_exchange_weak(observed, false, eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+ VERIFY(observed == false);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == false);
+ }
+
+ {
+ AtomicType atomic{ false };
+
+ BoolType observed = false;
+ bool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+ VERIFY(observed == false);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == true);
+ }
+
+ {
+ AtomicType atomic{ false };
+
+ BoolType observed = true;
+ bool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ VERIFY(observed == false);
+ }
+}
+
+void AtomicBoolBasicTest::TestAllMemoryOrders()
+{
+ {
+ AtomicType atomic;
+
+ atomic.store(true);
+
+ atomic.store(true, eastl::memory_order_relaxed);
+
+ atomic.store(true, eastl::memory_order_release);
+
+ atomic.store(true, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic.load();
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ ret = atomic.load(eastl::memory_order_acquire);
+
+ ret = atomic.load(eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType ret = atomic.exchange(true);
+
+ ret = atomic.exchange(true, eastl::memory_order_relaxed);
+
+ ret = atomic.exchange(true, eastl::memory_order_acquire);
+
+ ret = atomic.exchange(true, eastl::memory_order_release);
+
+ ret = atomic.exchange(true, eastl::memory_order_acq_rel);
+
+ ret = atomic.exchange(true, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType observed = false;
+ bool ret = atomic.compare_exchange_weak(observed, true);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType observed = false;
+ bool ret = atomic.compare_exchange_strong(observed, true);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType observed = false;
+ bool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acquire, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acquire, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_release, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acq_rel, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic;
+
+ BoolType observed = false;
+ bool ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acquire, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acquire, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_release, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acq_rel, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);
+ }
+}
+
+
+template <typename T>
+class AtomicIntegralBasicTest
+{
+public:
+
+ using AtomicType = eastl::atomic<T>;
+ using IntegralType = T;
+
+ int RunTest()
+ {
+ TestAtomicCtor();
+
+ TestAtomicFetchAdd();
+ TestAtomicAddFetch();
+
+ TestAtomicFetchSub();
+ TestAtomicSubFetch();
+
+ TestAtomicFetchAnd();
+ TestAtomicAndFetch();
+
+ TestAtomicFetchOr();
+ TestAtomicOrFetch();
+
+ TestAtomicFetchXor();
+ TestAtomicXorFetch();
+
+ TestAssignmentOperators();
+
+ TestIsLockFree();
+
+ TestStore();
+
+ TestLoad();
+
+ TestExchange();
+
+ TestCompareExchangeWeak();
+
+ TestCompareExchangeStrong();
+
+ TestAllMemoryOrders();
+
+ TestAtomicStandalone();
+
+ return nErrorCount;
+ }
+
+private:
+
+ void TestAtomicCtor();
+
+ void TestAtomicFetchAdd();
+ void TestAtomicAddFetch();
+
+ void TestAtomicFetchSub();
+ void TestAtomicSubFetch();
+
+ void TestAtomicFetchAnd();
+ void TestAtomicAndFetch();
+
+ void TestAtomicFetchOr();
+ void TestAtomicOrFetch();
+
+ void TestAtomicFetchXor();
+ void TestAtomicXorFetch();
+
+ void TestAssignmentOperators();
+
+ void TestIsLockFree();
+
+ void TestStore();
+
+ void TestLoad();
+
+ void TestExchange();
+
+ void TestCompareExchangeWeak();
+
+ void TestCompareExchangeStrong();
+
+ void TestAllMemoryOrders();
+
+ void TestAtomicStandalone();
+
+private:
+
+ int nErrorCount = 0;
+};
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicCtor()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ }
+
+ {
+ AtomicType atomic{ 20 };
+
+ IntegralType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 20);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicFetchAdd()
+{
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic.fetch_add(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic.fetch_add(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 5 };
+
+ IntegralType ret = atomic.fetch_add(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 5);
+
+ ret = atomic.fetch_add(4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 5);
+
+ ret = atomic.fetch_add(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 9);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 10);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicAddFetch()
+{
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic.add_fetch(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic.add_fetch(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 5 };
+
+ IntegralType ret = atomic.add_fetch(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 5);
+
+ ret = atomic.add_fetch(4, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 9);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 9);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicFetchSub()
+{
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic.fetch_sub(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic.fetch_sub(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ }
+
+ {
+ AtomicType atomic{ 5 };
+
+ IntegralType ret = atomic.fetch_sub(2, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 5);
+
+ ret = atomic.fetch_sub(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 3);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 2);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicSubFetch()
+{
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic.sub_fetch(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic.sub_fetch(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ }
+
+ {
+ AtomicType atomic{ 5 };
+
+ IntegralType ret = atomic.sub_fetch(2, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 3);
+
+ ret = atomic.sub_fetch(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 2);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 2);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicFetchAnd()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.fetch_and(0x0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.fetch_and(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 0xF };
+
+ IntegralType ret = atomic.fetch_and(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0xF);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0X1);
+ }
+
+ {
+ AtomicType atomic{ 0xF };
+
+ IntegralType ret = atomic.fetch_and(0xF0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0xF);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicAndFetch()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.and_fetch(0x0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.and_fetch(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 0xF };
+
+ IntegralType ret = atomic.and_fetch(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+
+ {
+ AtomicType atomic{ 0xF };
+
+ IntegralType ret = atomic.and_fetch(0xF0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicFetchOr()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.fetch_or(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic.fetch_or(0x0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic.fetch_or(0x2, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x3);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicOrFetch()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.or_fetch(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic.or_fetch(0x0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic.or_fetch(0x2, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x3);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x3);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicFetchXor()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.fetch_xor(0x0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic.fetch_xor(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ }
+
+ {
+ AtomicType atomic{ 0x0 };
+
+ IntegralType ret = atomic.fetch_xor(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicXorFetch()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.xor_fetch(0x0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic.xor_fetch(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ }
+
+ {
+ AtomicType atomic{ 0x0 };
+
+ IntegralType ret = atomic.xor_fetch(0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAssignmentOperators()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = (atomic = 5);
+
+ VERIFY(ret == 5);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 5);
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = ++atomic;
+
+ VERIFY(ret == 1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic++;
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = --atomic;
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic--;
+
+ VERIFY(ret == 1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic += 5;
+
+ VERIFY(ret == 5);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 5);
+ }
+
+ {
+ AtomicType atomic{ 5 };
+
+ IntegralType ret = atomic -= 3;
+
+ VERIFY(ret == 2);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 2);
+ }
+
+ {
+ AtomicType atomic{ 0x0 };
+
+ IntegralType ret = atomic |= 0x1;
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic &= 0x1;
+
+ VERIFY(ret == 0x1);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic ^= 0x1;
+
+ VERIFY(ret == 0x0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestIsLockFree()
+{
+ {
+ const AtomicType atomic{ 5 };
+
+ VERIFY(atomic.is_lock_free() == true);
+
+ VERIFY(AtomicType::is_always_lock_free == true);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestStore()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ atomic.store(0, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0);
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ atomic.store(1, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestLoad()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0);
+
+ bool ret = atomic == 0;
+ VERIFY(ret == true);
+
+ VERIFY(atomic == 0);
+ }
+
+ {
+ AtomicType atomic{ 5 };
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 5);
+
+ bool ret = atomic == 5;
+ VERIFY(ret == true);
+
+ VERIFY(atomic == 5);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestExchange()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.exchange(0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType ret = atomic.exchange(1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestCompareExchangeWeak()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType observed = 0;
+ bool ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_relaxed);
+
+ if (ret == true)
+ {
+ VERIFY(ret == true);
+ VERIFY(observed == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType observed = 1;
+ bool ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ VERIFY(observed == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestCompareExchangeStrong()
+{
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType observed = 0;
+ bool ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+ VERIFY(observed == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic{ 0 };
+
+ IntegralType observed = 1;
+ bool ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == false);
+ VERIFY(observed == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0);
+ }
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAllMemoryOrders()
+{
+ {
+ AtomicType atomic{};
+
+ atomic.store(1);
+
+ atomic.store(1, eastl::memory_order_relaxed);
+
+ atomic.store(1, eastl::memory_order_release);
+
+ atomic.store(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.load();
+
+ ret = atomic.load(eastl::memory_order_relaxed);
+
+ ret = atomic.load(eastl::memory_order_acquire);
+
+ ret = atomic.load(eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.exchange(1);
+
+ ret = atomic.exchange(1, eastl::memory_order_relaxed);
+
+ ret = atomic.exchange(1, eastl::memory_order_acquire);
+
+ ret = atomic.exchange(1, eastl::memory_order_release);
+
+ ret = atomic.exchange(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.exchange(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.fetch_add(1);
+
+ ret = atomic.fetch_add(1, eastl::memory_order_relaxed);
+
+ ret = atomic.fetch_add(1, eastl::memory_order_acquire);
+
+ ret = atomic.fetch_add(1, eastl::memory_order_release);
+
+ ret = atomic.fetch_add(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.fetch_add(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.add_fetch(1);
+
+ ret = atomic.add_fetch(1, eastl::memory_order_relaxed);
+
+ ret = atomic.add_fetch(1, eastl::memory_order_acquire);
+
+ ret = atomic.add_fetch(1, eastl::memory_order_release);
+
+ ret = atomic.add_fetch(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.add_fetch(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.fetch_sub(1);
+
+ ret = atomic.fetch_sub(1, eastl::memory_order_relaxed);
+
+ ret = atomic.fetch_sub(1, eastl::memory_order_acquire);
+
+ ret = atomic.fetch_sub(1, eastl::memory_order_release);
+
+ ret = atomic.fetch_sub(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.fetch_sub(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.sub_fetch(1);
+
+ ret = atomic.sub_fetch(1, eastl::memory_order_relaxed);
+
+ ret = atomic.sub_fetch(1, eastl::memory_order_acquire);
+
+ ret = atomic.sub_fetch(1, eastl::memory_order_release);
+
+ ret = atomic.sub_fetch(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.sub_fetch(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.fetch_and(1);
+
+ ret = atomic.fetch_and(1, eastl::memory_order_relaxed);
+
+ ret = atomic.fetch_and(1, eastl::memory_order_acquire);
+
+ ret = atomic.fetch_and(1, eastl::memory_order_release);
+
+ ret = atomic.fetch_and(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.fetch_and(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.and_fetch(1);
+
+ ret = atomic.and_fetch(1, eastl::memory_order_relaxed);
+
+ ret = atomic.and_fetch(1, eastl::memory_order_acquire);
+
+ ret = atomic.and_fetch(1, eastl::memory_order_release);
+
+ ret = atomic.and_fetch(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.and_fetch(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.fetch_or(1);
+
+ ret = atomic.fetch_or(1, eastl::memory_order_relaxed);
+
+ ret = atomic.fetch_or(1, eastl::memory_order_acquire);
+
+ ret = atomic.fetch_or(1, eastl::memory_order_release);
+
+ ret = atomic.fetch_or(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.fetch_or(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.or_fetch(1);
+
+ ret = atomic.or_fetch(1, eastl::memory_order_relaxed);
+
+ ret = atomic.or_fetch(1, eastl::memory_order_acquire);
+
+ ret = atomic.or_fetch(1, eastl::memory_order_release);
+
+ ret = atomic.or_fetch(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.or_fetch(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.fetch_xor(1);
+
+ ret = atomic.fetch_xor(1, eastl::memory_order_relaxed);
+
+ ret = atomic.fetch_xor(1, eastl::memory_order_acquire);
+
+ ret = atomic.fetch_xor(1, eastl::memory_order_release);
+
+ ret = atomic.fetch_xor(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.fetch_xor(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType ret = atomic.xor_fetch(1);
+
+ ret = atomic.xor_fetch(1, eastl::memory_order_relaxed);
+
+ ret = atomic.xor_fetch(1, eastl::memory_order_acquire);
+
+ ret = atomic.xor_fetch(1, eastl::memory_order_release);
+
+ ret = atomic.xor_fetch(1, eastl::memory_order_acq_rel);
+
+ ret = atomic.xor_fetch(1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType observed = 0;
+ bool ret;
+
+ ret = atomic.compare_exchange_weak(observed, 1);
+
+ ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType observed = 0;
+ bool ret;
+
+ ret = atomic.compare_exchange_strong(observed, 1);
+
+ ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_release);
+
+ ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_acq_rel);
+
+ ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType observed = 0;
+ bool ret;
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_relaxed,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_acquire,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_acquire,
+ eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_release,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_acq_rel,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_acq_rel,
+ eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_seq_cst,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_seq_cst,
+ eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_weak(observed, 1,
+ eastl::memory_order_seq_cst,
+ eastl::memory_order_seq_cst);
+ }
+
+ {
+ AtomicType atomic{};
+
+ IntegralType observed = 0;
+ bool ret;
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_relaxed,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_acquire,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_acquire,
+ eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_release,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_acq_rel,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_acq_rel,
+ eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_seq_cst,
+ eastl::memory_order_relaxed);
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_seq_cst,
+ eastl::memory_order_acquire);
+
+ ret = atomic.compare_exchange_strong(observed, 1,
+ eastl::memory_order_seq_cst,
+ eastl::memory_order_seq_cst);
+ }
+
+}
+
+template <typename T>
+void AtomicIntegralBasicTest<T>::TestAtomicStandalone()
+{
+ {
+ AtomicType atomic;
+
+ IntegralType expected = 0;
+ bool ret = atomic_compare_exchange_weak(&atomic, &expected, 1);
+
+ if (ret)
+ {
+ VERIFY(ret == true);
+
+ VERIFY(expected == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType expected = 0;
+ bool ret = atomic_compare_exchange_weak_explicit(&atomic, &expected, 1, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ if (ret)
+ {
+ VERIFY(ret == true);
+
+ VERIFY(expected == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType expected = 0;
+ bool ret = atomic_compare_exchange_strong(&atomic, &expected, 1);
+
+ VERIFY(ret == true);
+
+ VERIFY(expected == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType expected = 0;
+ bool ret = atomic_compare_exchange_strong_explicit(&atomic, &expected, 1, eastl::memory_order_relaxed, eastl::memory_order_relaxed);
+
+ VERIFY(ret == true);
+
+ VERIFY(expected == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_fetch_xor(&atomic, 0x1);
+
+ VERIFY(ret == 0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_fetch_xor_explicit(&atomic, 0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_xor_fetch(&atomic, 0x1);
+
+ VERIFY(ret == 0x1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_xor_fetch_explicit(&atomic, 0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_fetch_or(&atomic, 0x1);
+
+ VERIFY(ret == 0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_fetch_or_explicit(&atomic, 0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_or_fetch(&atomic, 0x1);
+
+ VERIFY(ret == 0x1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_or_fetch_explicit(&atomic, 0x1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic_fetch_and(&atomic, 0x0);
+
+ VERIFY(ret == 0x1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x0);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic_fetch_and_explicit(&atomic, 0x0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x0);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic_and_fetch(&atomic, 0x0);
+
+ VERIFY(ret == 0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x0);
+ }
+
+ {
+ AtomicType atomic{ 0x1 };
+
+ IntegralType ret = atomic_and_fetch_explicit(&atomic, 0x0, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0x0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0x0);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic_fetch_sub(&atomic, 1);
+
+ VERIFY(ret == 1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic_fetch_sub_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic_sub_fetch(&atomic, 1);
+
+ VERIFY(ret == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0);
+ }
+
+ {
+ AtomicType atomic{ 1 };
+
+ IntegralType ret = atomic_sub_fetch_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 0);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_fetch_add(&atomic, 1);
+
+ VERIFY(ret == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_fetch_add_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_add_fetch(&atomic, 1);
+
+ VERIFY(ret == 1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_add_fetch_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 1);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_exchange(&atomic, 1);
+
+ VERIFY(ret == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_exchange_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_load(&atomic);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_load_explicit(&atomic, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_load_cond(&atomic, [](IntegralType val) { return true; });
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic;
+
+ IntegralType ret = atomic_load_cond_explicit(&atomic, [](IntegralType val) { return true; }, eastl::memory_order_relaxed);
+
+ VERIFY(ret == 0);
+ }
+
+ {
+ AtomicType atomic;
+
+ atomic_store(&atomic, 1);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ atomic_store_explicit(&atomic, 1, eastl::memory_order_relaxed);
+
+ VERIFY(atomic.load(eastl::memory_order_relaxed) == 1);
+ }
+
+ {
+ AtomicType atomic;
+
+ VERIFY(atomic_is_lock_free(&atomic) == true);
+ }
+}
+
+struct AtomicNonDefaultConstructible
+{
+ AtomicNonDefaultConstructible(uint8_t a)
+ : a(a)
+ {
+ }
+
+ friend bool operator==(const AtomicNonDefaultConstructible& a, const AtomicNonDefaultConstructible& b)
+ {
+ return a.a == b.a;
+ }
+
+ uint8_t a;
+};
+
+#if defined(EASTL_ATOMIC_HAS_8BIT)
+
+int TestAtomicNonDefaultConstructible()
+{
+ int nErrorCount = 0;
+
+ {
+ eastl::atomic<AtomicNonDefaultConstructible> atomic{AtomicNonDefaultConstructible{(uint8_t)3}};
+
+ VERIFY(atomic.load() == AtomicNonDefaultConstructible{(uint8_t)3});
+ }
+
+ {
+ eastl::atomic<AtomicNonDefaultConstructible> atomic{AtomicNonDefaultConstructible{(uint8_t)3}};
+
+ atomic.store(AtomicNonDefaultConstructible{(uint8_t)4});
+
+ VERIFY(atomic.load() == AtomicNonDefaultConstructible{(uint8_t)4});
+ }
+
+ {
+ eastl::atomic<AtomicNonDefaultConstructible> atomic{AtomicNonDefaultConstructible{(uint8_t)3}};
+
+ VERIFY(atomic_load_cond(&atomic, [] (AtomicNonDefaultConstructible) { return true; }) == AtomicNonDefaultConstructible{(uint8_t)3});
+ }
+
+ {
+ eastl::atomic<AtomicNonDefaultConstructible> atomic{AtomicNonDefaultConstructible{(uint8_t)3}};
+
+ VERIFY(atomic_load_cond_explicit(&atomic, [] (AtomicNonDefaultConstructible) { return true; }, eastl::memory_order_seq_cst) == AtomicNonDefaultConstructible{(uint8_t)3});
+ }
+
+ return nErrorCount;
+}
+
+#endif
+
+struct Atomic128LoadType
+{
+ friend bool operator==(const Atomic128LoadType& a, const Atomic128LoadType& b)
+ {
+ return a.a == b.a && a.b == b.b && a.c == b.c && a.d == b.d;
+ }
+
+ uint32_t a, b, c, d;
+};
+
+#if defined(EASTL_ATOMIC_HAS_128BIT)
+
+int TestAtomic128Loads()
+{
+ int nErrorCount = 0;
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{1, 1, 0, 0}};
+
+ VERIFY((atomic.load() == Atomic128LoadType{1, 1, 0, 0}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 1, 1}};
+
+ VERIFY((atomic.load() == Atomic128LoadType{0, 0, 1, 1}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 1, 0, 1}};
+
+ VERIFY((atomic.load() == Atomic128LoadType{0, 1, 0, 1}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{1, 0, 1, 0}};
+
+ VERIFY((atomic.load() == Atomic128LoadType{1, 0, 1, 0}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{1, 1, 0, 0}};
+
+ Atomic128LoadType expected{0, 0, 0, 0};
+ atomic.compare_exchange_strong(expected, Atomic128LoadType{1, 1, 0, 0});
+
+ VERIFY((expected == Atomic128LoadType{1, 1, 0, 0}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 1, 1}};
+
+ Atomic128LoadType expected{0, 0, 0, 0};
+ atomic.compare_exchange_strong(expected, Atomic128LoadType{0, 0, 1, 1});
+
+ VERIFY((expected == Atomic128LoadType{0, 0, 1, 1}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 1, 0, 1}};
+
+ Atomic128LoadType expected{0, 0, 0, 0};
+ atomic.compare_exchange_strong(expected, Atomic128LoadType{0, 1, 0, 1});
+
+ VERIFY((expected == Atomic128LoadType{0, 1, 0, 1}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{1, 0, 1, 0}};
+
+ Atomic128LoadType expected{0, 0, 0, 0};
+ atomic.compare_exchange_strong(expected, Atomic128LoadType{1, 0, 1, 0});
+
+ VERIFY((expected == Atomic128LoadType{1, 0, 1, 0}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 0, 0}};
+
+ Atomic128LoadType expected{0, 0, 0, 0};
+ atomic.compare_exchange_strong(expected, Atomic128LoadType{1, 1, 0, 0});
+
+ VERIFY((atomic.load() == Atomic128LoadType{1, 1, 0, 0}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 0, 0}};
+
+ Atomic128LoadType expected{0, 0, 0, 0};
+ atomic.compare_exchange_strong(expected, Atomic128LoadType{0, 0, 1, 1});
+
+ VERIFY((atomic.load() == Atomic128LoadType{0, 0, 1, 1}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 0, 0}};
+
+ Atomic128LoadType expected{0, 0, 0, 0};
+ atomic.compare_exchange_strong(expected, Atomic128LoadType{0, 1, 0, 1});
+
+ VERIFY((atomic.load() == Atomic128LoadType{0, 1, 0, 1}));
+ }
+
+ {
+ eastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 0, 0}};
+
+ Atomic128LoadType expected{0, 0, 0, 0};
+ atomic.compare_exchange_strong(expected, Atomic128LoadType{1, 0, 1, 0});
+
+ VERIFY((atomic.load() == Atomic128LoadType{1, 0, 1, 0}));
+ }
+
+ return nErrorCount;
+}
+
+#endif
+
+int TestAtomicBasic()
+{
+ int nErrorCount = 0;
+
+ #if defined(EASTL_ATOMIC_HAS_8BIT)
+ {
+ AtomicIntegralBasicTest<uint8_t> u8AtomicTest;
+
+ nErrorCount += u8AtomicTest.RunTest();
+ }
+ #endif
+
+ #if defined(EASTL_ATOMIC_HAS_16BIT)
+ {
+ AtomicIntegralBasicTest<uint16_t> u16AtomicTest;
+
+ nErrorCount += u16AtomicTest.RunTest();
+ }
+ #endif
+
+ #if defined(EASTL_ATOMIC_HAS_32BIT)
+ {
+ AtomicIntegralBasicTest<uint32_t> u32AtomicTest;
+
+ nErrorCount += u32AtomicTest.RunTest();
+ }
+ #endif
+
+ #if defined(EASTL_ATOMIC_HAS_64BIT)
+ {
+ AtomicIntegralBasicTest<uint64_t> u64AtomicTest;
+
+ nErrorCount += u64AtomicTest.RunTest();
+ }
+ #endif
+
+ #if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_GNUC))
+ {
+ AtomicIntegralBasicTest<__uint128_t> u128AtomicTest;
+
+ nErrorCount += u128AtomicTest.RunTest();
+ }
+
+ {
+ AtomicIntegralBasicTest<eastl_uint128_t> u128AtomicTest;
+
+ nErrorCount += u128AtomicTest.RunTest();
+ }
+ #endif
+
+ {
+ AtomicBoolBasicTest boolAtomicTest;
+
+ nErrorCount += boolAtomicTest.RunTest();
+ }
+
+ #if defined(EASTL_ATOMIC_HAS_16BIT)
+ {
+ AtomicUserTypeBasicTest<AtomicUserType16> userTypeAtomicTest;
+
+ nErrorCount += userTypeAtomicTest.RunTest();
+ }
+ #endif
+
+ #if defined(EASTL_ATOMIC_HAS_32BIT)
+ {
+ AtomicUserTypeBasicTest<AtomicNonTriviallyConstructible> userTypeAtomicTest;
+
+ nErrorCount += userTypeAtomicTest.RunTest();
+ }
+
+ {
+ AtomicUserTypeBasicTest<AtomicNonTriviallyConstructibleNoExcept> userTypeAtomicTest;
+
+ nErrorCount += userTypeAtomicTest.RunTest();
+ }
+ #endif
+
+ #if defined(EASTL_ATOMIC_HAS_128BIT)
+ {
+ AtomicUserTypeBasicTest<AtomicUserType128> userTypeAtomicTest;
+
+ nErrorCount += userTypeAtomicTest.RunTest();
+ }
+ #endif
+
+ {
+ AtomicPointerBasicTest ptrAtomicTest;
+
+ nErrorCount += ptrAtomicTest.RunTest();
+ }
+
+ {
+ AtomicVoidPointerBasicTest voidPtrAtomicTest;
+
+ nErrorCount += voidPtrAtomicTest.RunTest();
+ }
+
+ {
+ AtomicFlagBasicTest atomicFlagBasicTest;
+
+ nErrorCount += atomicFlagBasicTest.RunTest();
+ }
+
+ {
+ AtomicStandaloneBasicTest atomicStandaloneBasicTest;
+
+ nErrorCount += atomicStandaloneBasicTest.RunTest();
+ }
+
+#if defined(EASTL_ATOMIC_HAS_128BIT)
+
+ nErrorCount += TestAtomic128Loads();
+
+#endif
+
+#if defined(EASTL_ATOMIC_HAS_8BIT)
+
+ nErrorCount += TestAtomicNonDefaultConstructible();
+
+#endif
+
+ nErrorCount += TestAtomicConstantInitialization();
+
+ return nErrorCount;
+}