Initial code

This commit is contained in:
John Wellbelove 2025-02-11 11:46:34 +00:00
parent 5f6384f96b
commit 3b0f7eaf86
10 changed files with 2207 additions and 2315 deletions

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2196,60 +2196,79 @@ namespace etl
static ETL_CONSTANT size_t Alignment = etl::alignment_of<T>::value;
/// Index operator.
T& operator [](int i)
/// Warning: The element may not be initialised.
reference operator [](int i)
{
return reinterpret_cast<T*>(this->raw)[i];
return reinterpret_cast<pointer>(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<const T*>(this->raw)[i];
return reinterpret_cast<const_pointer>(this->raw)[i];
}
/// Convert to T reference.
operator T& ()
operator reference ()
{
return *reinterpret_cast<T*>(raw);
return *reinterpret_cast<pointer>(raw);
}
/// Convert to const T reference.
operator const T& () const
operator const_reference () const
{
return *reinterpret_cast<const T*>(raw);
return *reinterpret_cast<const_pointer>(raw);
}
/// Convert to T pointer.
operator T* ()
operator pointer ()
{
return reinterpret_cast<T*>(raw);
return reinterpret_cast<pointer>(raw);
}
/// Convert to const T pointer.
operator const T* () const
operator const_pointer () const
{
return reinterpret_cast<const T*>(raw);
return reinterpret_cast<const_pointer>(raw);
}
T* begin()
/// Get an iterator to the first element.
/// Warning: The element may not be initialised.
iterator begin()
{
return reinterpret_cast<T*>(raw);
return reinterpret_cast<pointer>(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<const T*>(raw);
return reinterpret_cast<const_pointer>(raw);
}
T* end()
/// Get an iterator to one past the last element.
iterator end()
{
return reinterpret_cast<T*>(raw + (sizeof(T) * N_Objects));
return reinterpret_cast<pointer>(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<const T*>(raw + (sizeof(T) * N_Objects));
return reinterpret_cast<const_pointer>(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)

View File

@ -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 <atomic>
@ -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<int>::is_always_lock_free);
// CHECK_TRUE(test.is_always_lock_free);
//#endif
#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC
CHECK_TRUE(etl::atomic<int>::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<int>::is_always_lock_free);
// CHECK_TRUE(etl::atomic<int*>::is_always_lock_free);
// CHECK_FALSE(etl::atomic<S>::is_always_lock_free);
// }
//#endif
//*************************************************************************
TEST(test_atomic_float_is_lock_free)
{
std::atomic<float> compare;
etl::atomic<float> test;
CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free());
#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC
CHECK_TRUE(etl::atomic<float>::is_always_lock_free);
CHECK_TRUE(test.is_always_lock_free);
#endif
}
//*************************************************************************
TEST(test_atomic_double_is_lock_free)
{
std::atomic<double> compare;
etl::atomic<double> test;
CHECK_EQUAL(compare.is_lock_free(), test.is_lock_free());
#if ETL_NOT_USING_STL && ETL_HAS_ATOMIC
CHECK_TRUE(etl::atomic<double>::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<int>::is_always_lock_free;
constexpr bool ialf_pint = etl::atomic<int*>::is_always_lock_free;
constexpr bool ialf_s = etl::atomic<S>::is_always_lock_free;
constexpr bool ialf_double = etl::atomic<double>::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<float> compare(1.23f);
etl::atomic<float> test(1.23f);
CHECK_EQUAL(compare.load(), test.load());
}
//*************************************************************************
TEST(test_atomic_double_load)
{
std::atomic<double> compare(1.23);
etl::atomic<double> 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<S> 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<int> compare(1);
etl::atomic<int> test(1);
int c = compare;
int t = test;
CHECK_EQUAL(c, t);
}
//*************************************************************************
TEST(test_atomic_enum_implicit_conversion)
{
std::atomic<Enum> compare(Enum::One);
etl::atomic<Enum> test(Enum::One);
Enum c = compare;
Enum t = test;
CHECK_EQUAL(c, t);
}
//*************************************************************************
TEST(test_atomic_pointer_implicit_conversion)
{
int i;
std::atomic<int*> compare(&i);
etl::atomic<int*> test(&i);
int* c = compare;
int* t = test;
CHECK_EQUAL(c, t);
}
//*************************************************************************
TEST(test_atomic_bool_implicit_conversion)
{
std::atomic<bool> compare(true);
etl::atomic<bool> test(true);
bool c = compare;
bool t = test;
CHECK_EQUAL(c, t);
}
//*************************************************************************
TEST(test_atomic_float_implicit_conversion)
{
std::atomic<float> compare(1.23f);
etl::atomic<float> test(1.23f);
float c = compare;
float t = test;
CHECK_EQUAL(c, t);
}
//*************************************************************************
TEST(test_atomic_double_implicit_conversion)
{
std::atomic<double> compare(1.23);
etl::atomic<double> 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<S> 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<float> compare(1.23f);
etl::atomic<float> test(1.23f);
compare.store(1.23f);
test.store(1.23f);
CHECK_EQUAL(compare.load(), test.load());
}
//*************************************************************************
TEST(test_atomic_double_store)
{
std::atomic<double> compare(1.23);
etl::atomic<double> 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<S> 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<double> compare(1.23f);
etl::atomic<double> test(1.23f);
compare = 1.23f;
test = 1.23f;
CHECK_EQUAL(compare.load(), test.load());
}
//*************************************************************************
TEST(test_atomic_double_assignment)
{
std::atomic<double> compare(1.23f);
etl::atomic<double> 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<S> 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<S> 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<int> compare;
etl::atomic<int> test;
@ -551,7 +851,7 @@ namespace
}
//*************************************************************************
TEST(test_atomic_compare_exchange_weak_pass)
TEST(test_atomic_compare_exchange_weak_pass_for_integer)
{
std::atomic<int> compare;
etl::atomic<int> test;
@ -620,7 +920,87 @@ namespace
}
//*************************************************************************
TEST(test_atomic_compare_exchange_strong_fail)
TEST(test_atomic_compare_exchange_weak_pass_for_float)
{
std::atomic<float> compare;
etl::atomic<float> 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<double> compare;
etl::atomic<double> 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<S> 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<int> compare;
etl::atomic<int> test;
@ -643,7 +1023,7 @@ namespace
}
//*************************************************************************
TEST(test_atomic_compare_exchange_strong_pass)
TEST(test_atomic_compare_exchange_strong_pass_for_integer)
{
std::atomic<int> compare;
etl::atomic<int> test;
@ -711,6 +1091,52 @@ namespace
CHECK_EQUAL(compare.load(), test.load());
}
//*************************************************************************
TEST(test_atomic_compare_exchange_strong_pass_for_float)
{
std::atomic<float> compare;
etl::atomic<float> 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<double> compare;
etl::atomic<double> 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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -534,7 +534,7 @@
<ClInclude Include="..\..\include\etl\atomic\atomic_std.h">
<Filter>ETL\Utilities\Atomic</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\atomic\atomic_gcc_sync.h">
<ClInclude Include="..\..\include\etl\atomic\atomic_gcc.h">
<Filter>ETL\Utilities\Atomic</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\queue_mpmc_mutex.h">
@ -804,7 +804,7 @@
<ClInclude Include="..\..\include\etl\flags.h">
<Filter>ETL\Utilities</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\atomic\atomic_clang_sync.h">
<ClInclude Include="..\..\include\etl\atomic\atomic_clang.h">
<Filter>ETL\Utilities\Atomic</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\buffer_descriptors.h">
@ -1425,6 +1425,12 @@
<ClInclude Include="..\..\include\etl\singleton_base.h">
<Filter>UnitTest++\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\function_traits.h">
<Filter>UnitTest++\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\type_list.h">
<Filter>UnitTest++\Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test_string_char.cpp">
@ -3422,6 +3428,12 @@
<ClCompile Include="..\etl_error_handler\assert_function\test_error_handler.cpp">
<Filter>Tests\Error Handler\Assert Function</Filter>
</ClCompile>
<ClCompile Include="..\syntax_check\function_traits.h.t.cpp">
<Filter>Tests</Filter>
</ClCompile>
<ClCompile Include="..\test_function_traits.cpp">
<Filter>Tests</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">