diff --git a/include/etl/atomic.h b/include/etl/atomic.h index 9d18ee5a..9b437c43 100644 --- a/include/etl/atomic.h +++ b/include/etl/atomic.h @@ -32,16 +32,16 @@ SOFTWARE. #include "platform.h" #if ETL_HAS_ATOMIC - #if (ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) + #if (ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST)) || defined(ETL_USE_ATOMIC_STD)) #include "atomic/atomic_std.h" - #elif defined(ETL_COMPILER_ARM5) + #elif defined(ETL_COMPILER_ARM5) || defined(ETL_USE_ATOMIN_ARM5) #include "atomic/atomic_arm.h" - #elif defined(ETL_COMPILER_ARM6) + #elif defined(ETL_COMPILER_ARM6) || defined(ETL_USE_ATOMIN_ARM6) #include "atomic/atomic_arm.h" - #elif defined(ETL_COMPILER_GCC) - #include "atomic/atomic_gcc_sync.h" - #elif defined(ETL_COMPILER_CLANG) - #include "atomic/atomic_clang_sync.h" + #elif defined(ETL_COMPILER_GCC) || defined(ETL_USE_ATOMIN_GCC) + #include "atomic/atomic_gcc.h" + #elif defined(ETL_COMPILER_CLANG) || defined(ETL_USE_ATOMIN_CLANG) + #include "atomic/atomic_clang.h" #endif #endif diff --git a/include/etl/atomic/atomic_arm.h b/include/etl/atomic/atomic_arm.h index 42606b0b..06c0be8a 100644 --- a/include/etl/atomic/atomic_arm.h +++ b/include/etl/atomic/atomic_arm.h @@ -29,6 +29,6 @@ SOFTWARE. #ifndef ETL_ATOMIC_ARM_INCLUDED #define ETL_ATOMIC_ARM_INCLUDED -#include "atomic_gcc_sync.h" +#include "atomic_gcc.h" #endif diff --git a/include/etl/atomic/atomic_clang_sync.h b/include/etl/atomic/atomic_clang.h similarity index 97% rename from include/etl/atomic/atomic_clang_sync.h rename to include/etl/atomic/atomic_clang.h index 23e9360c..95150f25 100644 --- a/include/etl/atomic/atomic_clang_sync.h +++ b/include/etl/atomic/atomic_clang.h @@ -29,6 +29,6 @@ SOFTWARE. #ifndef ETL_ATOMIC_CLANG_INCLUDED #define ETL_ATOMIC_CLANG_INCLUDED -#include "atomic_gcc_sync.h" +#include "atomic_gcc.h" #endif diff --git a/include/etl/atomic/atomic_gcc.h b/include/etl/atomic/atomic_gcc.h new file mode 100644 index 00000000..eb728cde --- /dev/null +++ b/include/etl/atomic/atomic_gcc.h @@ -0,0 +1,1281 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 John Wellbelove + +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_GCC_SYNC_INCLUDED +#define ETL_ATOMIC_GCC_SYNC_INCLUDED + +#include "../platform.h" +#include "../type_traits.h" +#include "../static_assert.h" +#include "../nullptr.h" +#include "../char_traits.h" +#include "../bit.h" +#include "../memory.h" + +#include +#include + +namespace etl +{ + //************************************************************************* + // Atomic type for pre C++11 GCC compilers that support the builtin '__atomic' functions. + // Only integral and pointer types are supported. + //************************************************************************* + + typedef enum memory_order + { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST + } memory_order; + + namespace private_atomic + { + //************************************************************************* + template + struct storage_type + { + typedef +#if ETL_USING_8BIT_TYPES + typename etl::conditional::type>::type>::type type; +#else + typename etl::conditional::type>::type type; +#endif + }; + + template + class atomic_common + { + public: + + // Is always lock free? + static ETL_CONSTANT bool is_always_lock_free = __atomic_always_lock_free(sizeof(TStore), nullptr); + }; + + template + ETL_CONSTANT bool atomic_common::is_always_lock_free; + } + + template ::value> + class atomic; + + //************************************************************************* + /// Specialisation for integral types. + //************************************************************************* + template + class atomic : public etl::private_atomic::atomic_common + { + public: + + //************************************************************************* + /// Default constructor + //************************************************************************* + atomic() + : value(T()) + { + } + + //************************************************************************* + /// Contruct from a value + //************************************************************************* + atomic(T v) + : value(v) + { + } + + //************************************************************************* + /// Assignment + //************************************************************************* + T operator =(T v) + { + store(v); + + return v; + } + + //************************************************************************* + /// Assignment + /// Volatile + //************************************************************************* + T operator =(T v) volatile + { + store(v); + + return v; + } + + //************************************************************************* + /// Pre-increment + //************************************************************************* + T operator ++() + { + return static_cast(__atomic_add_fetch(&value, 1, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Pre-increment + /// Volatile + //************************************************************************* + T operator ++() volatile + { + return static_cast(__atomic_add_fetch(&value, 1, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Post-increment + //************************************************************************* + T operator ++(int) + { + return static_cast(__atomic_fetch_add(&value, 1, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Post-increment + /// Volatile + //************************************************************************* + T operator ++(int) volatile + { + return static_cast(__atomic_fetch_add(&value, 1, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Pre-decrement + //************************************************************************* + T operator --() + { + return static_cast(__atomic_sub_fetch(&value, 1, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Pre-decrement + /// Volatile + //************************************************************************* + T operator --() volatile + { + return static_cast(__atomic_sub_fetch(&value, 1, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Post-decrement + //************************************************************************* + T operator --(int) + { + return static_cast(__atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Post-decrement + /// Volatile + //************************************************************************* + T operator --(int) volatile + { + return static_cast(__atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Add + //************************************************************************* + T operator +=(T v) + { + return static_cast(__atomic_fetch_add(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Add + /// Volatile + //************************************************************************* + T operator +=(T v) volatile + { + return static_cast(__atomic_fetch_add(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Subtract + //************************************************************************* + T operator -=(T v) + { + return static_cast(__atomic_fetch_sub(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Subtract + /// Volatile + //************************************************************************* + T operator -=(T v) volatile + { + return static_cast(__atomic_fetch_sub(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// And + //************************************************************************* + T operator &=(T v) + { + return static_cast(__atomic_fetch_and(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// And + /// Volatile + //************************************************************************* + T operator &=(T v) volatile + { + return static_cast(__atomic_fetch_and(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Or + //************************************************************************* + T operator |=(T v) + { + return static_cast(__atomic_fetch_or(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Or + /// Volatile + //************************************************************************* + T operator |=(T v) volatile + { + return static_cast(__atomic_fetch_or(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Exclusive or + //************************************************************************* + T operator ^=(T v) + { + return static_cast(__atomic_fetch_xor(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Exclusive or + /// Volatile + //************************************************************************* + T operator ^=(T v) volatile + { + return static_cast(__atomic_fetch_xor(&value, v, etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Conversion operator + //************************************************************************* + operator T() const + { + return load(); + } + + //************************************************************************* + /// Conversion operator + /// Volatile + //************************************************************************* + operator T() volatile const + { + return load(); + } + + //************************************************************************* + /// Is lock free? + //************************************************************************* + bool is_lock_free() const + { + return __atomic_is_lock_free(sizeof(T), &value); + } + + //************************************************************************* + /// Is lock free? + /// Volatile + //************************************************************************* + bool is_lock_free() const volatile + { + return __atomic_is_lock_free(sizeof(T), &value); + } + + //************************************************************************* + /// Store + //************************************************************************* + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + __atomic_store_n(&value, v, order); + } + + //************************************************************************* + /// Store + /// Volatile + //************************************************************************* + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + __atomic_store_n(&value, v, order); + } + + //************************************************************************* + /// Load + //************************************************************************* + T load(etl::memory_order order = etl::memory_order_seq_cst) const + { + return static_cast(__atomic_load_n(&value, order)); + } + + //************************************************************************* + /// Load + /// Volatile + //************************************************************************* + T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile + { + return static_cast(__atomic_load_n(&value, order)); + } + + //************************************************************************* + /// Fetch add + //************************************************************************* + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return static_cast(__atomic_fetch_add(&value, v, order)); + } + + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return static_cast(__atomic_fetch_add(&value, v, order)); + } + + //************************************************************************* + /// Fetch subtract + //************************************************************************* + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return static_cast(__atomic_fetch_sub(&value, v, order)); + } + + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return static_cast(__atomic_fetch_sub(&value, v, order)); + } + + //************************************************************************* + /// Fetch or + //************************************************************************* + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return static_cast(__atomic_fetch_or(&value, v, order)); + } + + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return static_cast(__atomic_fetch_or(&value, v, order)); + } + + //************************************************************************* + /// Fetch and + //************************************************************************* + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return static_cast(__atomic_fetch_and(&value, v, order)); + } + + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return static_cast(__atomic_fetch_and(&value, v, order)); + } + + //************************************************************************* + /// Fetch exclusive or + //************************************************************************* + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return static_cast(__atomic_fetch_xor(&value, v, order)); + } + + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __atomic_fetch_xor(&value, v, order); + } + + //************************************************************************* + /// Exchange + //************************************************************************* + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return static_cast(__atomic_exchange_n(&value, v, order)); + } + + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return static_cast(__atomic_exchange_n(&value, v, order)); + } + + //************************************************************************* + /// Compare exchange weak + //************************************************************************* + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return __atomic_compare_exchange_n(&value, &expected, desired, true, order, order); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __atomic_compare_exchange_n(&value, &expected, desired, true, order, order); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + return __atomic_compare_exchange_n(&value, &expected, desired, true, success, failure); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + return __atomic_compare_exchange_n(&value, &expected, desired, true, success, failure); + } + + //************************************************************************* + /// Compare exchange strong + //************************************************************************* + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return __atomic_compare_exchange_n(&value, &expected, desired, false, order, order); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __atomic_compare_exchange_n(&value, &expected, desired, false, order, order); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + return __atomic_compare_exchange_n(&value, &expected, desired, false, success, failure); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + return __atomic_compare_exchange_n(&value, &expected, desired, false, success, failure); + } + + private: + + atomic& operator =(const atomic&) ETL_DELETE; + atomic& operator =(const atomic&) volatile ETL_DELETE; + + mutable T value; + }; + + //************************************************************************* + /// Specialisation for pointer types. + //************************************************************************* + template + class atomic : public etl::private_atomic::atomic_common + { + public: + + //************************************************************************* + /// Default constructor + //************************************************************************* + atomic() + : value(0U) + { + } + + //************************************************************************* + /// Contruct from a value + //************************************************************************* + atomic(T* v) + : value(uintptr_t(v)) + { + } + + //************************************************************************* + /// Assignment + //************************************************************************* + T* operator =(T* v) + { + store(v); + + return v; + } + + //************************************************************************* + /// Assignment + /// Volatile + //************************************************************************* + T* operator =(T* v) volatile + { + store(v); + + return v; + } + + //************************************************************************* + /// Pre-increment + //************************************************************************* + T* operator ++() + { + return reinterpret_cast(__atomic_add_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Pre-increment + /// Volatile + //************************************************************************* + T* operator ++() volatile + { + return reinterpret_cast(__atomic_add_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Post-increment + //************************************************************************* + T* operator ++(int) + { + return reinterpret_cast(__atomic_fetch_add(&value, sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Post-increment + /// Volatile + //************************************************************************* + T* operator ++(int) volatile + { + return reinterpret_cast(__atomic_fetch_add(&value, sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Pre-decrement + //************************************************************************* + T* operator --() + { + return reinterpret_cast(__atomic_sub_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Pre-decrement + /// Volatile + //************************************************************************* + T* operator --() volatile + { + return reinterpret_cast(__atomic_sub_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Post-decrement + //************************************************************************* + T* operator --(int) + { + return reinterpret_cast(__atomic_fetch_sub(&value, sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Post-decrement + /// Volatile + //************************************************************************* + T* operator --(int) volatile + { + return reinterpret_cast(__atomic_fetch_sub(&value, sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Add + //************************************************************************* + T* operator +=(ptrdiff_t v) + { + return reinterpret_cast(__atomic_fetch_add(&value, v * sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Add + /// Volatile + //************************************************************************* + T* operator +=(ptrdiff_t v) volatile + { + return reinterpret_cast(__atomic_fetch_add(&value, v * sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Subtract + //************************************************************************* + T* operator -=(ptrdiff_t v) + { + return reinterpret_cast(__atomic_fetch_sub(&value, v * sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Subtract + /// Volatile + //************************************************************************* + T* operator -=(ptrdiff_t v) volatile + { + return reinterpret_cast(__atomic_fetch_sub(&value, v * sizeof(T), etl::memory_order_seq_cst)); + } + + //************************************************************************* + /// Conversion operator + //************************************************************************* + operator T* () const + { + return load(); + } + + //************************************************************************* + /// Conversion operator + /// Volatile + //************************************************************************* + operator T*() volatile const + { + return load(); + } + + //************************************************************************* + /// Is lock free? + //************************************************************************* + bool is_lock_free() const + { + return __atomic_is_lock_free(sizeof(uintptr_t), &value); + } + + //************************************************************************* + /// Is lock free? + /// Volatile + //************************************************************************* + bool is_lock_free() const volatile + { + return __atomic_is_lock_free(sizeof(uintptr_t), &value); + } + + //************************************************************************* + /// Store + //************************************************************************* + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) + { + __atomic_store_n(&value, uintptr_t(v), order); + } + + //************************************************************************* + /// Store + /// Volatile + //************************************************************************* + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + __atomic_store_n(&value, uintptr_t(v), order); + } + + //************************************************************************* + /// Load + //************************************************************************* + T* load(etl::memory_order order = etl::memory_order_seq_cst) const + { + return reinterpret_cast(__atomic_load_n(&value, order)); + } + + //************************************************************************* + /// Load + /// Volatile + //************************************************************************* + T* load(etl::memory_order order = etl::memory_order_seq_cst) const volatile + { + return reinterpret_cast(__atomic_load_n(&value, order)); + } + + //************************************************************************* + /// Fetch add + //************************************************************************* + T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) + { + return reinterpret_cast(__atomic_fetch_add(&value, v, order)); + } + + //************************************************************************* + /// Fetch add + /// Volatile + //************************************************************************* + T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return reinterpret_cast(__atomic_fetch_add(&value, v, order)); + } + + //************************************************************************* + /// Fetch subtract + //************************************************************************* + T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) + { + return reinterpret_cast(__atomic_fetch_sub(&value, v, order)); + } + + //************************************************************************* + /// Fetch subtract + /// Volatile + //************************************************************************* + T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return reinterpret_cast(__atomic_fetch_sub(&value, v, order)); + } + + //************************************************************************* + /// Exchange + //************************************************************************* + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) + { + return reinterpret_cast(__atomic_exchange_n(&value, uintptr_t(v), order)); + } + + //************************************************************************* + /// Exchange + /// Volatile + //************************************************************************* + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return reinterpret_cast(__atomic_exchange_n(&value, uintptr_t(v), order)); + } + + //************************************************************************* + /// Compare exchange weak + //************************************************************************* + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) + { + uintptr_t expected_v = uintptr_t(expected); + + return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), true, order, order); + } + + //************************************************************************* + /// Compare exchange weak + /// Volatile + //************************************************************************* + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + uintptr_t expected_v = uintptr_t(expected); + + return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), true, order, order); + } + + //************************************************************************* + /// Compare exchange weak + /// Success/failure + //************************************************************************* + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + uintptr_t expected_v = uintptr_t(expected); + + return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), true, success, failure); + } + + //************************************************************************* + /// Compare exchange weak + /// Success/failure + /// Volatile + //************************************************************************* + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + uintptr_t expected_v = uintptr_t(expected); + + return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), true, success, failure); + } + + //************************************************************************* + /// Compare exchange strong + //************************************************************************* + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) + { + uintptr_t expected_v = uintptr_t(expected); + + return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), false, order, order); + } + + //************************************************************************* + /// Compare exchange strong + /// Volatile + //************************************************************************* + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + uintptr_t expected_v = uintptr_t(expected); + + return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), false, order, order); + } + + //************************************************************************* + /// Compare exchange strong + /// Success/failure + //************************************************************************* + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + uintptr_t expected_v = uintptr_t(expected); + + return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), false, success, failure); + } + + //************************************************************************* + /// Compare exchange strong + /// Success/failure + /// Volatile + //************************************************************************* + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + uintptr_t expected_v = uintptr_t(expected); + + return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), false, success, failure); + } + + private: + + atomic& operator =(const atomic&) ETL_DELETE; + atomic& operator =(const atomic&) volatile ETL_DELETE; + + mutable uintptr_t value; + }; + + //************************************************************************* + /// Specialisation for other types that can fit in an integral sized storage. + //************************************************************************* + template + class atomic : public etl::private_atomic::atomic_common::type> + { + private: + + /// Define an integral storage type that can hold the value. + typedef typename etl::private_atomic::storage_type::type storage_t; + + ETL_STATIC_ASSERT(sizeof(storage_t) >= sizeof(T), "Cannot assign atomic storage for T"); + +#if defined(ETL_COMPILER_GCC) + ETL_STATIC_ASSERT(__has_trivial_copy(T), "Type is not trivially copyable"); +#else + ETL_STATIC_ASSERT(__is_trivially_copyable(T), "Type is not trivially copyable"); +#endif + + public: + + //************************************************************************* + /// Default constructor + //************************************************************************* + atomic() + : value(storage_t()) + { + T v = T(); + memcpy(&value, &v, sizeof(v)); + } + + //************************************************************************* + /// Contruct from a value + //************************************************************************* + atomic(T v) + : value(storage_t()) + { + memcpy(&value, &v, sizeof(v)); + } + + //************************************************************************* + /// Assignment + //************************************************************************* + T operator =(T v) + { + store(v); + + return v; + } + + //************************************************************************* + /// Assignment + /// Volatile + //************************************************************************* + T operator =(T v) volatile + { + store(v); + + return v; + } + + //************************************************************************* + /// Conversion operator to T + //************************************************************************* + operator T() const + { + return load(); + } + + //************************************************************************* + /// Conversion operator to T + /// Volatile + //************************************************************************* + operator T() volatile const + { + return load(); + } + + //************************************************************************* + /// Is lock free? + //************************************************************************* + bool is_lock_free() const + { + return __atomic_is_lock_free(sizeof(T), &value); + } + + //************************************************************************* + /// Is lock free? + /// Volatile + //************************************************************************* + bool is_lock_free() const volatile + { + return __atomic_is_lock_free(sizeof(T), &value); + } + + //************************************************************************* + /// Store + //************************************************************************* + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + storage_t s = 0; + + memcpy(&s, &v, sizeof(T)); + + __atomic_store_n(&value, s, order); + } + + //************************************************************************* + /// Store + /// Volatile + //************************************************************************* + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + storage_t s = 0; + + memcpy(&s, &v, sizeof(T)); + + __atomic_store_n(&value, s, order); + } + + //************************************************************************* + /// Load + //************************************************************************* + T load(etl::memory_order order = etl::memory_order_seq_cst) const + { + storage_t s = __atomic_load_n(&value, order); + etl::uninitialized_buffer_of buffer; + + memcpy(buffer.data(), &s, sizeof(T)); + + return buffer; // Implicit conversion to T. + } + + //************************************************************************* + /// Load + /// Volatile + //************************************************************************* + T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile + { + storage_t s = __atomic_load_n(&value, order); + etl::uninitialized_buffer_of buffer; + + memcpy(buffer.data(), &s, sizeof(T)); + + return buffer; // Implicit conversion to T. + } + + //************************************************************************* + /// Exchange + //************************************************************************* + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + storage_t next; + memcpy(&next, &v, sizeof(T)); + + storage_t prev = __atomic_exchange_n(&value, next, order); + + etl::uninitialized_buffer_of buffer; + memcpy(buffer.data(), &prev, sizeof(T)); + + return buffer; // Implicit conversion to T. + } + + //************************************************************************* + /// Exchange + /// Volatile + //************************************************************************* + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + storage_t next; + memcpy(&next, &v, sizeof(T)); + + storage_t prev = __atomic_exchange_n(&value, next, order); + + etl::uninitialized_buffer_of buffer; + memcpy(buffer.data(), &prev, sizeof(T)); + + return buffer; // Implicit conversion to T. + } + + //************************************************************************* + /// Compare exchange weak + //************************************************************************* + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + storage_t expected_s; + memcpy(&expected_s, &expected, sizeof(T)); + + storage_t desired_s; + memcpy(&desired_s, &desired, sizeof(T)); + + bool pass = __atomic_compare_exchange_n(&value, &expected_s, desired_s, true, order, order); + + if (pass) + { + memcpy(reinterpret_cast(&expected), &expected_s, sizeof(T)); + } + + return pass; + } + + //************************************************************************* + /// Compare exchange weak + /// Volatile + //************************************************************************* + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + storage_t expected_s; + memcpy(&expected_s, &expected, sizeof(T)); + + storage_t desired_s; + memcpy(&desired_s, &desired, sizeof(T)); + + bool pass = __atomic_compare_exchange_n(&value, &expected_s, desired_s, true, order, order); + + if (pass) + { + memcpy(reinterpret_cast(&expected), &expected_s, sizeof(T)); + } + + return pass; + } + + //************************************************************************* + /// Compare exchange weak + /// Success/Failure + //************************************************************************* + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + storage_t expected_s; + memcpy(&expected_s, &expected, sizeof(T)); + + storage_t desired_s; + memcpy(&desired_s, &desired, sizeof(T)); + + bool pass = __atomic_compare_exchange_n(&value, &expected_s, desired_s, true, success, failure); + + if (pass) + { + memcpy(reinterpret_cast(&expected), &expected_s, sizeof(T)); + } + + return pass; + } + + //************************************************************************* + /// Compare exchange weak + /// Success/Failure + /// Volatile + //************************************************************************* + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + storage_t expected_s; + memcpy(&expected_s, &expected, sizeof(T)); + + storage_t desired_s; + memcpy(&desired_s, &desired, sizeof(T)); + + bool pass = __atomic_compare_exchange_n(&value, &expected_s, desired_s, true, success, failure); + + if (pass) + { + memcpy(reinterpret_cast(&expected), &expected_s, sizeof(T)); + } + + return pass; + } + + //************************************************************************* + /// Compare exchange strong + //************************************************************************* + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + storage_t expected_s; + memcpy(&expected_s, &expected, sizeof(T)); + + storage_t desired_s; + memcpy(&desired_s, &desired, sizeof(T)); + + bool pass = __atomic_compare_exchange_n(&value, &expected_s, desired_s, false, order, order); + + if (pass) + { + memcpy(reinterpret_cast(&expected), &expected_s, sizeof(T)); + } + + return pass; + } + + //************************************************************************* + /// Compare exchange strong + /// Volatile + //************************************************************************* + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + storage_t expected_s; + memcpy(&expected_s, &expected, sizeof(T)); + + storage_t desired_s; + memcpy(&desired_s, &desired, sizeof(T)); + + bool pass = __atomic_compare_exchange_n(&value, &expected_s, desired_s, false, order, order); + + if (pass) + { + memcpy(reinterpret_cast(&expected), &expected_s, sizeof(T)); + } + + return pass; + } + + //************************************************************************* + /// Compare exchange strong + /// Success/Failure + //************************************************************************* + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + storage_t expected_s; + memcpy(&expected_s, &expected, sizeof(T)); + + storage_t desired_s; + memcpy(&desired_s, &desired, sizeof(T)); + + bool pass = __atomic_compare_exchange_n(&value, &expected_s, desired_s, false, success, failure); + + if (pass) + { + memcpy(reinterpret_cast(&expected), &expected_s, sizeof(T)); + } + + return pass; + } + + //************************************************************************* + /// Compare exchange strong + /// Success/Failure + /// Volatile + //************************************************************************* + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + storage_t expected_s; + memcpy(&expected_s, &expected, sizeof(T)); + + storage_t desired_s; + memcpy(&desired_s, &desired, sizeof(T)); + + bool pass = __atomic_compare_exchange_n(&value, &expected_s, desired_s, false, success, failure); + + if (pass) + { + memcpy(reinterpret_cast(&expected), &expected_s, sizeof(T)); + } + + return pass; + } + + private: + + atomic& operator =(const atomic&) ETL_DELETE; + atomic& operator =(const atomic&) volatile ETL_DELETE; + + mutable storage_t value; + }; + + typedef etl::atomic atomic_bool; + typedef etl::atomic atomic_char; + typedef etl::atomic atomic_schar; + typedef etl::atomic atomic_uchar; + typedef etl::atomic atomic_short; + typedef etl::atomic atomic_ushort; + typedef etl::atomic atomic_int; + typedef etl::atomic atomic_uint; + typedef etl::atomic atomic_long; + typedef etl::atomic atomic_ulong; + typedef etl::atomic atomic_llong; + typedef etl::atomic atomic_ullong; + typedef etl::atomic atomic_wchar_t; +#if ETL_HAS_NATIVE_CHAR8_T + typedef etl::atomic atomic_char8_t; +#endif +#if ETL_HAS_NATIVE_CHAR16_T + typedef etl::atomic atomic_char16_t; +#endif +#if ETL_HAS_NATIVE_CHAR32_T + typedef etl::atomic atomic_char32_t; +#endif +#if ETL_USING_8BIT_TYPES + typedef etl::atomic atomic_uint8_t; + typedef etl::atomic atomic_int8_t; +#endif + typedef etl::atomic atomic_uint16_t; + typedef etl::atomic atomic_int16_t; + typedef etl::atomic atomic_uint32_t; + typedef etl::atomic atomic_int32_t; +#if ETL_USING_64BIT_TYPES + typedef etl::atomic atomic_uint64_t; + typedef etl::atomic atomic_int64_t; +#endif + typedef etl::atomic atomic_int_least8_t; + typedef etl::atomic atomic_uint_least8_t; + typedef etl::atomic atomic_int_least16_t; + typedef etl::atomic atomic_uint_least16_t; + typedef etl::atomic atomic_int_least32_t; + typedef etl::atomic atomic_uint_least32_t; +#if ETL_USING_64BIT_TYPES + typedef etl::atomic atomic_int_least64_t; + typedef etl::atomic atomic_uint_least64_t; +#endif + typedef etl::atomic atomic_int_fast8_t; + typedef etl::atomic atomic_uint_fast8_t; + typedef etl::atomic atomic_int_fast16_t; + typedef etl::atomic atomic_uint_fast16_t; + typedef etl::atomic atomic_int_fast32_t; + typedef etl::atomic atomic_uint_fast32_t; +#if ETL_USING_64BIT_TYPES + typedef etl::atomic atomic_int_fast64_t; + typedef etl::atomic atomic_uint_fast64_t; +#endif + typedef etl::atomic atomic_intptr_t; + typedef etl::atomic atomic_uintptr_t; + typedef etl::atomic atomic_size_t; + typedef etl::atomic atomic_ptrdiff_t; + typedef etl::atomic atomic_intmax_t; + typedef etl::atomic atomic_uintmax_t; +} + +#endif + diff --git a/include/etl/atomic/atomic_gcc_sync.h b/include/etl/atomic/atomic_gcc_sync.h deleted file mode 100644 index 67c7c8bf..00000000 --- a/include/etl/atomic/atomic_gcc_sync.h +++ /dev/null @@ -1,2255 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2017 John Wellbelove - -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_GCC_SYNC_INCLUDED -#define ETL_ATOMIC_GCC_SYNC_INCLUDED - -#include "../platform.h" -#include "../type_traits.h" -#include "../static_assert.h" -#include "../nullptr.h" -#include "../char_traits.h" -#include "../mutex.h" - -#include -#include - -// Select the atomic builtins based on the ARM5 version of the GCC compiler. -#if defined(ETL_COMPILER_ARM5) - #define ETL_USE_SYNC_BUILTINS -#endif - -// Select the atomic builtins based on the ARM6 version of the GCC compiler. -#if defined(ETL_COMPILER_ARM6) - #if ETL_COMPILER_FULL_VERSION >= 40700 - #define ETL_USE_ATOMIC_BUILTINS - #else - #define ETL_USE_SYNC_BUILTINS - #endif -#endif - -// Select the atomic builtins based on the version of the GCC compiler. -#if defined(ETL_COMPILER_GCC) - #if ETL_COMPILER_FULL_VERSION >= 40700 - #define ETL_USE_ATOMIC_BUILTINS - #else - #define ETL_USE_SYNC_BUILTINS - #endif -#endif - -// Select the atomic builtins based on the version of the Clang compiler. -#if defined(ETL_COMPILER_CLANG) - #if ETL_COMPILER_FULL_VERSION >= 50000 - #define ETL_USE_ATOMIC_BUILTINS - #else - #define ETL_USE_SYNC_BUILTINS - #endif -#endif - -namespace etl -{ -#if defined(ETL_USE_ATOMIC_BUILTINS) - -#define ETL_BUILTIN_LOCK while (__atomic_test_and_set(&flag, etl::memory_order_seq_cst)) {} -#define ETL_BUILTIN_UNLOCK __atomic_clear(&flag, etl::memory_order_seq_cst); - - //*************************************************************************** - // Atomic type for pre C++11 GCC compilers that support the builtin '__atomic' functions. - // Only integral and pointer types are supported. - //*************************************************************************** - - typedef enum memory_order - { - memory_order_relaxed = __ATOMIC_RELAXED, - memory_order_consume = __ATOMIC_CONSUME, - memory_order_acquire = __ATOMIC_ACQUIRE, - memory_order_release = __ATOMIC_RELEASE, - memory_order_acq_rel = __ATOMIC_ACQ_REL, - memory_order_seq_cst = __ATOMIC_SEQ_CST - } memory_order; - - template - struct atomic_traits - { - static ETL_CONSTANT bool is_always_lock_free = Is_Always_Lock_Free; - }; - - template - ETL_CONSTANT bool atomic_traits::is_always_lock_free; - - //*************************************************************************** - /// For all types except bool, pointers and types that are always lock free. - //*************************************************************************** - template ::value> - class atomic : public atomic_traits - { - public: - - atomic() - : value(T()) - { - } - - atomic(T v) - : value(v) - { - } - - // Assignment - T operator =(T v) - { - store(v); - - return v; - } - - T operator =(T v) volatile - { - store(v); - - return v; - } - - // Pre-increment - T operator ++() - { - return __atomic_add_fetch(&value, 1, etl::memory_order_seq_cst); - } - - T operator ++() volatile - { - return __atomic_add_fetch(&value, 1, etl::memory_order_seq_cst); - } - - // Post-increment - T operator ++(int) - { - return __atomic_fetch_add(&value, 1, etl::memory_order_seq_cst); - } - - T operator ++(int) volatile - { - return __atomic_fetch_add(&value, 1, etl::memory_order_seq_cst); - } - - // Pre-decrement - T operator --() - { - return __atomic_sub_fetch(&value, 1, etl::memory_order_seq_cst); - } - - T operator --() volatile - { - return __atomic_sub_fetch(&value, 1, etl::memory_order_seq_cst); - } - - // Post-decrement - T operator --(int) - { - return __atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst); - } - - T operator --(int) volatile - { - return __atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst); - } - - // Add - T operator +=(T v) - { - return __atomic_fetch_add(&value, v, etl::memory_order_seq_cst); - } - - T operator +=(T v) volatile - { - return __atomic_fetch_add(&value, v, etl::memory_order_seq_cst); - } - - // Subtract - T operator -=(T v) - { - return __atomic_fetch_sub(&value, v, etl::memory_order_seq_cst); - } - - T operator -=(T v) volatile - { - return __atomic_fetch_sub(&value, v, etl::memory_order_seq_cst); - } - - // And - T operator &=(T v) - { - return __atomic_fetch_and(&value, v, etl::memory_order_seq_cst); - } - - T operator &=(T v) volatile - { - return __atomic_fetch_and(&value, v, etl::memory_order_seq_cst); - } - - // Or - T operator |=(T v) - { - return __atomic_fetch_or(&value, v, etl::memory_order_seq_cst); - } - - T operator |=(T v) volatile - { - return __atomic_fetch_or(&value, v, etl::memory_order_seq_cst); - } - - // Exclusive or - T operator ^=(T v) - { - return __atomic_fetch_xor(&value, v, etl::memory_order_seq_cst); - } - - T operator ^=(T v) volatile - { - return __atomic_fetch_xor(&value, v, etl::memory_order_seq_cst); - } - - // Conversion operator - operator T () const - { - return __atomic_fetch_add(&value, 0, etl::memory_order_seq_cst); - } - - operator T() volatile const - { - return __atomic_fetch_add(&value, 0, etl::memory_order_seq_cst); - } - - // Is lock free? - bool is_lock_free() const - { - return true; - } - - bool is_lock_free() const volatile - { - return true; - } - - // Store - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - __atomic_store_n(&value, v, order); - } - - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - __atomic_store_n(&value, v, order); - } - - // Load - T load(etl::memory_order order = etl::memory_order_seq_cst) const - { - return __atomic_load_n(&value, order); - } - - T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - return __atomic_load_n(&value, order); - } - - // Fetch add - T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - return __atomic_fetch_add(&value, v, order); - } - - T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return __atomic_fetch_add(&value, v, order); - } - - // Fetch subtract - T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - return __atomic_fetch_sub(&value, v, order); - } - - T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return __atomic_fetch_sub(&value, v, order); - } - - // Fetch or - T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - return __atomic_fetch_or(&value, v, order); - } - - T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return __atomic_fetch_or(&value, v, order); - } - - // Fetch and - T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - return __atomic_fetch_and(&value, v, order); - } - - T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return __atomic_fetch_and(&value, v, order); - } - - // Fetch exclusive or - T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - return __atomic_fetch_xor(&value, v, order); - } - - T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return __atomic_fetch_xor(&value, v, order); - } - - // Exchange - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - return __atomic_exchange_n(&value, v, order); - } - - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return __atomic_exchange_n(&value, v, order); - } - - // Compare exchange weak - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) - { - return __atomic_compare_exchange_n(&value, &expected, desired, true, order, order); - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return __atomic_compare_exchange_n(&value, &expected, desired, true, order, order); - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) - { - return __atomic_compare_exchange_n(&value, &expected, desired, true, success, failure); - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - return __atomic_compare_exchange_n(&value, &expected, desired, true, success, failure); - } - - // Compare exchange strong - bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) - { - return __atomic_compare_exchange_n(&value, &expected, desired, false, order, order); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return __atomic_compare_exchange_n(&value, &expected, desired, false, order, order); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) - { - return __atomic_compare_exchange_n(&value, &expected, desired, false, success, failure); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - return __atomic_compare_exchange_n(&value, &expected, desired, false, success, failure); - } - - private: - - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; - - mutable T value; - }; - - //*************************************************************************** - /// Specialisation for pointers - //*************************************************************************** - template - class atomic : public atomic_traits - { - public: - - atomic() - : value(0U) - { - } - - atomic(T* v) - : value(uintptr_t(v)) - { - } - - // Assignment - T* operator =(T* v) - { - store(v); - - return v; - } - - T* operator =(T* v) volatile - { - store(v); - - return v; - } - - // Pre-increment - T* operator ++() - { - return reinterpret_cast(__atomic_add_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); - } - - T* operator ++() volatile - { - return reinterpret_cast(__atomic_add_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); - } - - // Post-increment - T* operator ++(int) - { - return reinterpret_cast(__atomic_fetch_add(&value, sizeof(T), etl::memory_order_seq_cst)); - } - - T* operator ++(int) volatile - { - return reinterpret_cast(__atomic_fetch_add(&value, sizeof(T), etl::memory_order_seq_cst)); - } - - // Pre-decrement - T* operator --() - { - return reinterpret_cast(__atomic_sub_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); - } - - T* operator --() volatile - { - return reinterpret_cast(__atomic_sub_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); - } - - // Post-decrement - T* operator --(int) - { - return reinterpret_cast(__atomic_fetch_sub(&value, sizeof(T), etl::memory_order_seq_cst)); - } - - T* operator --(int) volatile - { - return reinterpret_cast(__atomic_fetch_sub(&value, sizeof(T), etl::memory_order_seq_cst)); - } - - // Add - T* operator +=(ptrdiff_t v) - { - return reinterpret_cast(__atomic_fetch_add(&value, v * sizeof(T), etl::memory_order_seq_cst)); - } - - T* operator +=(ptrdiff_t v) volatile - { - return reinterpret_cast(__atomic_fetch_add(&value, v * sizeof(T), etl::memory_order_seq_cst)); - } - - // Subtract - T* operator -=(ptrdiff_t v) - { - return reinterpret_cast(__atomic_fetch_sub(&value, v * sizeof(T), etl::memory_order_seq_cst)); - } - - T* operator -=(ptrdiff_t v) volatile - { - return reinterpret_cast(__atomic_fetch_sub(&value, v * sizeof(T), etl::memory_order_seq_cst)); - } - - // Conversion operator - operator T* () const - { - return reinterpret_cast(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst)); - } - - operator T*() volatile const - { - return reinterpret_cast(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst)); - } - - // Is lock free? - bool is_lock_free() const - { - return true; - } - - bool is_lock_free() const volatile - { - return true; - } - - // Store - void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) - { - __atomic_store_n(&value, uintptr_t(v), order); - } - - void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - __atomic_store_n(&value, uintptr_t(v), order); - } - - // Load - T* load(etl::memory_order order = etl::memory_order_seq_cst) const - { - return reinterpret_cast(__atomic_load_n(&value, order)); - } - - T* load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - return reinterpret_cast(__atomic_load_n(&value, order)); - } - - // Fetch add - T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) - { - return reinterpret_cast(__atomic_fetch_add(&value, v, order)); - } - - T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return reinterpret_cast(__atomic_fetch_add(&value, v, order)); - } - - // Fetch subtract - T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) - { - return reinterpret_cast(__atomic_fetch_sub(&value, v, order)); - } - - T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return reinterpret_cast(__atomic_fetch_sub(&value, v, order)); - } - - // Exchange - T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) - { - return reinterpret_cast(__atomic_exchange_n(&value, uintptr_t(v), order)); - } - - T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return reinterpret_cast(__atomic_exchange_n(&value, uintptr_t(v), order)); - } - - // Compare exchange weak - bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) - { - uintptr_t expected_v = uintptr_t(expected); - - return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), true, order, order); - } - - bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - uintptr_t expected_v = uintptr_t(expected); - - return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), true, order, order); - } - - bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) - { - uintptr_t expected_v = uintptr_t(expected); - - return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), true, success, failure); - } - - bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile - { - uintptr_t expected_v = uintptr_t(expected); - - return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), true, success, failure); - } - - // Compare exchange strong - bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) - { - uintptr_t expected_v = uintptr_t(expected); - - return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), false, order, order); - } - - bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - uintptr_t expected_v = uintptr_t(expected); - - return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), false, order, order); - } - - bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) - { - uintptr_t expected_v = uintptr_t(expected); - - return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), false, success, failure); - } - - bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile - { - uintptr_t expected_v = uintptr_t(expected); - - return __atomic_compare_exchange_n(&value, &expected_v, uintptr_t(desired), false, success, failure); - } - - private: - - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; - - mutable uintptr_t value; - }; - - //*************************************************************************** - /// Specialisation for bool - //*************************************************************************** - template <> - class atomic : public atomic_traits - { - public: - - atomic() - : value(0U) - { - } - - atomic(bool v) - : value(char(v)) - { - } - - // Assignment - bool operator =(bool v) - { - store(v); - - return v; - } - - bool operator =(bool v) volatile - { - store(v); - - return v; - } - - // Conversion operator - operator bool () const - { - return static_cast(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst)); - } - - operator bool() volatile const - { - return static_cast(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst)); - } - - // Is lock free? - bool is_lock_free() const - { - return true; - } - - bool is_lock_free() const volatile - { - return true; - } - - // Store - void store(bool v, etl::memory_order order = etl::memory_order_seq_cst) - { - __atomic_store_n(&value, char(v), order); - } - - void store(bool v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - __atomic_store_n(&value, char(v), order); - } - - // Load - bool load(etl::memory_order order = etl::memory_order_seq_cst) const - { - return static_cast(__atomic_load_n(&value, order)); - } - - bool load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - return static_cast(__atomic_load_n(&value, order)); - } - - // Exchange - bool exchange(bool v, etl::memory_order order = etl::memory_order_seq_cst) - { - return static_cast(__atomic_exchange_n(&value, char(v), order)); - } - - bool exchange(bool v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return static_cast(__atomic_exchange_n(&value, char(v), order)); - } - - // Compare exchange weak - bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) - { - char expected_v = char(expected); - char desired_v = char(desired); - - return __atomic_compare_exchange_n(&value, &expected_v, desired_v, true, order, order); - } - - bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - char expected_v = char(expected); - char desired_v = char(desired); - - return __atomic_compare_exchange_n(&value, &expected_v, desired_v, true, order, order); - } - - bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) - { - char expected_v = char(expected); - char desired_v = char(desired); - - return __atomic_compare_exchange_n(&value, &expected_v, desired_v, true, success, failure); - } - - bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) volatile - { - char expected_v = char(expected); - char desired_v = char(desired); - - return __atomic_compare_exchange_n(&value, &expected_v, desired_v, true, success, failure); - } - - // Compare exchange strong - bool compare_exchange_strong(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) - { - char expected_v = char(expected); - char desired_v = char(desired); - - return __atomic_compare_exchange_n(&value, &expected_v, desired_v, false, order, order); - } - - bool compare_exchange_strong(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - char expected_v = char(expected); - char desired_v = char(desired); - - return __atomic_compare_exchange_n(&value, &expected_v, desired_v, false, order, order); - } - - bool compare_exchange_strong(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) - { - char expected_v = char(expected); - char desired_v = char(desired); - - return __atomic_compare_exchange_n(&value, &expected_v, desired_v, false, success, failure); - } - - bool compare_exchange_strong(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) volatile - { - char expected_v = char(expected); - char desired_v = char(desired); - - return __atomic_compare_exchange_n(&value, &expected_v, desired_v, false, success, failure); - } - - private: - - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; - - mutable char value; - }; - - //*************************************************************************** - /// Specialisation for type that are not integral, pointer or bool. - /// Uses a mutex to control access. - //*************************************************************************** - template - class atomic : public atomic_traits - { - public: - - atomic() - : flag(0) - , value(T()) - { - } - - atomic(T v) - : flag(0) - , value(v) - { - } - - // Assignment - T operator =(T v) - { - store(v); - - return v; - } - - T operator =(T v) volatile - { - store(v); - - return v; - } - - // Conversion operator - operator T () const - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - operator T() volatile const - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - // Is lock free? - bool is_lock_free() const - { - return false; - } - - bool is_lock_free() const volatile - { - return false; - } - - // Store - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - ETL_BUILTIN_LOCK; - value = v; - ETL_BUILTIN_UNLOCK; - } - - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - ETL_BUILTIN_LOCK; - value = v; - ETL_BUILTIN_UNLOCK; - } - - // Load - T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - (void)order; - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - // Load - T load(etl::memory_order order = etl::memory_order_seq_cst) const - { - (void)order; - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - // Exchange - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - ETL_BUILTIN_LOCK; - T result = value; - value = v; - ETL_BUILTIN_UNLOCK; - - return result; - } - - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - ETL_BUILTIN_LOCK; - T result = value; - value = v; - ETL_BUILTIN_UNLOCK; - - return result; - } - - // Compare exchange weak - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) - { - bool result; - - (void)order; - ETL_BUILTIN_LOCK; - if (memcmp(&value, &expected, sizeof(T)) == 0) - { - value = desired; - result = true; - } - else - { - result = false; - } - ETL_BUILTIN_UNLOCK; - - return result; - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - bool result; - - (void)order; - ETL_BUILTIN_LOCK; - if (memcmp(&value, &expected, sizeof(T)) == 0) - { - value = desired; - result = true; - } - else - { - result = false; - } - ETL_BUILTIN_UNLOCK; - - return result; - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) - { - (void)success; - (void)failure; - return compare_exchange_weak(expected, desired); - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - (void)success; - (void)failure; - return compare_exchange_weak(expected, desired); - } - - // Compare exchange strong - bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - return compare_exchange_weak(expected, desired); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - return compare_exchange_weak(expected, desired); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) - { - (void)success; - (void)failure; - return compare_exchange_weak(expected, desired); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - (void)success; - (void)failure; - return compare_exchange_weak(expected, desired); - } - - private: - - mutable char flag; - mutable T value; - }; - -#undef ETL_BUILTIN_LOCK -#undef ETL_BUILTIN_UNLOCK - -#endif - -#if defined(ETL_USE_SYNC_BUILTINS) - -#define ETL_BUILTIN_LOCK while (__sync_lock_test_and_set(&flag, 1U)) {} -#define ETL_BUILTIN_UNLOCK __sync_lock_release(&flag); - - //*************************************************************************** - // 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 - struct atomic_traits - { - static ETL_CONSTANT bool is_always_lock_free = Is_Always_Lock_Free; - }; - - template - ETL_CONSTANT bool atomic_traits::is_always_lock_free; - - //*************************************************************************** - /// For all types except bool and pointers - //*************************************************************************** - template ::value> - class atomic : public atomic_traits - { - public: - - ETL_STATIC_ASSERT(etl::is_integral::value, "Only integral types are supported"); - - atomic() - : value(0) - { - } - - atomic(T v) - : value(v) - { - } - - // Assignment - T operator =(T v) - { - store(v); - - return v; - } - - T operator =(T v) volatile - { - store(v); - - return v; - } - - // Pre-increment - T operator ++() - { - return __sync_add_and_fetch(&value, 1); - } - - T operator ++() volatile - { - return __sync_add_and_fetch(&value, 1); - } - - // Post-increment - T operator ++(int) - { - return __sync_fetch_and_add(&value, 1); - } - - T operator ++(int) volatile - { - return __sync_fetch_and_add(&value, 1); - } - - // Pre-decrement - T operator --() - { - return __sync_sub_and_fetch(&value, 1); - } - - T operator --() volatile - { - return __sync_sub_and_fetch(&value, 1); - } - - // Post-decrement - T operator --(int) - { - return __sync_fetch_and_sub(&value, 1); - } - - T operator --(int) volatile - { - return __sync_fetch_and_sub(&value, 1); - } - - // Add - T operator +=(T v) - { - return __sync_fetch_and_add(&value, v); - } - - T operator +=(T v) volatile - { - return __sync_fetch_and_add(&value, v); - } - - // Subtract - T operator -=(T v) - { - return __sync_fetch_and_sub(&value, v); - } - - T operator -=(T v) volatile - { - return __sync_fetch_and_sub(&value, v); - } - - // And - T operator &=(T v) - { - return __sync_fetch_and_and(&value, v); - } - - T operator &=(T v) volatile - { - return __sync_fetch_and_and(&value, v); - } - - // Or - T operator |=(T v) - { - return __sync_fetch_and_or(&value, v); - } - - T operator |=(T v) volatile - { - return __sync_fetch_and_or(&value, v); - } - - // Exclusive or - T operator ^=(T v) - { - return __sync_fetch_and_xor(&value, v); - } - - T operator ^=(T v) volatile - { - return __sync_fetch_and_xor(&value, v); - } - - // Conversion operator - operator T () const - { - return __sync_fetch_and_add(&value, 0); - } - - operator T() volatile const - { - return __sync_fetch_and_add(&value, 0); - } - - // Is lock free? - bool is_lock_free() const - { - return true; - } - - bool is_lock_free() const volatile - { - return true; - } - - // Store - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - (void)__sync_lock_test_and_set(&value, v); - } - - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - (void)__sync_lock_test_and_set(&value, v); - } - - // Load - T load(etl::memory_order order = etl::memory_order_seq_cst) const - { - (void)order; - return __sync_fetch_and_add(&value, 0); - } - - T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - (void)order; - return __sync_fetch_and_add(&value, 0); - } - - // Fetch add - T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - return __sync_fetch_and_add(&value, v); - } - - T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - return __sync_fetch_and_add(&value, v); - } - - // Fetch subtract - T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - return __sync_fetch_and_sub(&value, v); - } - - T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - return __sync_fetch_and_sub(&value, v); - } - - // Fetch or - T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - return __sync_fetch_and_or(&value, v); - } - - T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - return __sync_fetch_and_or(&value, v); - } - - // Fetch and - T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - return __sync_fetch_and_and(&value, v); - } - - T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - return __sync_fetch_and_and(&value, v); - } - - // Fetch exclusive or - T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - return __sync_fetch_and_xor(&value, v); - } - - T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - return __sync_fetch_and_xor(&value, v); - } - - // Exchange - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - return __sync_lock_test_and_set(&value, v); - } - - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - return __sync_lock_test_and_set(&value, v); - } - - // Compare exchange weak - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - 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 order = etl::memory_order_seq_cst) volatile - { - (void)order; - 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) - { - (void)success; - (void)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 - { - (void)success; - (void)failure; - 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, etl::memory_order order = etl::memory_order_seq_cst) - { - (void)order; - 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 order = etl::memory_order_seq_cst) volatile - { - (void)order; - 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) - { - (void)success; - (void)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 - { - (void)success; - (void)failure; - T old = expected; - - while (!compare_exchange_weak(old, desired)) - { - if (memcmp(&old, &expected, sizeof(T))) - { - expected = old; - return false; - } - } - - return true; - } - - private: - - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; - - mutable volatile T value; - }; - - //*************************************************************************** - /// Specialisation for pointers - //*************************************************************************** - template - class atomic : public atomic_traits - { - public: - - atomic() - : value(0U) - { - } - - atomic(T* v) - : value(uintptr_t(v)) - { - } - - // Assignment - T* operator =(T* v) - { - store(v); - - return v; - } - - T* operator =(T* v) volatile - { - store(v); - - return v; - } - - // Pre-increment - T* operator ++() - { - return reinterpret_cast(__sync_add_and_fetch(&value, sizeof(T))); - } - - T* operator ++() volatile - { - return reinterpret_cast(__sync_add_and_fetch(&value, sizeof(T))); - } - - // Post-increment - T* operator ++(int) - { - return reinterpret_cast(__sync_fetch_and_add(&value, sizeof(T))); - } - - T* operator ++(int) volatile - { - return reinterpret_cast(__sync_fetch_and_add(&value, sizeof(T))); - } - - // Pre-decrement - T* operator --() - { - return reinterpret_cast(__sync_sub_and_fetch(&value, sizeof(T))); - } - - T* operator --() volatile - { - return reinterpret_cast(__sync_sub_and_fetch(&value, sizeof(T))); - } - - // Post-decrement - T* operator --(int) - { - return reinterpret_cast(__sync_fetch_and_sub(&value, sizeof(T))); - } - - T* operator --(int) volatile - { - return reinterpret_cast(__sync_fetch_and_sub(&value, sizeof(T))); - } - - // Add - T* operator +=(ptrdiff_t v) - { - return reinterpret_cast(__sync_fetch_and_add(&value, v * sizeof(T))); - } - - T* operator +=(ptrdiff_t v) volatile - { - return reinterpret_cast(__sync_fetch_and_add(&value, v * sizeof(T))); - } - - // Subtract - T* operator -=(ptrdiff_t v) - { - return reinterpret_cast(__sync_fetch_and_sub(&value, v * sizeof(T))); - } - - T* operator -=(ptrdiff_t v) volatile - { - return reinterpret_cast(__sync_fetch_and_sub(&value, v * sizeof(T))); - } - - // Conversion operator - operator T* () const - { - return reinterpret_cast(__sync_fetch_and_add(&value, 0)); - } - - operator T* () volatile const - { - return reinterpret_cast(__sync_fetch_and_add(&value, 0)); - } - - // Is lock free? - bool is_lock_free() const - { - return true; - } - - bool is_lock_free() const volatile - { - return true; - } - - // Store - void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) - { - __sync_lock_test_and_set(&value, uintptr_t(v)); - } - - void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - __sync_lock_test_and_set(&value, uintptr_t(v)); - } - - // Load - T* load(etl::memory_order order = etl::memory_order_seq_cst) const - { - return reinterpret_cast(__sync_fetch_and_add(&value, 0)); - } - - T* load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - return reinterpret_cast(__sync_fetch_and_add(&value, 0)); - } - - // Fetch add - T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) - { - return reinterpret_cast(__sync_fetch_and_add(&value, v)); - } - - T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return reinterpret_cast(__sync_fetch_and_add(&value, v)); - } - - // Fetch subtract - T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) - { - return reinterpret_cast(__sync_fetch_and_sub(&value, v)); - } - - T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return reinterpret_cast(__sync_fetch_and_sub(&value, v)); - } - - // Exchange - T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) - { - return reinterpret_cast(__sync_lock_test_and_set(&value, uintptr_t(v))); - } - - T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return reinterpret_cast(__sync_lock_test_and_set(&value, uintptr_t(v))); - } - - // Compare exchange weak - bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) - { - T* old = reinterpret_cast(__sync_val_compare_and_swap(&value, uintptr_t(expected), uintptr_t(desired))); - - if (old == expected) - { - return true; - } - else - { - expected = old; - return false; - } - } - - bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - T* old = reinterpret_cast(__sync_val_compare_and_swap(&value, uintptr_t(expected), uintptr_t(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 = reinterpret_cast(__sync_val_compare_and_swap(&value, uintptr_t(expected), uintptr_t(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 = reinterpret_cast(__sync_val_compare_and_swap(&value, uintptr_t(expected), uintptr_t(desired))); - - if (old == expected) - { - return true; - } - else - { - expected = old; - return false; - } - } - - // Compare exchange strong - bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) - { - 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 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; - - while (!compare_exchange_weak(old, desired)) - { - if (memcmp(&old, &expected, sizeof(T*))) - { - expected = old; - return false; - } - } - - return true; - } - - private: - - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; - - mutable uintptr_t value; - }; - - //*************************************************************************** - /// Specialisation for bool - //*************************************************************************** - template <> - class atomic : public atomic_traits - { - public: - - atomic() - : value(0U) - { - } - - atomic(bool v) - : value(char(v)) - { - } - - // Assignment - bool operator =(bool v) - { - store(v); - - return v; - } - - bool operator =(bool v) volatile - { - store(v); - - return v; - } - - // Conversion operator - operator bool() const - { - return static_cast(__sync_fetch_and_add(&value, 0)); - } - - operator bool() volatile const - { - return static_cast(__sync_fetch_and_add(&value, 0)); - } - - // Is lock free? - bool is_lock_free() const - { - return true; - } - - bool is_lock_free() const volatile - { - return true; - } - - // Store - void store(bool v, etl::memory_order order = etl::memory_order_seq_cst) - { - __sync_lock_test_and_set(&value, char(v)); - } - - void store(bool v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - __sync_lock_test_and_set(&value, char(v)); - } - - // Load - bool load(etl::memory_order order = etl::memory_order_seq_cst) const - { - return static_cast(__sync_fetch_and_add(&value, 0)); - } - - bool load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - return static_cast(__sync_fetch_and_add(&value, 0)); - } - - // Exchange - bool exchange(bool v, etl::memory_order order = etl::memory_order_seq_cst) - { - return static_cast(__sync_lock_test_and_set(&value, char(v))); - } - - bool exchange(bool v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return static_cast(__sync_lock_test_and_set(&value, char(v))); - } - - // Compare exchange weak - bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) - { - bool old = static_cast(__sync_val_compare_and_swap(&value, char(expected), char(desired))); - - if (old == expected) - { - return true; - } - else - { - expected = old; - return false; - } - } - - bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - bool old = static_cast(__sync_val_compare_and_swap(&value, char(expected), char(desired))); - - if (old == expected) - { - return true; - } - else - { - expected = old; - return false; - } - } - - bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) - { - bool old = static_cast(__sync_val_compare_and_swap(&value, char(expected), char(desired))); - - if (old == expected) - { - return true; - } - else - { - expected = old; - return false; - } - } - - bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) volatile - { - bool old = static_cast(__sync_val_compare_and_swap(&value, char(expected), char(desired))); - - if (old == expected) - { - return true; - } - else - { - expected = old; - return false; - } - } - - // Compare exchange strong - bool compare_exchange_strong(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) - { - bool old = expected; - - while (!compare_exchange_weak(old, desired)) - { - if (memcmp(&old, &expected, sizeof(bool))) - { - expected = old; - return false; - } - } - - return true; - } - - bool compare_exchange_strong(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - bool old = expected; - - while (!compare_exchange_weak(old, desired)) - { - if (memcmp(&old, &expected, sizeof(bool))) - { - expected = old; - return false; - } - } - - return true; - } - - bool compare_exchange_strong(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) - { - bool old = expected; - - while (!compare_exchange_weak(old, desired)) - { - if (memcmp(&old, &expected, sizeof(bool))) - { - expected = old; - return false; - } - } - - return true; - } - - bool compare_exchange_strong(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) volatile - { - bool old = expected; - - while (!compare_exchange_weak(old, desired)) - { - if (memcmp(&old, &expected, sizeof(bool))) - { - expected = old; - return false; - } - } - - return true; - } - - private: - - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; - - mutable char value; - }; - - //*************************************************************************** - /// Specialisation for type that are not integral, pointer or bool. - /// Uses a mutex to control access. - //*************************************************************************** - template - class atomic : public atomic_traits - { - public: - - atomic() - : flag(0) - , value(T()) - { - } - - atomic(T v) - : flag(0) - , value(v) - { - } - - // Assignment - T operator =(T v) - { - store(v); - - return v; - } - - T operator =(T v) volatile - { - store(v); - - return v; - } - - // Conversion operator - operator T () const - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - operator T() volatile const - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - // Is lock free? - bool is_lock_free() const - { - return false; - } - - bool is_lock_free() const volatile - { - return false; - } - - // Store - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - ETL_BUILTIN_LOCK; - value = v; - ETL_BUILTIN_UNLOCK; - } - - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - ETL_BUILTIN_LOCK; - value = v; - ETL_BUILTIN_UNLOCK; - } - - // Load - T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - // Load - T load(etl::memory_order order = etl::memory_order_seq_cst) const - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - // Exchange - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) - { - ETL_BUILTIN_LOCK; - T result = value; - value = v; - ETL_BUILTIN_UNLOCK; - - return result; - } - - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - ETL_BUILTIN_LOCK; - T result = value; - value = v; - ETL_BUILTIN_UNLOCK; - - return result; - } - - // Compare exchange weak - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) - { - bool result; - - ETL_BUILTIN_LOCK; - if (memcmp(&value, &expected, sizeof(T)) == 0) - { - value = desired; - result = true; - } - else - { - result = false; - } - ETL_BUILTIN_UNLOCK; - - return result; - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - bool result; - - ETL_BUILTIN_LOCK; - if (memcmp(&value, &expected, sizeof(T)) == 0) - { - value = desired; - result = true; - } - else - { - result = false; - } - ETL_BUILTIN_UNLOCK; - - return result; - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) - { - return compare_exchange_weak(expected, desired); - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - return compare_exchange_weak(expected, desired); - } - - // Compare exchange strong - bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) - { - return compare_exchange_weak(expected, desired); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return compare_exchange_weak(expected, desired); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) - { - return compare_exchange_weak(expected, desired); - } - - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - return compare_exchange_weak(expected, desired); - } - - private: - - mutable char flag; - mutable T value; - }; - -#undef ETL_SYNC_BUILTIN_LOCK -#undef ETL_SYNC_BUILTIN_UNLOCK - -#endif - - typedef etl::atomic atomic_bool; - typedef etl::atomic atomic_char; - typedef etl::atomic atomic_schar; - typedef etl::atomic atomic_uchar; - typedef etl::atomic atomic_short; - typedef etl::atomic atomic_ushort; - typedef etl::atomic atomic_int; - typedef etl::atomic atomic_uint; - typedef etl::atomic atomic_long; - typedef etl::atomic atomic_ulong; - typedef etl::atomic atomic_llong; - typedef etl::atomic atomic_ullong; - typedef etl::atomic atomic_wchar_t; -#if ETL_HAS_NATIVE_CHAR8_T - typedef etl::atomic atomic_char8_t; -#endif -#if ETL_HAS_NATIVE_CHAR16_T - typedef etl::atomic atomic_char16_t; -#endif -#if ETL_HAS_NATIVE_CHAR32_T - typedef etl::atomic atomic_char32_t; -#endif -#if ETL_USING_8BIT_TYPES - typedef etl::atomic atomic_uint8_t; - typedef etl::atomic atomic_int8_t; -#endif - typedef etl::atomic atomic_uint16_t; - typedef etl::atomic atomic_int16_t; - typedef etl::atomic atomic_uint32_t; - typedef etl::atomic atomic_int32_t; -#if ETL_USING_64BIT_TYPES - typedef etl::atomic atomic_uint64_t; - typedef etl::atomic atomic_int64_t; -#endif - typedef etl::atomic atomic_int_least8_t; - typedef etl::atomic atomic_uint_least8_t; - typedef etl::atomic atomic_int_least16_t; - typedef etl::atomic atomic_uint_least16_t; - typedef etl::atomic atomic_int_least32_t; - typedef etl::atomic atomic_uint_least32_t; -#if ETL_USING_64BIT_TYPES - typedef etl::atomic atomic_int_least64_t; - typedef etl::atomic atomic_uint_least64_t; -#endif - typedef etl::atomic atomic_int_fast8_t; - typedef etl::atomic atomic_uint_fast8_t; - typedef etl::atomic atomic_int_fast16_t; - typedef etl::atomic atomic_uint_fast16_t; - typedef etl::atomic atomic_int_fast32_t; - typedef etl::atomic atomic_uint_fast32_t; -#if ETL_USING_64BIT_TYPES - typedef etl::atomic atomic_int_fast64_t; - typedef etl::atomic atomic_uint_fast64_t; -#endif - typedef etl::atomic atomic_intptr_t; - typedef etl::atomic atomic_uintptr_t; - typedef etl::atomic atomic_size_t; - typedef etl::atomic atomic_ptrdiff_t; - typedef etl::atomic atomic_intmax_t; - typedef etl::atomic atomic_uintmax_t; -} - -#endif - diff --git a/include/etl/memory.h b/include/etl/memory.h index 83e9a200..e16c043e 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -2196,60 +2196,79 @@ namespace etl static ETL_CONSTANT size_t Alignment = etl::alignment_of::value; /// Index operator. - T& operator [](int i) + /// Warning: The element may not be initialised. + reference operator [](int i) { - return reinterpret_cast(this->raw)[i]; + return reinterpret_cast(this->raw)[i]; } /// Index operator. - const T& operator [](int i) const + /// Warning: The element may not be initialised. + const_reference operator [](int i) const { - return reinterpret_cast(this->raw)[i]; + return reinterpret_cast(this->raw)[i]; } /// Convert to T reference. - operator T& () + operator reference () { - return *reinterpret_cast(raw); + return *reinterpret_cast(raw); } /// Convert to const T reference. - operator const T& () const + operator const_reference () const { - return *reinterpret_cast(raw); + return *reinterpret_cast(raw); } /// Convert to T pointer. - operator T* () - + operator pointer () { - return reinterpret_cast(raw); + return reinterpret_cast(raw); } /// Convert to const T pointer. - operator const T* () const + operator const_pointer () const { - return reinterpret_cast(raw); + return reinterpret_cast(raw); } - T* begin() + /// Get an iterator to the first element. + /// Warning: The element may not be initialised. + iterator begin() { - return reinterpret_cast(raw); + return reinterpret_cast(raw); } - const T* begin() const + /// Get a const iterator to the first element. + /// Warning: The element may not be initialised. + const_iterator begin() const { - return reinterpret_cast(raw); + return reinterpret_cast(raw); } - T* end() + /// Get an iterator to one past the last element. + iterator end() { - return reinterpret_cast(raw + (sizeof(T) * N_Objects)); + return reinterpret_cast(raw + (sizeof(T) * N_Objects)); } - const T* end() const + /// Get a const iterator to one past the last element. + const_iterator end() const { - return reinterpret_cast(raw + (sizeof(T) * N_Objects)); + return reinterpret_cast(raw + (sizeof(T) * N_Objects)); + } + + /// Get a char* to the raw storage data. + char* data() + { + return raw; + } + + /// Get a const char* to the raw storage data. + const char* data() const + { + return raw; } #if ETL_USING_CPP11 && !defined(ETL_COMPILER_ARM5) && !defined(ETL_UNINITIALIZED_BUFFER_FORCE_CPP03_IMPLEMENTATION) diff --git a/test/test_atomic.cpp b/test/test_atomic.cpp index 572a9b47..78a8147a 100644 --- a/test/test_atomic.cpp +++ b/test/test_atomic.cpp @@ -33,10 +33,14 @@ SOFTWARE. #if defined(ETL_COMPILER_MICROSOFT) #include "etl/atomic/atomic_std.h" +#elif defined(ETL_COMPILER_ARM5) + #include "atomic/atomic_arm.h" +#elif defined(ETL_COMPILER_ARM6) + #include "atomic/atomic_arm.h" #elif defined(ETL_COMPILER_GCC) - #include "etl/atomic/atomic_gcc_sync.h" + #include "etl/atomic/atomic_gcc.h" #elif defined(ETL_COMPILER_CLANG) - #include "etl/atomic/atomic_clang_sync.h" + #include "etl/atomic/atomic_clang.h" #endif #include @@ -76,10 +80,10 @@ namespace CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free()); -//#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC -// CHECK_TRUE(etl::atomic::is_always_lock_free); -// CHECK_TRUE(test.is_always_lock_free); -//#endif +#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC + CHECK_TRUE(etl::atomic::is_always_lock_free); + CHECK_TRUE(test.is_always_lock_free); +#endif } //************************************************************************* @@ -96,22 +100,57 @@ namespace #endif } -//#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC -// //************************************************************************* -// TEST(test_atomic_is_always_lock_free) -// { -// struct S -// { -// int a; -// int b; -// int c; -// }; -// -// CHECK_TRUE(etl::atomic::is_always_lock_free); -// CHECK_TRUE(etl::atomic::is_always_lock_free); -// CHECK_FALSE(etl::atomic::is_always_lock_free); -// } -//#endif + //************************************************************************* + TEST(test_atomic_float_is_lock_free) + { + std::atomic compare; + etl::atomic test; + + CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free()); + +#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC + CHECK_TRUE(etl::atomic::is_always_lock_free); + CHECK_TRUE(test.is_always_lock_free); +#endif + } + + //************************************************************************* + TEST(test_atomic_double_is_lock_free) + { + std::atomic compare; + etl::atomic test; + + CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free()); + +#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC + CHECK_TRUE(etl::atomic::is_always_lock_free); + CHECK_TRUE(test.is_always_lock_free); +#endif + } + +#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC + //************************************************************************* + TEST(test_atomic_is_always_lock_free) + { + struct S + { + char a; + char b; + short c; + int d; + }; + + constexpr bool ialf_int = etl::atomic::is_always_lock_free; + constexpr bool ialf_pint = etl::atomic::is_always_lock_free; + constexpr bool ialf_s = etl::atomic::is_always_lock_free; + constexpr bool ialf_double = etl::atomic::is_always_lock_free; + + CHECK_TRUE(ialf_int); + CHECK_TRUE(ialf_pint); + CHECK_TRUE(ialf_s); + CHECK_TRUE(ialf_double); + } +#endif //************************************************************************* TEST(test_atomic_integer_load) @@ -151,6 +190,144 @@ namespace CHECK_EQUAL(compare.load(), test.load()); } + //************************************************************************* + TEST(test_atomic_float_load) + { + std::atomic compare(1.23f); + etl::atomic test(1.23f); + + CHECK_EQUAL(compare.load(), test.load()); + } + + //************************************************************************* + TEST(test_atomic_double_load) + { + std::atomic compare(1.23); + etl::atomic test(1.23); + + CHECK_EQUAL(compare.load(), test.load()); + } + + //************************************************************************* + TEST(test_atomic_struct_load) + { + struct S + { + char a; + char b; + short c; + int d; + }; + + S s1 = { char(0xA5), char(0x5A), short(0x55AA), int(0xFF5511AA) }; + + etl::atomic test(s1); + + S s2 = test.load(); + + CHECK_EQUAL(s1.a, s2.a); + CHECK_EQUAL(s1.b, s2.b); + CHECK_EQUAL(s1.c, s2.c); + CHECK_EQUAL(s1.d, s2.d); + } + + //************************************************************************* + TEST(test_atomic_integer_implicit_conversion) + { + std::atomic compare(1); + etl::atomic test(1); + + int c = compare; + int t = test; + + CHECK_EQUAL(c, t); + } + + //************************************************************************* + TEST(test_atomic_enum_implicit_conversion) + { + std::atomic compare(Enum::One); + etl::atomic test(Enum::One); + + Enum c = compare; + Enum t = test; + + CHECK_EQUAL(c, t); + } + + //************************************************************************* + TEST(test_atomic_pointer_implicit_conversion) + { + int i; + + std::atomic compare(&i); + etl::atomic test(&i); + + int* c = compare; + int* t = test; + + CHECK_EQUAL(c, t); + } + + //************************************************************************* + TEST(test_atomic_bool_implicit_conversion) + { + std::atomic compare(true); + etl::atomic test(true); + + bool c = compare; + bool t = test; + + CHECK_EQUAL(c, t); + } + + //************************************************************************* + TEST(test_atomic_float_implicit_conversion) + { + std::atomic compare(1.23f); + etl::atomic test(1.23f); + + float c = compare; + float t = test; + + CHECK_EQUAL(c, t); + } + + //************************************************************************* + TEST(test_atomic_double_implicit_conversion) + { + std::atomic compare(1.23); + etl::atomic test(1.23); + + double c = compare; + double t = test; + + CHECK_EQUAL(c, t); + } + + //************************************************************************* + TEST(test_atomic_struct_implicit_conversion) + { + struct S + { + char a; + char b; + short c; + int d; + }; + + S s1 = { char(0xA5), char(0x5A), short(0x55AA), int(0xFF5511AA) }; + + etl::atomic test(s1); + + S s2 = test; + + CHECK_EQUAL(s1.a, s2.a); + CHECK_EQUAL(s1.b, s2.b); + CHECK_EQUAL(s1.c, s2.c); + CHECK_EQUAL(s1.d, s2.d); + } + //************************************************************************* TEST(test_atomic_integer_store) { @@ -198,6 +375,52 @@ namespace CHECK_EQUAL(compare.load(), test.load()); } + //************************************************************************* + TEST(test_atomic_float_store) + { + std::atomic compare(1.23f); + etl::atomic test(1.23f); + + compare.store(1.23f); + test.store(1.23f); + CHECK_EQUAL(compare.load(), test.load()); + } + + //************************************************************************* + TEST(test_atomic_double_store) + { + std::atomic compare(1.23); + etl::atomic test(1.23); + + compare.store(1.23); + test.store(1.23); + CHECK_EQUAL(compare.load(), test.load()); + } + + //************************************************************************* + TEST(test_atomic_struct_store) + { + struct S + { + char a; + char b; + short c; + int d; + }; + + S s1 = { char(0xA5), char(0x5A), short(0x55AA), int(0xFF5511AA) }; + + etl::atomic test; + test.store(s1); + + S s2 = test.load(); + + CHECK_EQUAL(s1.a, s2.a); + CHECK_EQUAL(s1.b, s2.b); + CHECK_EQUAL(s1.c, s2.c); + CHECK_EQUAL(s1.d, s2.d); + } + //************************************************************************* TEST(test_atomic_integer_assignment) { @@ -245,6 +468,53 @@ namespace CHECK_EQUAL(compare.load(), test.load()); } + //************************************************************************* + TEST(test_atomic_float_assignment) + { + std::atomic compare(1.23f); + etl::atomic test(1.23f); + + compare = 1.23f; + test = 1.23f; + CHECK_EQUAL(compare.load(), test.load()); + } + + //************************************************************************* + TEST(test_atomic_double_assignment) + { + std::atomic compare(1.23f); + etl::atomic test(1.23f); + + compare = 1.23f; + test = 1.23f; + CHECK_EQUAL(compare.load(), test.load()); + } + + //************************************************************************* + TEST(test_atomic_struct_assignment) + { + struct S + { + char a; + char b; + short c; + int d; + }; + + S s1 = { char(0x00), char(0x00), 0x0000, 0x00000000 }; + S s2 = { char(0xA5), char(0x5A), short(0x55AA), int(0xFF5511AA) }; + + etl::atomic test(s1); + test = s2; + + S s3 = test.load(); + + CHECK_EQUAL(s2.a, s3.a); + CHECK_EQUAL(s2.b, s3.b); + CHECK_EQUAL(s2.c, s3.c); + CHECK_EQUAL(s2.d, s3.d); + } + //************************************************************************* TEST(test_atomic_operator_integer_pre_increment) { @@ -528,7 +798,37 @@ namespace } //************************************************************************* - TEST(test_atomic_compare_exchange_weak_fail) + TEST(test_atomic_struct_exchange) + { + struct S + { + char a; + char b; + short c; + int d; + }; + + S s1 = { char(0x00), char(0x00), 0x0000, 0x00000000 }; + S s2 = { char(0xA5), char(0x5A), short(0x55AA), int(0xFF5511AA) }; + + etl::atomic test(s1); + + S s3 = test.exchange(s2); + S s4 = test.load(); + + CHECK_EQUAL(s1.a, s3.a); + CHECK_EQUAL(s1.b, s3.b); + CHECK_EQUAL(s1.c, s3.c); + CHECK_EQUAL(s1.d, s3.d); + + CHECK_EQUAL(s2.a, s4.a); + CHECK_EQUAL(s2.b, s4.b); + CHECK_EQUAL(s2.c, s4.c); + CHECK_EQUAL(s2.d, s4.d); + } + + //************************************************************************* + TEST(test_atomic_compare_exchange_weak_fail_for_integer) { std::atomic compare; etl::atomic test; @@ -551,7 +851,7 @@ namespace } //************************************************************************* - TEST(test_atomic_compare_exchange_weak_pass) + TEST(test_atomic_compare_exchange_weak_pass_for_integer) { std::atomic compare; etl::atomic test; @@ -620,7 +920,87 @@ namespace } //************************************************************************* - TEST(test_atomic_compare_exchange_strong_fail) + TEST(test_atomic_compare_exchange_weak_pass_for_float) + { + std::atomic compare; + etl::atomic test; + + float actual = 1.23f; + + compare = actual; + test = actual; + + float compare_expected = actual; + float test_expected = actual; + float desired = 2.34f; + + 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_for_double) + { + std::atomic compare; + etl::atomic test; + + double actual = 1.23; + + compare = actual; + test = actual; + + double compare_expected = actual; + double test_expected = actual; + double desired = 2.34; + + 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_for_struct) + { + struct S + { + char a; + char b; + short c; + int d; + }; + + S s1 = { char(0x00), char(0x00), 0x0000, 0x00000000 }; + S s2 = { char(0xA5), char(0x5A), short(0x55AA), int(0xFF5511AA) }; + + etl::atomic test; + + S actual = s1; + test = actual; + + S test_expected = actual; + S desired = s2; + + bool test_result = test.compare_exchange_weak(test_expected, desired); + + S result = test.load(); + + CHECK_TRUE(test_result); + CHECK_EQUAL(result.a, desired.a); + CHECK_EQUAL(result.b, desired.b); + CHECK_EQUAL(result.c, desired.c); + CHECK_EQUAL(result.d, desired.d); + + } + + //************************************************************************* + TEST(test_atomic_compare_exchange_strong_fail_for_integer) { std::atomic compare; etl::atomic test; @@ -643,7 +1023,7 @@ namespace } //************************************************************************* - TEST(test_atomic_compare_exchange_strong_pass) + TEST(test_atomic_compare_exchange_strong_pass_for_integer) { std::atomic compare; etl::atomic test; @@ -711,6 +1091,52 @@ namespace CHECK_EQUAL(compare.load(), test.load()); } + //************************************************************************* + TEST(test_atomic_compare_exchange_strong_pass_for_float) + { + std::atomic compare; + etl::atomic test; + + float actual = 1.23f; + + compare = actual; + test = actual; + + float compare_expected = actual; + float test_expected = actual; + float desired = 2.34f; + + 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_for_double) + { + std::atomic compare; + etl::atomic test; + + double actual = 1.23; + + compare = actual; + test = actual; + + double compare_expected = actual; + double test_expected = actual; + double desired = 2.34f; + + 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()); + } + //************************************************************************* #if REALTIME_TEST diff --git a/test/vs2022/etl.sln b/test/vs2022/etl.sln index 3b5f836e..71e21f61 100644 --- a/test/vs2022/etl.sln +++ b/test/vs2022/etl.sln @@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "etl", "etl.vcxproj", "{C21D EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug Clang C++20|Win32 = Debug Clang C++20|Win32 + Debug Clang C++20|x64 = Debug Clang C++20|x64 Debug MSVC C++ 20 - No Tests|Win32 = Debug MSVC C++ 20 - No Tests|Win32 Debug MSVC C++ 20 - No Tests|x64 = Debug MSVC C++ 20 - No Tests|x64 Debug MSVC C++14 - No STL|Win32 = Debug MSVC C++14 - No STL|Win32 @@ -33,6 +35,10 @@ Global Release MSVC C++20 - Optimised O2|x64 = Release MSVC C++20 - Optimised O2|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Clang C++20|Win32.ActiveCfg = Debug Clang C++20|Win32 + {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Clang C++20|Win32.Build.0 = Debug Clang C++20|Win32 + {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Clang C++20|x64.ActiveCfg = Debug Clang C++20|x64 + {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Clang C++20|x64.Build.0 = Debug Clang C++20|x64 {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++ 20 - No Tests|Win32.ActiveCfg = Debug MSVC C++ 20 - No Tests|Win32 {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++ 20 - No Tests|Win32.Build.0 = Debug MSVC C++ 20 - No Tests|Win32 {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++ 20 - No Tests|x64.ActiveCfg = Debug MSVC C++ 20 - No Tests|x64 diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 0ed83920..518695e6 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -1,6 +1,14 @@  + + Debug Clang C++20 + Win32 + + + Debug Clang C++20 + x64 + Debug MSVC C++ 20 - No Tests Win32 @@ -135,6 +143,13 @@ Unicode false + + Application + true + ClangCL + Unicode + false + Application true @@ -375,6 +390,12 @@ v143 Unicode + + Application + true + v143 + Unicode + Application true @@ -629,6 +650,9 @@ + + + @@ -737,6 +761,9 @@ + + + @@ -870,6 +897,11 @@ true $(Configuration)\ + + true + true + $(Configuration)\ + true true @@ -1053,6 +1085,10 @@ true true + + true + true + true true @@ -1289,6 +1325,32 @@ "$(OutDir)\etl.exe" + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ../../../unittest-cpp/;../../include;../../test + + + true + stdcpp20 + EditAndContinue + /Zc:__cplusplus %(AdditionalOptions) + true + EnableFastChecks + false + + + Console + true + + + "$(OutDir)\etl.exe" + + @@ -2175,6 +2237,27 @@ $(OutDir)\etl.exe + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ../../unittest-cpp/UnitTest++/;../../include/etl;../../test + + + false + stdcpp14 + + + Console + true + + + $(OutDir)\etl.exe + + @@ -3007,8 +3090,8 @@ - - + + @@ -3354,6 +3437,7 @@ true + true true true true @@ -3371,6 +3455,7 @@ true true true + true true true true @@ -3409,6 +3494,7 @@ true true true + true true true true @@ -3447,6 +3533,7 @@ true true true + true true true true @@ -3485,6 +3572,7 @@ true true true + true true true true @@ -3565,6 +3653,7 @@ true + true true true true @@ -3580,6 +3669,7 @@ true + true true true true @@ -3597,6 +3687,7 @@ true true true + true true true true @@ -3635,6 +3726,7 @@ true true true + true true true true @@ -3673,6 +3765,7 @@ true true true + true true true true @@ -3711,6 +3804,7 @@ true true true + true true true true @@ -3749,6 +3843,7 @@ true + true true true true @@ -3764,6 +3859,7 @@ true + true true true true @@ -3779,6 +3875,7 @@ true + true true true true @@ -3794,6 +3891,7 @@ true + true true true true @@ -3809,6 +3907,7 @@ true + true true true true @@ -3824,6 +3923,7 @@ true + true true true true @@ -3839,6 +3939,7 @@ true + true true true true @@ -3854,6 +3955,7 @@ true + true true true true @@ -3869,6 +3971,7 @@ true + true true true true @@ -3882,6 +3985,7 @@ true true true + true true true true @@ -3897,6 +4001,7 @@ true + true true true true @@ -3910,6 +4015,7 @@ true true true + true true true true @@ -3925,6 +4031,7 @@ true + true true true true @@ -3940,6 +4047,7 @@ true + true true true true @@ -3955,6 +4063,7 @@ true + true true true true @@ -3970,6 +4079,7 @@ true + true true true true @@ -3985,6 +4095,7 @@ true + true true true true @@ -4000,6 +4111,7 @@ true + true true true true @@ -4015,6 +4127,7 @@ true + true true true true @@ -4028,6 +4141,7 @@ true true true + true true true true @@ -4043,6 +4157,7 @@ true + true true true true @@ -4058,6 +4173,7 @@ true + true true true true @@ -4073,6 +4189,7 @@ true + true true true true @@ -4088,6 +4205,7 @@ true + true true true true @@ -4103,6 +4221,7 @@ true + true true true true @@ -4118,6 +4237,7 @@ true + true true true true @@ -4133,6 +4253,7 @@ true + true true true true @@ -4148,6 +4269,7 @@ true + true true true true @@ -4163,6 +4285,7 @@ true + true true true true @@ -4178,6 +4301,7 @@ true + true true true true @@ -4193,6 +4317,7 @@ true + true true true true @@ -4208,6 +4333,7 @@ true + true true true true @@ -4223,6 +4349,7 @@ true + true true true true @@ -4238,6 +4365,7 @@ true + true true true true @@ -4253,6 +4381,7 @@ true + true true true true @@ -4268,6 +4397,7 @@ true + true true true true @@ -4283,6 +4413,7 @@ true + true true true true @@ -4298,6 +4429,7 @@ true + true true true true @@ -4313,6 +4445,7 @@ true + true true true true @@ -4328,6 +4461,7 @@ true + true true true true @@ -4343,6 +4477,7 @@ true + true true true true @@ -4358,6 +4493,7 @@ true + true true true true @@ -4373,6 +4509,7 @@ true + true true true true @@ -4388,6 +4525,7 @@ true + true true true true @@ -4403,6 +4541,7 @@ true + true true true true @@ -4416,6 +4555,7 @@ true true true + true true true true @@ -4431,6 +4571,7 @@ true + true true true true @@ -4446,6 +4587,7 @@ true + true true true true @@ -4461,6 +4603,7 @@ true + true true true true @@ -4476,6 +4619,7 @@ true + true true true true @@ -4491,6 +4635,7 @@ true + true true true true @@ -4506,6 +4651,7 @@ true + true true true true @@ -4521,6 +4667,7 @@ true + true true true true @@ -4536,6 +4683,7 @@ true + true true true true @@ -4551,6 +4699,7 @@ true + true true true true @@ -4566,6 +4715,7 @@ true + true true true true @@ -4581,6 +4731,7 @@ true + true true true true @@ -4596,6 +4747,7 @@ true + true true true true @@ -4611,6 +4763,7 @@ true + true true true true @@ -4626,6 +4779,7 @@ true + true true true true @@ -4641,6 +4795,7 @@ true + true true true true @@ -4656,6 +4811,7 @@ true + true true true true @@ -4671,6 +4827,7 @@ true + true true true true @@ -4686,6 +4843,7 @@ true + true true true true @@ -4701,6 +4859,7 @@ true + true true true true @@ -4716,6 +4875,7 @@ true + true true true true @@ -4731,6 +4891,7 @@ true + true true true true @@ -4746,6 +4907,7 @@ true + true true true true @@ -4761,6 +4923,7 @@ true + true true true true @@ -4776,6 +4939,7 @@ true + true true true true @@ -4791,6 +4955,7 @@ true + true true true true @@ -4806,6 +4971,7 @@ true + true true true true @@ -4821,6 +4987,7 @@ true + true true true true @@ -4836,6 +5003,7 @@ true + true true true true @@ -4851,6 +5019,7 @@ true + true true true true @@ -4866,6 +5035,7 @@ true + true true true true @@ -4881,6 +5051,7 @@ true + true true true true @@ -4896,6 +5067,7 @@ true + true true true true @@ -4911,6 +5083,7 @@ true + true true true true @@ -4926,6 +5099,7 @@ true + true true true true @@ -4941,6 +5115,7 @@ true + true true true true @@ -4956,6 +5131,7 @@ true + true true true true @@ -4971,6 +5147,7 @@ true + true true true true @@ -4986,6 +5163,7 @@ true + true true true true @@ -5001,6 +5179,7 @@ true + true true true true @@ -5016,6 +5195,7 @@ true + true true true true @@ -5031,6 +5211,7 @@ true + true true true true @@ -5046,6 +5227,7 @@ true + true true true true @@ -5061,6 +5243,7 @@ true + true true true true @@ -5076,6 +5259,7 @@ true + true true true true @@ -5091,6 +5275,7 @@ true + true true true true @@ -5106,6 +5291,7 @@ true + true true true true @@ -5121,6 +5307,7 @@ true + true true true true @@ -5136,6 +5323,7 @@ true + true true true true @@ -5151,6 +5339,7 @@ true + true true true true @@ -5166,6 +5355,7 @@ true + true true true true @@ -5181,6 +5371,7 @@ true + true true true true @@ -5196,6 +5387,7 @@ true + true true true true @@ -5211,6 +5403,7 @@ true + true true true true @@ -5226,6 +5419,7 @@ true + true true true true @@ -5241,6 +5435,7 @@ true + true true true true @@ -5256,6 +5451,7 @@ true + true true true true @@ -5271,6 +5467,7 @@ true + true true true true @@ -5286,6 +5483,7 @@ true + true true true true @@ -5301,6 +5499,7 @@ true + true true true true @@ -5316,6 +5515,7 @@ true + true true true true @@ -5331,6 +5531,7 @@ true + true true true true @@ -5346,6 +5547,7 @@ true + true true true true @@ -5361,6 +5563,7 @@ true + true true true true @@ -5376,6 +5579,7 @@ true + true true true true @@ -5391,6 +5595,7 @@ true + true true true true @@ -5406,6 +5611,7 @@ true + true true true true @@ -5421,6 +5627,7 @@ true + true true true true @@ -5436,6 +5643,7 @@ true + true true true true @@ -5451,6 +5659,7 @@ true + true true true true @@ -5466,6 +5675,7 @@ true + true true true true @@ -5481,6 +5691,7 @@ true + true true true true @@ -5496,6 +5707,7 @@ true + true true true true @@ -5511,6 +5723,7 @@ true + true true true true @@ -5526,6 +5739,7 @@ true + true true true true @@ -5541,6 +5755,7 @@ true + true true true true @@ -5556,6 +5771,7 @@ true + true true true true @@ -5571,6 +5787,7 @@ true + true true true true @@ -5586,6 +5803,7 @@ true + true true true true @@ -5601,6 +5819,7 @@ true + true true true true @@ -5616,6 +5835,7 @@ true + true true true true @@ -5631,6 +5851,7 @@ true + true true true true @@ -5646,6 +5867,7 @@ true + true true true true @@ -5661,6 +5883,7 @@ true + true true true true @@ -5674,6 +5897,7 @@ true true true + true true true true @@ -5689,6 +5913,7 @@ true + true true true true @@ -5704,6 +5929,7 @@ true + true true true true @@ -5719,6 +5945,7 @@ true + true true true true @@ -5734,6 +5961,7 @@ true + true true true true @@ -5749,6 +5977,7 @@ true + true true true true @@ -5764,6 +5993,7 @@ true + true true true true @@ -5779,6 +6009,7 @@ true + true true true true @@ -5794,6 +6025,7 @@ true + true true true true @@ -5809,6 +6041,7 @@ true + true true true true @@ -5824,6 +6057,7 @@ true + true true true true @@ -5839,6 +6073,7 @@ true + true true true true @@ -5854,6 +6089,7 @@ true + true true true true @@ -5869,6 +6105,7 @@ true + true true true true @@ -5884,6 +6121,7 @@ true + true true true true @@ -5899,6 +6137,7 @@ true + true true true true @@ -5914,6 +6153,7 @@ true + true true true true @@ -5929,6 +6169,7 @@ true + true true true true @@ -5944,6 +6185,7 @@ true + true true true true @@ -5959,6 +6201,7 @@ true + true true true true @@ -5974,6 +6217,7 @@ true + true true true true @@ -5989,6 +6233,7 @@ true + true true true true @@ -6004,6 +6249,7 @@ true + true true true true @@ -6019,6 +6265,7 @@ true + true true true true @@ -6034,6 +6281,7 @@ true + true true true true @@ -6049,6 +6297,7 @@ true + true true true true @@ -6064,6 +6313,7 @@ true + true true true true @@ -6079,6 +6329,7 @@ true + true true true true @@ -6094,6 +6345,7 @@ true + true true true true @@ -6109,6 +6361,7 @@ true + true true true true @@ -6124,6 +6377,7 @@ true + true true true true @@ -6139,6 +6393,7 @@ true + true true true true @@ -6154,6 +6409,7 @@ true + true true true true @@ -6169,6 +6425,7 @@ true + true true true true @@ -6184,6 +6441,7 @@ true + true true true true @@ -6199,6 +6457,7 @@ true + true true true true @@ -6214,6 +6473,7 @@ true + true true true true @@ -6229,6 +6489,7 @@ true + true true true true @@ -6244,6 +6505,7 @@ true + true true true true @@ -6259,6 +6521,7 @@ true + true true true true @@ -6274,6 +6537,7 @@ true + true true true true @@ -6289,6 +6553,7 @@ true + true true true true @@ -6304,6 +6569,7 @@ true + true true true true @@ -6319,6 +6585,7 @@ true + true true true true @@ -6334,6 +6601,7 @@ true + true true true true @@ -6349,6 +6617,7 @@ true + true true true true @@ -6364,6 +6633,7 @@ true + true true true true @@ -6379,6 +6649,7 @@ true + true true true true @@ -6394,6 +6665,7 @@ true + true true true true @@ -6409,6 +6681,7 @@ true + true true true true @@ -6424,6 +6697,7 @@ true + true true true true @@ -6439,6 +6713,7 @@ true + true true true true @@ -6454,6 +6729,7 @@ true + true true true true @@ -6469,6 +6745,7 @@ true + true true true true @@ -6484,6 +6761,7 @@ true + true true true true @@ -6499,6 +6777,7 @@ true + true true true true @@ -6514,6 +6793,7 @@ true + true true true true @@ -6529,6 +6809,7 @@ true + true true true true @@ -6544,6 +6825,7 @@ true + true true true true @@ -6559,6 +6841,7 @@ true + true true true true @@ -6574,6 +6857,7 @@ true + true true true true @@ -6589,6 +6873,7 @@ true + true true true true @@ -6604,6 +6889,7 @@ true + true true true true @@ -6619,6 +6905,7 @@ true + true true true true @@ -6634,6 +6921,7 @@ true + true true true true @@ -6649,6 +6937,7 @@ true + true true true true @@ -6664,6 +6953,7 @@ true + true true true true @@ -6679,6 +6969,7 @@ true + true true true true @@ -6694,6 +6985,7 @@ true + true true true true @@ -6709,6 +7001,7 @@ true + true true true true @@ -6724,6 +7017,7 @@ true + true true true true @@ -6739,6 +7033,7 @@ true + true true true true @@ -6754,6 +7049,7 @@ true + true true true true @@ -6769,6 +7065,7 @@ true + true true true true @@ -6784,6 +7081,7 @@ true + true true true true @@ -6799,6 +7097,7 @@ true + true true true true @@ -6814,6 +7113,7 @@ true + true true true true @@ -6829,6 +7129,7 @@ true + true true true true @@ -6844,6 +7145,7 @@ true + true true true true @@ -6859,6 +7161,7 @@ true + true true true true @@ -6874,6 +7177,7 @@ true + true true true true @@ -6889,6 +7193,7 @@ true + true true true true @@ -6904,6 +7209,7 @@ true + true true true true @@ -6919,6 +7225,7 @@ true + true true true true @@ -6934,6 +7241,7 @@ true + true true true true @@ -6949,6 +7257,7 @@ true + true true true true @@ -6964,6 +7273,7 @@ true + true true true true @@ -6979,6 +7289,7 @@ true + true true true true @@ -6994,6 +7305,7 @@ true + true true true true @@ -7009,6 +7321,7 @@ true + true true true true @@ -7024,6 +7337,7 @@ true + true true true true @@ -7037,6 +7351,7 @@ true true true + true true true true @@ -7052,6 +7367,7 @@ true + true true true true @@ -7067,6 +7383,7 @@ true + true true true true @@ -7082,6 +7399,7 @@ true + true true true true @@ -7097,6 +7415,7 @@ true + true true true true @@ -7112,6 +7431,7 @@ true + true true true true @@ -7127,6 +7447,7 @@ true + true true true true @@ -7142,6 +7463,7 @@ true + true true true true @@ -7157,6 +7479,7 @@ true + true true true true @@ -7172,6 +7495,7 @@ true + true true true true @@ -7187,6 +7511,7 @@ true + true true true true @@ -7202,6 +7527,7 @@ true + true true true true @@ -7217,6 +7543,7 @@ true + true true true true @@ -7232,6 +7559,7 @@ true + true true true true @@ -7247,6 +7575,7 @@ true + true true true true @@ -7262,6 +7591,7 @@ true + true true true true @@ -7277,6 +7607,7 @@ true + true true true true @@ -7290,6 +7621,7 @@ true true true + true true true true @@ -7305,6 +7637,7 @@ true + true true true true @@ -7320,6 +7653,7 @@ true + true true true true @@ -7335,6 +7669,7 @@ true + true true true true @@ -7350,6 +7685,7 @@ true + true true true true @@ -7365,6 +7701,7 @@ true + true true true true @@ -7380,6 +7717,7 @@ true + true true true true @@ -7395,6 +7733,7 @@ true + true true true true @@ -7410,6 +7749,7 @@ true + true true true true @@ -7425,6 +7765,7 @@ true + true true true true @@ -7440,6 +7781,7 @@ true + true true true true @@ -7455,6 +7797,7 @@ true + true true true true @@ -7470,6 +7813,7 @@ true + true true true true @@ -7485,6 +7829,7 @@ true + true true true true @@ -7500,6 +7845,7 @@ true + true true true true @@ -7515,6 +7861,7 @@ true + true true true true @@ -7530,6 +7877,7 @@ true + true true true true @@ -7545,6 +7893,7 @@ true + true true true true @@ -7560,6 +7909,7 @@ true + true true true true @@ -7575,6 +7925,7 @@ true + true true true true @@ -7590,6 +7941,7 @@ true + true true true true @@ -7605,6 +7957,7 @@ true + true true true true @@ -7620,6 +7973,7 @@ true + true true true true @@ -7635,6 +7989,7 @@ true + true true true true @@ -7650,6 +8005,7 @@ true + true true true true @@ -7665,6 +8021,7 @@ true + true true true true @@ -7680,6 +8037,7 @@ true + true true true true @@ -7695,6 +8053,7 @@ true + true true true true @@ -7710,6 +8069,7 @@ true + true true true true @@ -7725,6 +8085,7 @@ true + true true true true @@ -7740,6 +8101,7 @@ true + true true true true @@ -7755,6 +8117,7 @@ true + true true true true @@ -7770,6 +8133,7 @@ true + true true true true @@ -7785,6 +8149,7 @@ true + true true true true @@ -7800,6 +8165,7 @@ true + true true true true @@ -7815,6 +8181,7 @@ true + true true true true @@ -7830,6 +8197,7 @@ true + true true true true @@ -7845,6 +8213,7 @@ true + true true true true @@ -7860,6 +8229,7 @@ true + true true true true @@ -7875,6 +8245,7 @@ true + true true true true @@ -7890,6 +8261,7 @@ true + true true true true @@ -7905,6 +8277,7 @@ true + true true true true @@ -7920,6 +8293,7 @@ true + true true true true @@ -7935,6 +8309,7 @@ true + true true true true @@ -7950,6 +8325,7 @@ true + true true true true @@ -7965,6 +8341,7 @@ true + true true true true @@ -7980,6 +8357,7 @@ true + true true true true @@ -8002,6 +8380,7 @@ false + false false false false @@ -8166,6 +8545,7 @@ false false false + false false false false @@ -8206,6 +8586,7 @@ false false false + false false false false @@ -8265,6 +8646,7 @@ false false false + false false false false @@ -8305,6 +8687,7 @@ false false false + false false false false @@ -8359,6 +8742,7 @@ false false false + false false false false @@ -8399,6 +8783,7 @@ false false false + false false false false @@ -8443,6 +8828,7 @@ false false false + false false false false @@ -8483,6 +8869,7 @@ false false false + false false false false @@ -8527,6 +8914,7 @@ false false false + false false false false @@ -8567,6 +8955,7 @@ false false false + false false false false @@ -8611,6 +9000,7 @@ false false false + false false false false @@ -8651,6 +9041,7 @@ false false false + false false false false @@ -8700,6 +9091,7 @@ false false false + false false false false @@ -8740,6 +9132,7 @@ false false false + false false false false @@ -8788,6 +9181,7 @@ false false false + false false false false @@ -8828,6 +9222,7 @@ false false false + false false false false @@ -8884,6 +9279,7 @@ false false false + false false false false @@ -8924,6 +9320,7 @@ false false false + false false false false @@ -9169,6 +9566,7 @@ true + true true true true @@ -9186,6 +9584,7 @@ true true true + true true true true @@ -9224,6 +9623,7 @@ true true true + true true true true @@ -9262,6 +9662,7 @@ true true true + true true true true @@ -9300,6 +9701,7 @@ true true true + true true true true @@ -9342,6 +9744,7 @@ true + true true true true diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 38616394..371c85cd 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -534,7 +534,7 @@ ETL\Utilities\Atomic - + ETL\Utilities\Atomic @@ -804,7 +804,7 @@ ETL\Utilities - + ETL\Utilities\Atomic @@ -1425,6 +1425,12 @@ UnitTest++\Header Files + + UnitTest++\Header Files + + + UnitTest++\Header Files + @@ -3422,6 +3428,12 @@ Tests\Error Handler\Assert Function + + Tests + + + Tests +