From bc0a8a49a7f5a8a346bbf9e3241ffb1b3754654a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 2 Apr 2018 12:26:14 +0100 Subject: [PATCH] Updates to atomic classes. --- include/etl/atomic.h | 18 +- include/etl/atomic/atomic_arm.h | 2 +- .../{atomic_gcc.h => atomic_gcc_sync.h} | 293 +++++++-- include/etl/atomic/atomic_std.h | 604 ++++++++++++++++++ include/etl/atomic/atomic_windows.h | 104 --- include/etl/platform.h | 6 +- include/etl/profiles/arduino_arm.h | 2 +- include/etl/profiles/armv5.h | 2 +- include/etl/profiles/armv6.h | 2 +- include/etl/profiles/cpp03.h | 2 +- include/etl/profiles/cpp11.h | 2 +- include/etl/profiles/cpp14.h | 2 +- include/etl/profiles/gcc_generic.h | 2 +- include/etl/profiles/gcc_linux_x86.h | 2 +- include/etl/profiles/gcc_windows_x86.h | 2 +- include/etl/profiles/msvc_x86.h | 2 +- include/etl/profiles/ticc.h | 2 +- test/codeblocks/ETL.cbp | 9 +- test/test_atomic_gcc.cpp | 87 --- test/test_atomic_gcc_sync.cpp | 484 ++++++++++++++ test/test_atomic_std.cpp | 484 ++++++++++++++ test/test_spsc_queue_std_atomic.cpp | 109 ++++ test/vs2017/etl.vcxproj | 8 +- test/vs2017/etl.vcxproj.filters | 24 +- 24 files changed, 1965 insertions(+), 289 deletions(-) rename include/etl/atomic/{atomic_gcc.h => atomic_gcc_sync.h} (60%) create mode 100644 include/etl/atomic/atomic_std.h delete mode 100644 include/etl/atomic/atomic_windows.h delete mode 100644 test/test_atomic_gcc.cpp create mode 100644 test/test_atomic_gcc_sync.cpp create mode 100644 test/test_atomic_std.cpp create mode 100644 test/test_spsc_queue_std_atomic.cpp diff --git a/include/etl/atomic.h b/include/etl/atomic.h index 652f815d..6567140d 100644 --- a/include/etl/atomic.h +++ b/include/etl/atomic.h @@ -31,21 +31,17 @@ SOFTWARE. #include "platform.h" -#if ETL_ATOMIC_SUPPORTED == 1 - #include - - namespace etl - { - typedef std::atomic atomic_uint32_t; - } +#if ETL_STD_ATOMIC_SUPPORTED == 1 + #include "atomic/atomic_std.h" + #define ETL_HAS_ATOMIC 1 #elif defined(ETL_COMPILER_ARM) #include "atomic/atomic_arm.h" + #define ETL_HAS_ATOMIC 1 #elif defined(ETL_COMPILER_GCC) - #include "atomic/atomic_gcc.h" -#elif defined(ETL_COMPILER_MSVC) - #include "atomic/atomic_windows.h" + #include "atomic/atomic_gcc_sync.h" + #define ETL_HAS_ATOMIC 1 #else - #warning NO ATOMIC SUPPORT DEFINED! + #define ETL_HAS_ATOMIC 0 #endif #endif diff --git a/include/etl/atomic/atomic_arm.h b/include/etl/atomic/atomic_arm.h index 84de98bb..d8212254 100644 --- a/include/etl/atomic/atomic_arm.h +++ b/include/etl/atomic/atomic_arm.h @@ -29,6 +29,6 @@ SOFTWARE. #ifndef __ETL_ATOMIC_ARM__ #define __ETL_ATOMIC_ARM__ -#include "atomic_gcc.h" +#include "atomic_gcc_atomic.h" #endif diff --git a/include/etl/atomic/atomic_gcc.h b/include/etl/atomic/atomic_gcc_sync.h similarity index 60% rename from include/etl/atomic/atomic_gcc.h rename to include/etl/atomic/atomic_gcc_sync.h index 9bc9409c..763c0695 100644 --- a/include/etl/atomic/atomic_gcc.h +++ b/include/etl/atomic/atomic_gcc_sync.h @@ -26,23 +26,37 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ -#ifndef __ETL_ATOMIC_GCC__ -#define __ETL_ATOMIC_GCC__ +#ifndef __ETL_ATOMIC_GCC_SYNC__ +#define __ETL_ATOMIC_GCC_SYNC__ #include "../platform.h" #include "../type_traits.h" -#include "../char_traits.h" #include "../static_assert.h" #include "../nullptr.h" +#include #include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" + namespace etl { //*************************************************************************** - // Atomic type for pre C++11 GCC compilers that support the builtin 'fetch' functions. + // Atomic type for pre C++11 GCC compilers that support the builtin '__sync' functions. // Only integral and pointer types are supported. //*************************************************************************** + + typedef enum memory_order + { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst + } memory_order; + template class atomic { @@ -63,14 +77,14 @@ namespace etl // Assignment T operator =(T v) { - __sync_lock_test_and_set(&value, v); + store(v); return v; } T operator =(T v) volatile { - __sync_lock_test_and_set(&value, v); + store(v); return v; } @@ -177,12 +191,12 @@ namespace etl // Conversion operator operator T () const { - return __sync_fetch_and_add(const_cast(&value), 0); + return __sync_fetch_and_add(&value, 0); } operator T() volatile const { - return __sync_fetch_and_add(const_cast(&value), 0); + return __sync_fetch_and_add(&value, 0); } // Is lock free? @@ -197,95 +211,95 @@ namespace etl } // Store - void store(T v) + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) { __sync_lock_test_and_set(&value, v); } - void store(T v) volatile + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile { __sync_lock_test_and_set(&value, v); } // Load - T load() + T load(etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_add(&value, 0); } - T load() volatile + T load(etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_add(&value, 0); } // Fetch add - T fetch_add(T v) + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_add(&value, v); } - T fetch_add(T v) volatile + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_add(&value, v); } // Fetch subtract - T fetch_sub(T v) + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_sub(&value, v); } - T fetch_sub(T v) volatile + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_sub(&value, v); } // Fetch or - T fetch_or(T v) + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_or(&value, v); } - T fetch_or(T v) volatile + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_or(&value, v); } // Fetch and - T fetch_and(T v) + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_and(&value, v); } - T fetch_and(T v) volatile + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_and(&value, v); } // Fetch exclusive or - T fetch_xor(T v) + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_xor(&value, v); } - T fetch_xor(T v) volatile + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_xor(&value, v); } // Exchange - T exchange(T v) + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_lock_test_and_set(&value, v); } - T exchange(T v) volatile + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_lock_test_and_set(&value, v); } // Compare exchange weak - bool compare_exchange_weak(T& expected, T desired) + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) { T old = __sync_val_compare_and_swap(&value, expected, desired); @@ -300,7 +314,37 @@ namespace etl } } - bool compare_exchange_weak(T& expected, T desired) volatile + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + T old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + T old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile { T old = __sync_val_compare_and_swap(&value, expected, desired); @@ -316,7 +360,7 @@ namespace etl } // Compare exchange strong - bool compare_exchange_strong(T& expected, T desired) + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) { T old = expected; @@ -332,7 +376,39 @@ namespace etl return true; } - bool compare_exchange_strong(T& expected, T desired) volatile + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + T old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + T old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile { T old = expected; @@ -356,9 +432,6 @@ namespace etl T value; }; - //*************************************************************************** - // Specialisation for pointers. - //*************************************************************************** template class atomic { @@ -369,66 +442,66 @@ namespace etl { } - atomic(T v) + atomic(T* v) : value(v) { } // Assignment - T operator =(T* v) + T* operator =(T* v) { - __sync_lock_test_and_set(&value, v); + store(v); return v; } - T operator =(T* v) volatile + T* operator =(T* v) volatile { - __sync_lock_test_and_set(&value, v); + store(v); return v; } // Pre-increment - T operator ++() + T* operator ++() { return fetch_add(1) + 1; } - T operator ++() volatile + T* operator ++() volatile { return fetch_add(1) + 1; } // Post-increment - T operator ++(int) + T* operator ++(int) { return fetch_add(1); } - T operator ++(int) volatile + T* operator ++(int) volatile { return fetch_add(1); } // Pre-decrement - T operator --() + T* operator --() { return fetch_sub(1) + 1; } - T operator --() volatile + T* operator --() volatile { return fetch_sub(1) + 1; } // Post-decrement - T operator --(int) + T* operator --(int) { return fetch_sub(1); } - T operator --(int) volatile + T* operator --(int) volatile { return fetch_sub(1); } @@ -456,14 +529,14 @@ namespace etl } // Conversion operator - operator T () const + operator T* () const { - return __sync_fetch_and_add(const_cast(&value), 0); + return __sync_fetch_and_add(&value, 0); } - operator T() volatile const + operator T*() volatile const { - return __sync_fetch_and_add(const_cast(&value), 0); + return __sync_fetch_and_add(&value, 0); } // Is lock free? @@ -478,79 +551,129 @@ namespace etl } // Store - void store(T v) + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) { __sync_lock_test_and_set(&value, v); } - void store(T v) volatile + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile { __sync_lock_test_and_set(&value, v); } // Load - T load() + T* load(etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_add(&value, 0); } - T load() volatile + T* load(etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_add(&value, 0); } // Fetch add - T* fetch_add(std::ptrdiff_t v) + T* fetch_add(std::ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_add(&value, v); } - T* fetch_add(std::ptrdiff_t v) volatile + T* fetch_add(std::ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_add(&value, v); } // Fetch subtract - T* fetch_sub(std::ptrdiff_t v) + T* fetch_sub(std::ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_fetch_and_sub(&value, v); } - T* fetch_sub(std::ptrdiff_t v) volatile + T* fetch_sub(std::ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_fetch_and_sub(&value, v); } // Exchange - T exchange(T v) + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) { return __sync_lock_test_and_set(&value, v); } - T exchange(T v) volatile + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile { return __sync_lock_test_and_set(&value, v); } // Compare exchange weak - bool compare_exchange_weak(T& expected, T desired) + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) { - return __sync_bool_compare_and_swap(&value, expected, desired); + T* old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } } - bool compare_exchange_weak(T& expected, T desired) volatile + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile { - return __sync_bool_compare_and_swap(&value, expected, desired); + T* old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + T* old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + T* old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } } // Compare exchange strong - bool compare_exchange_strong(T& expected, T desired) + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) { - T old = expected; + T* old = expected; while (!compare_exchange_weak(old, desired)) { - if (memcmp(&old, &expected, sizeof(T))) + if (memcmp(&old, &expected, sizeof(T*))) { expected = old; return false; @@ -560,13 +683,45 @@ namespace etl return true; } - bool compare_exchange_strong(T& expected, T desired) volatile + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile { - T old = expected; + T* old = expected; while (!compare_exchange_weak(old, desired)) { - if (memcmp(&old, &expected, sizeof(T))) + if (memcmp(&old, &expected, sizeof(T*))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + T* old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T*))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + T* old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T*))) { expected = old; return false; @@ -630,4 +785,6 @@ namespace etl typedef etl::atomic atomic_uintmax_t; } +#pragma GCC diagnostic pop + #endif diff --git a/include/etl/atomic/atomic_std.h b/include/etl/atomic/atomic_std.h new file mode 100644 index 00000000..3970a290 --- /dev/null +++ b/include/etl/atomic/atomic_std.h @@ -0,0 +1,604 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2018 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ETL_ATOMIC_STD__ +#define __ETL_ATOMIC_STD__ + +#include "../platform.h" +#include "../nullptr.h" + +#include +#include + +namespace etl +{ + //*************************************************************************** + // ETL Atomic type for compilers that support std::atomic. + // etl::atomic is a simple wrapper around std::atomic. + //*************************************************************************** + + typedef std::memory_order memory_order; + + static const etl::memory_order memory_order_relaxed = std::memory_order_relaxed; + static const etl::memory_order memory_order_consume = std::memory_order_consume; + static const etl::memory_order memory_order_acquire = std::memory_order_acquire; + static const etl::memory_order memory_order_release = std::memory_order_release; + static const etl::memory_order memory_order_acq_rel = std::memory_order_acq_rel; + static const etl::memory_order memory_order_seq_cst = std::memory_order_seq_cst; + + template + class atomic + { + public: + + atomic() + : value(0) + { + } + + atomic(T v) + : value(v) + { + } + + // Assignment + T operator =(T v) + { + return value = v; + } + + T operator =(T v) volatile + { + return value = v; + } + + // Pre-increment + T operator ++() + { + return ++value; + } + + T operator ++() volatile + { + return ++value; + } + + // Post-increment + T operator ++(int) + { + return value++; + } + + T operator ++(int) volatile + { + return value++; + } + + // Pre-decrement + T operator --() + { + return --value; + } + + T operator --() volatile + { + return --value; + } + + // Post-decrement + T operator --(int) + { + return value--; + } + + T operator --(int) volatile + { + return value--; + } + + // Add + T operator +=(T v) + { + return value += v; + } + + T operator +=(T v) volatile + { + return value += v; + } + + // Subtract + T operator -=(T v) + { + return value -= v; + } + + T operator -=(T v) volatile + { + return value -= v; + } + + // And + T operator &=(T v) + { + return value &= v; + } + + T operator &=(T v) volatile + { + return value &= v; + } + + // Or + T operator |=(T v) + { + return value |= v; + } + + T operator |=(T v) volatile + { + return value |= v; + } + + // Exclusive or + T operator ^=(T v) + { + return value ^= v; + } + + T operator ^=(T v) volatile + { + return value ^= v; + } + + // Conversion operator + operator T () const + { + return T(value); + } + + operator T() volatile const + { + return T(value); + } + + // Is lock free? + bool is_lock_free() const + { + return value.is_lock_free(); + } + + bool is_lock_free() const volatile + { + return value.is_lock_free(); + } + + // Store + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + value.store(v, order); + } + + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + value.store(v, order); + } + + // Load + T load(etl::memory_order order = etl::memory_order_seq_cst) + { + return value.load(order); + } + + T load(etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.load(order); + } + + // Fetch add + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_add(v, order); + } + + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_add(v, order); + } + + // Fetch subtract + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_sub(v, order); + } + + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_sub(v, order); + } + + // Fetch or + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_or(v, order); + } + + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_or(v, order); + } + + // Fetch and + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_and(v, order); + } + + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_and(v, order); + } + + // Fetch exclusive or + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_xor(v, order); + } + + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_xor(v, order); + } + + // Exchange + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.exchange(v, order); + } + + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.exchange(v, order); + } + + // Compare exchange weak + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.compare_exchange_weak(expected, desired, order); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.compare_exchange_weak(expected, desired, order); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + return value.compare_exchange_weak(expected, desired, success, failure); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + return value.compare_exchange_weak(expected, desired, success, failure); + } + + // Compare exchange strong + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.compare_exchange_strong(expected, desired, order); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.compare_exchange_strong(expected, desired, order); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + return value.compare_exchange_strong(expected, desired, success, failure); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + return value.compare_exchange_strong(expected, desired, success, failure); + } + + private: + + atomic& operator =(const atomic&); + //atomic& operator =(const atomic&) volatile; + + std::atomic value; + }; + + template + class atomic + { + public: + + atomic() + : value(nullptr) + { + } + + atomic(T* v) + : value(v) + { + } + + // Assignment + T* operator =(T* v) + { + return value = v; + } + + T* operator =(T* v) volatile + { + return value = v; + } + + // Pre-increment + T* operator ++() + { + return ++value; + } + + T* operator ++() volatile + { + return ++value; + } + + // Post-increment + T* operator ++(int) + { + return value++; + } + + T* operator ++(int) volatile + { + return value++; + } + + // Pre-decrement + T* operator --() + { + return --value; + } + + T* operator --() volatile + { + return --value; + } + + // Post-decrement + T* operator --(int) + { + return value--; + } + + T* operator --(int) volatile + { + return value--; + } + + // Add + T* operator +=(std::ptrdiff_t v) + { + return value += v; + } + + T* operator +=(std::ptrdiff_t v) volatile + { + return value += v; + } + + // Subtract + T* operator -=(std::ptrdiff_t v) + { + return value -= v; + } + + T* operator -=(std::ptrdiff_t v) volatile + { + return value -= v; + } + + // Conversion operator + operator T* () const + { + return (T*)value; + } + + operator T*() volatile const + { + return (T*)value; + } + + // Is lock free? + bool is_lock_free() const + { + return value.is_lock_free(); + } + + bool is_lock_free() const volatile + { + return value.is_lock_free(); + } + + // Store + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) + { + value.store(v, order); + } + + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + value.store(v, order); + } + + // Load + T* load(etl::memory_order order = etl::memory_order_seq_cst) + { + return value.load(order); + } + + T* load(etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.load(order); + } + + // Fetch add + T* fetch_add(std::ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_add(v, order); + } + + T* fetch_add(std::ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_add(v, order); + } + + // Fetch subtract + T* fetch_sub(std::ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_sub(v, order); + } + + T* fetch_sub(std::ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_sub(v, order); + } + + // Exchange + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.exchange(v, order); + } + + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.exchange(v, order); + } + + // Compare exchange weak + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.compare_exchange_weak(expected, desired, order); + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.compare_exchange_weak(expected, desired, order); + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + return value.compare_exchange_weak(expected, desired, success, failure); + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + return value.compare_exchange_weak(expected, desired, success, failure); + } + + // Compare exchange strong + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.compare_exchange_strong(expected, desired, order); + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.compare_exchange_strong(expected, desired, order); + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + return value.compare_exchange_strong(expected, desired, success, failure); + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + return value.compare_exchange_strong(expected, desired, success, failure); + } + + private: + + atomic & operator =(const atomic&); + //atomic& operator =(const atomic&) volatile; + + std::atomic value; + }; + + typedef std::atomic atomic_char; + typedef std::atomic atomic_schar; + typedef std::atomic atomic_uchar; + typedef std::atomic atomic_short; + typedef std::atomic atomic_ushort; + typedef std::atomic atomic_int; + typedef std::atomic atomic_uint; + typedef std::atomic atomic_long; + typedef std::atomic atomic_ulong; + typedef std::atomic atomic_llong; + typedef std::atomic atomic_ullong; + typedef std::atomic atomic_wchar_t; + typedef std::atomic atomic_char16_t; + typedef std::atomic atomic_char32_t; + typedef std::atomic atomic_uint8_t; + typedef std::atomic atomic_int8_t; + typedef std::atomic atomic_uint16_t; + typedef std::atomic atomic_int16_t; + typedef std::atomic atomic_uint32_t; + typedef std::atomic atomic_int32_t; + typedef std::atomic atomic_uint64_t; + typedef std::atomic atomic_int64_t; + typedef std::atomic atomic_int_least8_t; + typedef std::atomic atomic_uint_least8_t; + typedef std::atomic atomic_int_least16_t; + typedef std::atomic atomic_uint_least16_t; + typedef std::atomic atomic_int_least32_t; + typedef std::atomic atomic_uint_least32_t; + typedef std::atomic atomic_int_least64_t; + typedef std::atomic atomic_uint_least64_t; + typedef std::atomic atomic_int_fast8_t; + typedef std::atomic atomic_uint_fast8_t; + typedef std::atomic atomic_int_fast16_t; + typedef std::atomic atomic_uint_fast16_t; + typedef std::atomic atomic_int_fast32_t; + typedef std::atomic atomic_uint_fast32_t; + typedef std::atomic atomic_int_fast64_t; + typedef std::atomic atomic_uint_fast64_t; + typedef std::atomic atomic_intptr_t; + typedef std::atomic atomic_uintptr_t; + typedef std::atomic atomic_size_t; + typedef std::atomic atomic_ptrdiff_t; + typedef std::atomic atomic_intmax_t; + typedef std::atomic atomic_uintmax_t; +}; + +#endif diff --git a/include/etl/atomic/atomic_windows.h b/include/etl/atomic/atomic_windows.h deleted file mode 100644 index 9b7a2ed3..00000000 --- a/include/etl/atomic/atomic_windows.h +++ /dev/null @@ -1,104 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2017 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_ATOMIC_WINDOWS__ -#define __ETL_ATOMIC_WINDOWS__ - -#include "../platform.h" - -#include -#include - -namespace etl -{ - class atomic_uint32_t - { - public: - - atomic_uint32_t() - { - InterlockedExchange(&value, 0); - } - - atomic_uint32_t(uint32_t v) - { - InterlockedExchange(&value, v); - } - - atomic_uint32_t& operator =(uint32_t v) - { - InterlockedExchange(&value, v); - - return *this; - } - - atomic_uint32_t& operator ++() - { - InterlockedIncrement(&value); - - return *this; - } - - volatile atomic_uint32_t& operator ++() volatile - { - InterlockedIncrement(&value); - - return *this; - } - - atomic_uint32_t& operator --() - { - InterlockedDecrement(&value); - - return *this; - } - - volatile atomic_uint32_t& operator --() volatile - { - InterlockedDecrement(&value); - - return *this; - } - - operator uint32_t () const - { - return InterlockedAdd((volatile long*)&value, 0); - } - - operator uint32_t() volatile const - { - return InterlockedAdd((volatile long*)&value, 0); - } - - private: - - uint32_t value; - }; -} - -#endif diff --git a/include/etl/platform.h b/include/etl/platform.h index f1a4c4de..6ae858e3 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -44,7 +44,7 @@ SOFTWARE. #undef ETL_NO_NULLPTR_SUPPORT #undef ETL_NO_LARGE_CHAR_SUPPORT #undef ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED -#undef ETL_ATOMIC_SUPPORTED +#undef ETL_STD_ATOMIC_SUPPORTED #include "etl_profile.h" @@ -53,6 +53,10 @@ SOFTWARE. #pragma warning(disable : 4996) #endif +#if defined(ETL_COMPILER_GCC) + #define GCC_VERSION ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__) +#endif + #if ETL_CPP11_SUPPORTED #define ETL_CONSTEXPR constexpr #else diff --git a/include/etl/profiles/arduino_arm.h b/include/etl/profiles/arduino_arm.h index 2ffe5977..5ea771aa 100644 --- a/include/etl/profiles/arduino_arm.h +++ b/include/etl/profiles/arduino_arm.h @@ -46,6 +46,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT 1 #define ETL_NO_LARGE_CHAR_SUPPORT 1 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 -#define ETL_ATOMIC_SUPPORTED 0 +#define ETL_STD_ATOMIC_SUPPORTED 0 #endif diff --git a/include/etl/profiles/armv5.h b/include/etl/profiles/armv5.h index 5d108fb6..d9a980ae 100644 --- a/include/etl/profiles/armv5.h +++ b/include/etl/profiles/armv5.h @@ -46,6 +46,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT 1 #define ETL_NO_LARGE_CHAR_SUPPORT 1 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 -#define ETL_ATOMIC_SUPPORTED 0 +#define ETL_STD_ATOMIC_SUPPORTED 0 #endif diff --git a/include/etl/profiles/armv6.h b/include/etl/profiles/armv6.h index 08b99db2..cc1df992 100644 --- a/include/etl/profiles/armv6.h +++ b/include/etl/profiles/armv6.h @@ -46,6 +46,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT 0 #define ETL_NO_LARGE_CHAR_SUPPORT 0 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 -#define ETL_ATOMIC_SUPPORTED 1 +#define ETL_STD_ATOMIC_SUPPORTED 1 #endif diff --git a/include/etl/profiles/cpp03.h b/include/etl/profiles/cpp03.h index 4b50addb..941eb93c 100644 --- a/include/etl/profiles/cpp03.h +++ b/include/etl/profiles/cpp03.h @@ -46,6 +46,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT 1 #define ETL_NO_LARGE_CHAR_SUPPORT 1 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 -#define ETL_ATOMIC_SUPPORTED 0 +#define ETL_STD_ATOMIC_SUPPORTED 0 #endif diff --git a/include/etl/profiles/cpp11.h b/include/etl/profiles/cpp11.h index 6af61ee5..4ba32310 100644 --- a/include/etl/profiles/cpp11.h +++ b/include/etl/profiles/cpp11.h @@ -46,6 +46,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT 0 #define ETL_NO_LARGE_CHAR_SUPPORT 0 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 -#define ETL_ATOMIC_SUPPORTED 1 +#define ETL_STD_ATOMIC_SUPPORTED 1 #endif diff --git a/include/etl/profiles/cpp14.h b/include/etl/profiles/cpp14.h index 4a26d7cb..83f38bef 100644 --- a/include/etl/profiles/cpp14.h +++ b/include/etl/profiles/cpp14.h @@ -46,6 +46,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT 0 #define ETL_NO_LARGE_CHAR_SUPPORT 0 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 -#define ETL_ATOMIC_SUPPORTED 1 +#define ETL_STD_ATOMIC_SUPPORTED 1 #endif diff --git a/include/etl/profiles/gcc_generic.h b/include/etl/profiles/gcc_generic.h index 3e4c4d0a..43abc0f4 100644 --- a/include/etl/profiles/gcc_generic.h +++ b/include/etl/profiles/gcc_generic.h @@ -52,6 +52,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED ETL_CPP14_SUPPORTED -#define ETL_ATOMIC_SUPPORTED ETL_CPP11_SUPPORTED +#define ETL_STD_ATOMIC_SUPPORTED ETL_CPP11_SUPPORTED #endif diff --git a/include/etl/profiles/gcc_linux_x86.h b/include/etl/profiles/gcc_linux_x86.h index 8280d59d..ea63377a 100644 --- a/include/etl/profiles/gcc_linux_x86.h +++ b/include/etl/profiles/gcc_linux_x86.h @@ -52,6 +52,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED ETL_CPP14_SUPPORTED -#define ETL_ATOMIC_SUPPORTED ETL_CPP11_SUPPORTED +#define ETL_STD_ATOMIC_SUPPORTED ETL_CPP11_SUPPORTED #endif diff --git a/include/etl/profiles/gcc_windows_x86.h b/include/etl/profiles/gcc_windows_x86.h index 610cc60f..4b083a89 100644 --- a/include/etl/profiles/gcc_windows_x86.h +++ b/include/etl/profiles/gcc_windows_x86.h @@ -52,6 +52,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED ETL_CPP14_SUPPORTED -#define ETL_ATOMIC_SUPPORTED ETL_CPP11_SUPPORTED +#define ETL_STD_ATOMIC_SUPPORTED ETL_CPP11_SUPPORTED #endif diff --git a/include/etl/profiles/msvc_x86.h b/include/etl/profiles/msvc_x86.h index 5382b62d..815b7a92 100644 --- a/include/etl/profiles/msvc_x86.h +++ b/include/etl/profiles/msvc_x86.h @@ -46,6 +46,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED ETL_CPP14_SUPPORTED -#define ETL_ATOMIC_SUPPORTED ETL_CPP11_SUPPORTED +#define ETL_STD_ATOMIC_SUPPORTED ETL_CPP11_SUPPORTED #endif diff --git a/include/etl/profiles/ticc.h b/include/etl/profiles/ticc.h index b1478c64..61c45f29 100644 --- a/include/etl/profiles/ticc.h +++ b/include/etl/profiles/ticc.h @@ -46,6 +46,6 @@ SOFTWARE. #define ETL_NO_NULLPTR_SUPPORT 1 #define ETL_NO_LARGE_CHAR_SUPPORT 1 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 -#define ETL_ATOMIC_SUPPORTED 0 +#define ETL_STD_ATOMIC_SUPPORTED 0 #endif diff --git a/test/codeblocks/ETL.cbp b/test/codeblocks/ETL.cbp index a399f5d1..b2c1bb70 100644 --- a/test/codeblocks/ETL.cbp +++ b/test/codeblocks/ETL.cbp @@ -62,8 +62,8 @@ - - + + @@ -296,6 +296,11 @@ + + + diff --git a/test/test_atomic_gcc.cpp b/test/test_atomic_gcc.cpp deleted file mode 100644 index bd6c881c..00000000 --- a/test/test_atomic_gcc.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2017 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#include "UnitTest++.h" - -#include "platform.h" - -#include "atomic/atomic_gcc.h" - -#include - -namespace -{ - SUITE(test_atomic_gcc) - { - //========================================================================= - TEST(test_atomic_compare_exchange_weak_fail) - { - std::atomic compare; - etl::atomic test; - - int actual = 1U; - - compare = actual; - test = actual; - - int compare_expected = 2U; - int test_expected = 2U; - int desired = 3U; - - bool compare_result = compare.compare_exchange_weak(compare_expected, desired); - bool test_result = test.compare_exchange_weak(test_expected, desired); - - CHECK_EQUAL(compare_result, test_result); - CHECK_EQUAL(compare_expected, test_expected); - CHECK_EQUAL(compare.load(), test.load()); - } - - //========================================================================= - TEST(test_atomic_compare_exchange_weak_pass) - { - std::atomic compare; - etl::atomic test; - - int actual = 1U; - - compare = actual; - test = actual; - - int compare_expected = actual; - int test_expected = actual; - int desired = 3U; - - bool compare_result = compare.compare_exchange_weak(compare_expected, desired); - bool test_result = test.compare_exchange_weak(test_expected, desired); - - CHECK_EQUAL(compare_result, test_result); - CHECK_EQUAL(compare_expected, test_expected); - CHECK_EQUAL(compare.load(), test.load()); - } - }; -} diff --git a/test/test_atomic_gcc_sync.cpp b/test/test_atomic_gcc_sync.cpp new file mode 100644 index 00000000..9af9c77e --- /dev/null +++ b/test/test_atomic_gcc_sync.cpp @@ -0,0 +1,484 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "UnitTest++.h" + +#include "platform.h" +#include "atomic/atomic_std.h" + +#include + +namespace +{ + SUITE(test_atomic_std) + { + //========================================================================= + TEST(test_atomic_integer_is_lock_free) + { + std::atomic compare; + etl::atomic test; + + CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free()); + } + + //========================================================================= + TEST(test_atomic_pointer_is_lock_free) + { + std::atomic compare; + etl::atomic test; + + CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free()); + } + + //========================================================================= + TEST(test_atomic_integer_load) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare.load(), (int)test.load()); + } + + //========================================================================= + TEST(test_atomic_pointer_load) + { + int i; + + std::atomic compare(&i); + etl::atomic test(&i); + + CHECK_EQUAL((int*)compare.load(), (int*)test.load()); + } + + //========================================================================= + TEST(test_atomic_integer_store) + { + std::atomic compare(1); + etl::atomic test(1); + + compare.store(2); + test.store(2); + CHECK_EQUAL((int)compare.load(), (int)test.load()); + } + + //========================================================================= + TEST(test_atomic_pointer_store) + { + int i; + int j; + + std::atomic compare(&i); + etl::atomic test(&i); + + compare.store(&j); + test.store(&j); + CHECK_EQUAL((int*)compare.load(), (int*)test.load()); + } + + //========================================================================= + TEST(test_atomic_integer_assignment) + { + std::atomic compare(1); + etl::atomic test(1); + + compare = 2; + test = 2; + CHECK_EQUAL((int)compare.load(), (int)test.load()); + } + + //========================================================================= + TEST(test_atomic_pointer_assignment) + { + int i; + int j; + + std::atomic compare(&i); + etl::atomic test(&i); + + compare = &j; + test = &j; + CHECK_EQUAL((int*)compare.load(), (int*)test.load()); + } + + //========================================================================= + TEST(test_atomic_operator_integer_pre_increment) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)++compare, (int)++test); + CHECK_EQUAL((int)++compare, (int)++test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_post_increment) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare++, (int)test++); + CHECK_EQUAL((int)compare++, (int)test++); + } + + //========================================================================= + TEST(test_atomic_operator_integer_pre_decrement) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)--compare, (int)--test); + CHECK_EQUAL((int)--compare, (int)--test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_post_decrement) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare--, (int)test--); + CHECK_EQUAL((int)compare--, (int)test--); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_pre_increment) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + CHECK_EQUAL((int*)++compare, (int*)++test); + CHECK_EQUAL((int*)++compare, (int*)++test); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_post_increment) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + CHECK_EQUAL((int*)compare++, (int*)test++); + CHECK_EQUAL((int*)compare++, (int*)test++); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_pre_decrement) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[3]); + etl::atomic test(&data[3]); + + CHECK_EQUAL((int*)--compare, (int*)--test); + CHECK_EQUAL((int*)--compare, (int*)--test); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_post_decrement) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[3]); + etl::atomic test(&data[3]); + + CHECK_EQUAL((int*)compare--, (int*)test--); + CHECK_EQUAL((int*)compare--, (int*)test--); + } + + //========================================================================= + TEST(test_atomic_operator_integer_fetch_add) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare.fetch_add(2), (int)test.fetch_add(2)); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_fetch_add) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + CHECK_EQUAL((int*)compare.fetch_add(std::ptrdiff_t(10)), (int*)test.fetch_add(std::ptrdiff_t(10))); + } + + //========================================================================= + TEST(test_atomic_operator_integer_plus_equals) + { + std::atomic compare(1); + etl::atomic test(1); + + compare += 2; + test += 2; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_plus_equals) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + compare += 2; + test += 2; + + CHECK_EQUAL((int*)compare, (int*)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_minus_equals) + { + std::atomic compare(1); + etl::atomic test(1); + + compare += 2; + test += 2; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_minus_equals) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[3]); + etl::atomic test(&data[3]); + + compare += 2; + test += 2; + + CHECK_EQUAL((int*)compare, (int*)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_and_equals) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + compare &= 0x55AA55AA; + test &= 0x55AA55AA; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_or_equals) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + compare |= 0x55AA55AA; + test |= 0x55AA55AA; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_xor_equals) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + compare ^= 0x55AA55AA; + test ^= 0x55AA55AA; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_fetch_sub) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare.fetch_sub(2), (int)test.fetch_sub(2)); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_fetch_sub) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + CHECK_EQUAL((int*)compare.fetch_add(std::ptrdiff_t(10)), (int*)test.fetch_add(std::ptrdiff_t(10))); + } + + //========================================================================= + TEST(test_atomic_operator_fetch_and) + { + std::atomic compare(0xFFFFFFFF); + etl::atomic test(0xFFFFFFFF); + + CHECK_EQUAL((int)compare.fetch_and(0x55AA55AA), (int)test.fetch_and(0x55AA55AA)); + } + + //========================================================================= + TEST(test_atomic_operator_fetch_or) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + CHECK_EQUAL((int)compare.fetch_or(0x55AA55AA), (int)test.fetch_or(0x55AA55AA)); + } + + //========================================================================= + TEST(test_atomic_operator_fetch_xor) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + CHECK_EQUAL((int)compare.fetch_xor(0x55AA55AA), (int)test.fetch_xor(0x55AA55AA)); + } + + //========================================================================= + TEST(test_atomic_integer_exchange) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare.exchange(2), (int)test.exchange(2)); + } + + //========================================================================= + TEST(test_atomic_pointer_exchange) + { + int i; + int j; + + std::atomic compare(&i); + etl::atomic test(&i); + + CHECK_EQUAL((int*)compare.exchange(&j), (int*)test.exchange(&j)); + } + + //========================================================================= + TEST(test_atomic_compare_exchange_weak_fail) + { + std::atomic compare; + etl::atomic test; + + int actual = 1U; + + compare = actual; + test = actual; + + int compare_expected = 2U; + int test_expected = 2U; + int desired = 3U; + + bool compare_result = compare.compare_exchange_weak(compare_expected, desired); + bool test_result = test.compare_exchange_weak(test_expected, desired); + + CHECK_EQUAL(compare_result, test_result); + CHECK_EQUAL(compare_expected, test_expected); + CHECK_EQUAL(compare.load(), test.load()); + } + + //========================================================================= + TEST(test_atomic_compare_exchange_weak_pass) + { + std::atomic compare; + etl::atomic test; + + int actual = 1U; + + compare = actual; + test = actual; + + int compare_expected = actual; + int test_expected = actual; + int desired = 3U; + + bool compare_result = compare.compare_exchange_weak(compare_expected, desired); + bool test_result = test.compare_exchange_weak(test_expected, desired); + + CHECK_EQUAL(compare_result, test_result); + CHECK_EQUAL(compare_expected, test_expected); + CHECK_EQUAL(compare.load(), test.load()); + } + + //========================================================================= + TEST(test_atomic_compare_exchange_strong_fail) + { + std::atomic compare; + etl::atomic test; + + int actual = 1U; + + compare = actual; + test = actual; + + int compare_expected = 2U; + int test_expected = 2U; + int desired = 3U; + + bool compare_result = compare.compare_exchange_strong(compare_expected, desired); + bool test_result = test.compare_exchange_strong(test_expected, desired); + + CHECK_EQUAL(compare_result, test_result); + CHECK_EQUAL(compare_expected, test_expected); + CHECK_EQUAL(compare.load(), test.load()); + } + + //========================================================================= + TEST(test_atomic_compare_exchange_strong_pass) + { + std::atomic compare; + etl::atomic test; + + int actual = 1U; + + compare = actual; + test = actual; + + int compare_expected = actual; + int test_expected = actual; + int desired = 3U; + + bool compare_result = compare.compare_exchange_strong(compare_expected, desired); + bool test_result = test.compare_exchange_strong(test_expected, desired); + + CHECK_EQUAL(compare_result, test_result); + CHECK_EQUAL(compare_expected, test_expected); + CHECK_EQUAL(compare.load(), test.load()); + } + }; +} diff --git a/test/test_atomic_std.cpp b/test/test_atomic_std.cpp new file mode 100644 index 00000000..9af9c77e --- /dev/null +++ b/test/test_atomic_std.cpp @@ -0,0 +1,484 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "UnitTest++.h" + +#include "platform.h" +#include "atomic/atomic_std.h" + +#include + +namespace +{ + SUITE(test_atomic_std) + { + //========================================================================= + TEST(test_atomic_integer_is_lock_free) + { + std::atomic compare; + etl::atomic test; + + CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free()); + } + + //========================================================================= + TEST(test_atomic_pointer_is_lock_free) + { + std::atomic compare; + etl::atomic test; + + CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free()); + } + + //========================================================================= + TEST(test_atomic_integer_load) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare.load(), (int)test.load()); + } + + //========================================================================= + TEST(test_atomic_pointer_load) + { + int i; + + std::atomic compare(&i); + etl::atomic test(&i); + + CHECK_EQUAL((int*)compare.load(), (int*)test.load()); + } + + //========================================================================= + TEST(test_atomic_integer_store) + { + std::atomic compare(1); + etl::atomic test(1); + + compare.store(2); + test.store(2); + CHECK_EQUAL((int)compare.load(), (int)test.load()); + } + + //========================================================================= + TEST(test_atomic_pointer_store) + { + int i; + int j; + + std::atomic compare(&i); + etl::atomic test(&i); + + compare.store(&j); + test.store(&j); + CHECK_EQUAL((int*)compare.load(), (int*)test.load()); + } + + //========================================================================= + TEST(test_atomic_integer_assignment) + { + std::atomic compare(1); + etl::atomic test(1); + + compare = 2; + test = 2; + CHECK_EQUAL((int)compare.load(), (int)test.load()); + } + + //========================================================================= + TEST(test_atomic_pointer_assignment) + { + int i; + int j; + + std::atomic compare(&i); + etl::atomic test(&i); + + compare = &j; + test = &j; + CHECK_EQUAL((int*)compare.load(), (int*)test.load()); + } + + //========================================================================= + TEST(test_atomic_operator_integer_pre_increment) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)++compare, (int)++test); + CHECK_EQUAL((int)++compare, (int)++test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_post_increment) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare++, (int)test++); + CHECK_EQUAL((int)compare++, (int)test++); + } + + //========================================================================= + TEST(test_atomic_operator_integer_pre_decrement) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)--compare, (int)--test); + CHECK_EQUAL((int)--compare, (int)--test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_post_decrement) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare--, (int)test--); + CHECK_EQUAL((int)compare--, (int)test--); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_pre_increment) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + CHECK_EQUAL((int*)++compare, (int*)++test); + CHECK_EQUAL((int*)++compare, (int*)++test); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_post_increment) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + CHECK_EQUAL((int*)compare++, (int*)test++); + CHECK_EQUAL((int*)compare++, (int*)test++); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_pre_decrement) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[3]); + etl::atomic test(&data[3]); + + CHECK_EQUAL((int*)--compare, (int*)--test); + CHECK_EQUAL((int*)--compare, (int*)--test); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_post_decrement) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[3]); + etl::atomic test(&data[3]); + + CHECK_EQUAL((int*)compare--, (int*)test--); + CHECK_EQUAL((int*)compare--, (int*)test--); + } + + //========================================================================= + TEST(test_atomic_operator_integer_fetch_add) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare.fetch_add(2), (int)test.fetch_add(2)); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_fetch_add) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + CHECK_EQUAL((int*)compare.fetch_add(std::ptrdiff_t(10)), (int*)test.fetch_add(std::ptrdiff_t(10))); + } + + //========================================================================= + TEST(test_atomic_operator_integer_plus_equals) + { + std::atomic compare(1); + etl::atomic test(1); + + compare += 2; + test += 2; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_plus_equals) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + compare += 2; + test += 2; + + CHECK_EQUAL((int*)compare, (int*)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_minus_equals) + { + std::atomic compare(1); + etl::atomic test(1); + + compare += 2; + test += 2; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_minus_equals) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[3]); + etl::atomic test(&data[3]); + + compare += 2; + test += 2; + + CHECK_EQUAL((int*)compare, (int*)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_and_equals) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + compare &= 0x55AA55AA; + test &= 0x55AA55AA; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_or_equals) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + compare |= 0x55AA55AA; + test |= 0x55AA55AA; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_xor_equals) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + compare ^= 0x55AA55AA; + test ^= 0x55AA55AA; + + CHECK_EQUAL((int)compare, (int)test); + } + + //========================================================================= + TEST(test_atomic_operator_integer_fetch_sub) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare.fetch_sub(2), (int)test.fetch_sub(2)); + } + + //========================================================================= + TEST(test_atomic_operator_pointer_fetch_sub) + { + int data[] = { 1, 2, 3, 4 }; + + std::atomic compare(&data[0]); + etl::atomic test(&data[0]); + + CHECK_EQUAL((int*)compare.fetch_add(std::ptrdiff_t(10)), (int*)test.fetch_add(std::ptrdiff_t(10))); + } + + //========================================================================= + TEST(test_atomic_operator_fetch_and) + { + std::atomic compare(0xFFFFFFFF); + etl::atomic test(0xFFFFFFFF); + + CHECK_EQUAL((int)compare.fetch_and(0x55AA55AA), (int)test.fetch_and(0x55AA55AA)); + } + + //========================================================================= + TEST(test_atomic_operator_fetch_or) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + CHECK_EQUAL((int)compare.fetch_or(0x55AA55AA), (int)test.fetch_or(0x55AA55AA)); + } + + //========================================================================= + TEST(test_atomic_operator_fetch_xor) + { + std::atomic compare(0x0000FFFF); + etl::atomic test(0x0000FFFF); + + CHECK_EQUAL((int)compare.fetch_xor(0x55AA55AA), (int)test.fetch_xor(0x55AA55AA)); + } + + //========================================================================= + TEST(test_atomic_integer_exchange) + { + std::atomic compare(1); + etl::atomic test(1); + + CHECK_EQUAL((int)compare.exchange(2), (int)test.exchange(2)); + } + + //========================================================================= + TEST(test_atomic_pointer_exchange) + { + int i; + int j; + + std::atomic compare(&i); + etl::atomic test(&i); + + CHECK_EQUAL((int*)compare.exchange(&j), (int*)test.exchange(&j)); + } + + //========================================================================= + TEST(test_atomic_compare_exchange_weak_fail) + { + std::atomic compare; + etl::atomic test; + + int actual = 1U; + + compare = actual; + test = actual; + + int compare_expected = 2U; + int test_expected = 2U; + int desired = 3U; + + bool compare_result = compare.compare_exchange_weak(compare_expected, desired); + bool test_result = test.compare_exchange_weak(test_expected, desired); + + CHECK_EQUAL(compare_result, test_result); + CHECK_EQUAL(compare_expected, test_expected); + CHECK_EQUAL(compare.load(), test.load()); + } + + //========================================================================= + TEST(test_atomic_compare_exchange_weak_pass) + { + std::atomic compare; + etl::atomic test; + + int actual = 1U; + + compare = actual; + test = actual; + + int compare_expected = actual; + int test_expected = actual; + int desired = 3U; + + bool compare_result = compare.compare_exchange_weak(compare_expected, desired); + bool test_result = test.compare_exchange_weak(test_expected, desired); + + CHECK_EQUAL(compare_result, test_result); + CHECK_EQUAL(compare_expected, test_expected); + CHECK_EQUAL(compare.load(), test.load()); + } + + //========================================================================= + TEST(test_atomic_compare_exchange_strong_fail) + { + std::atomic compare; + etl::atomic test; + + int actual = 1U; + + compare = actual; + test = actual; + + int compare_expected = 2U; + int test_expected = 2U; + int desired = 3U; + + bool compare_result = compare.compare_exchange_strong(compare_expected, desired); + bool test_result = test.compare_exchange_strong(test_expected, desired); + + CHECK_EQUAL(compare_result, test_result); + CHECK_EQUAL(compare_expected, test_expected); + CHECK_EQUAL(compare.load(), test.load()); + } + + //========================================================================= + TEST(test_atomic_compare_exchange_strong_pass) + { + std::atomic compare; + etl::atomic test; + + int actual = 1U; + + compare = actual; + test = actual; + + int compare_expected = actual; + int test_expected = actual; + int desired = 3U; + + bool compare_result = compare.compare_exchange_strong(compare_expected, desired); + bool test_result = test.compare_exchange_strong(test_expected, desired); + + CHECK_EQUAL(compare_result, test_result); + CHECK_EQUAL(compare_expected, test_expected); + CHECK_EQUAL(compare.load(), test.load()); + } + }; +} diff --git a/test/test_spsc_queue_std_atomic.cpp b/test/test_spsc_queue_std_atomic.cpp new file mode 100644 index 00000000..5ce3ad33 --- /dev/null +++ b/test/test_spsc_queue_std_atomic.cpp @@ -0,0 +1,109 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2018 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "UnitTest++.h" + +#include "spsc_queue.h" + +namespace +{ + struct Item + { + Item(char c_, int i_, double d_) + : c(c_), + i(i_), + d(d_) + { + } + + char c; + int i; + double d; + }; + + bool operator == (const Item& lhs, const Item& rhs) + { + return (lhs.c == rhs.c) && (lhs.i == rhs.i) && (lhs.d == rhs.d); + } + + typedef etl::spsc_queue Queue; + typedef etl::ispsc_queue IQueue; + + SUITE(test_queue) + { + Item item1(1, 2, 3.4); + Item item2(2, 3, 4.5); + Item item3(3, 4, 5.6); + Item item4(4, 5, 6.7); + + TEST(test_normal_operation) + { + Queue queue; + + IQueue& iqueue = queue; + + CHECK(queue.empty()); + CHECK(!queue.full()); + + CHECK_EQUAL(4U, queue.capacity()); + CHECK_EQUAL(4U, queue.max_size()); + + // Fill the queue. + CHECK(queue.push(item1)); + CHECK_EQUAL(1U, queue.size()); + CHECK_EQUAL(3U, queue.available()); + CHECK(!queue.empty()); + CHECK(!queue.full()); + + CHECK(iqueue.push(item2)); + CHECK_EQUAL(2U, iqueue.size()); + CHECK_EQUAL(2U, iqueue.available()); + CHECK(!iqueue.empty()); + CHECK(!iqueue.full()); + + CHECK(queue.push(item3)); + CHECK_EQUAL(3U, queue.size()); + CHECK_EQUAL(1U, queue.available()); + CHECK(!queue.empty()); + CHECK(!queue.full()); + + CHECK(iqueue.push(item4)); + CHECK_EQUAL(4U, iqueue.size()); + CHECK_EQUAL(0U, iqueue.available()); + CHECK(!iqueue.empty()); + CHECK(iqueue.full()); + + // Too many + CHECK(!queue.push(item4)); + CHECK_EQUAL(4U, queue.size()); + CHECK_EQUAL(0U, queue.available()); + CHECK(!queue.empty()); + CHECK(queue.full()); + } + }; +} diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index efc88c3b..16cb721c 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -135,7 +135,8 @@ - + + @@ -150,6 +151,9 @@ + + + @@ -163,6 +167,7 @@ + @@ -345,6 +350,7 @@ + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 675dce75..ff3b8299 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -561,9 +561,6 @@ ETL\Utilities\Atomic - - ETL\Utilities\Atomic - Source Files\ECL @@ -588,6 +585,24 @@ ECL + + ETL\Utilities\Atomic + + + ETL\Utilities\Atomic + + + ETL\Containers + + + ETL\Utilities + + + ETL\Utilities + + + ETL\Utilities + @@ -974,6 +989,9 @@ Source Files + + Source Files +