Add constexpr to trivial Atomics

According to https://en.cppreference.com/cpp/atomic/atomic/atomic the constructors of atomics should be constexpr. This change marks (at least for the trivial types) the constructor as constexpr.
This commit is contained in:
christophcrruething 2026-06-02 08:10:26 +02:00 committed by Christoph Rüthing
parent 777fb0c199
commit ef2be90f37
10 changed files with 99 additions and 55 deletions

View File

@ -32,7 +32,7 @@ SOFTWARE.
#include "platform.h" #include "platform.h"
#if ETL_HAS_ATOMIC #if ETL_HAS_ATOMIC
#if (ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) #if (ETL_USING_CPP11 && ETL_USING_STL)
#include "atomic/atomic_std.h" #include "atomic/atomic_std.h"
#elif defined(ETL_COMPILER_ARM5) #elif defined(ETL_COMPILER_ARM5)
#include "atomic/atomic_arm.h" #include "atomic/atomic_arm.h"

View File

@ -118,12 +118,12 @@ namespace etl
{ {
public: public:
atomic() ETL_CONSTEXPR atomic()
: value(T()) : value(T())
{ {
} }
atomic(T v) ETL_CONSTEXPR atomic(T v)
: value(v) : value(v)
{ {
} }
@ -410,7 +410,7 @@ namespace etl
{ {
public: public:
atomic() ETL_CONSTEXPR atomic()
: value(0U) : value(0U)
{ {
} }
@ -656,12 +656,12 @@ namespace etl
{ {
public: public:
atomic() ETL_CONSTEXPR atomic()
: value(0U) : value(0U)
{ {
} }
atomic(bool v) ETL_CONSTEXPR atomic(bool v)
: value(char(v)) : value(char(v))
{ {
} }
@ -997,12 +997,12 @@ namespace etl
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Only integral types are supported"); ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Only integral types are supported");
atomic() ETL_CONSTEXPR atomic()
: value(0) : value(0)
{ {
} }
atomic(T v) ETL_CONSTEXPR atomic(T v)
: value(v) : value(v)
{ {
} }
@ -1401,7 +1401,7 @@ namespace etl
{ {
public: public:
atomic() ETL_CONSTEXPR atomic()
: value(0U) : value(0U)
{ {
} }
@ -1711,12 +1711,12 @@ namespace etl
{ {
public: public:
atomic() ETL_CONSTEXPR atomic()
: value(0U) : value(0U)
{ {
} }
atomic(bool v) ETL_CONSTEXPR atomic(bool v)
: value(char(v)) : value(char(v))
{ {
} }

View File

@ -567,14 +567,14 @@ typedef uint_least32_t char32_t;
#define ETL_HAS_ATOMIC 0 #define ETL_HAS_ATOMIC 0
#define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 0 #define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 0
#else #else
#if ((ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) || defined(ETL_COMPILER_ARM5) || defined(ETL_COMPILER_ARM6) \ #if ((ETL_USING_CPP11 && ETL_USING_STL) || defined(ETL_COMPILER_ARM5) || defined(ETL_COMPILER_ARM6) || defined(ETL_COMPILER_GCC) \
|| defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_CLANG)) || defined(ETL_COMPILER_CLANG))
#define ETL_HAS_ATOMIC 1 #define ETL_HAS_ATOMIC 1
#else #else
#define ETL_HAS_ATOMIC 0 #define ETL_HAS_ATOMIC 0
#endif #endif
#if ((ETL_USING_CPP17 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) || defined(ETL_COMPILER_ARM5) || defined(ETL_COMPILER_ARM6) \ #if ((ETL_USING_CPP17 && ETL_USING_STL) || defined(ETL_COMPILER_ARM5) || defined(ETL_COMPILER_ARM6) || defined(ETL_COMPILER_GCC) \
|| defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_CLANG)) || defined(ETL_COMPILER_CLANG))
#define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 1 #define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 1
#else #else
#define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 0 #define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 0

View File

@ -891,5 +891,37 @@ namespace
CHECK_EQUAL(0, atomic_value.load()); CHECK_EQUAL(0, atomic_value.load());
} }
#endif #endif
#if ETL_USING_CPP11
//*************************************************************************
TEST(test_atomic_trivial_constexpr_default_constructor)
{
// Verify that default constructors are usable in constexpr context
constexpr etl::atomic<int> a_int{};
constexpr etl::atomic<char> a_char{};
constexpr etl::atomic<bool> a_bool{};
(void)a_int;
(void)a_char;
(void)a_bool;
CHECK(true);
}
//*************************************************************************
TEST(test_atomic_trivial_constexpr_value_constructor)
{
// Verify that value constructors are usable in constexpr context
constexpr etl::atomic<int> a_int{42};
constexpr etl::atomic<char> a_char{'A'};
constexpr etl::atomic<bool> a_bool{true};
(void)a_int;
(void)a_char;
(void)a_bool;
CHECK(true);
}
#endif
} }
} // namespace } // namespace

View File

@ -37,11 +37,13 @@ SOFTWARE.
#include <thread> #include <thread>
#include <vector> #include <vector>
#if defined(ETL_COMPILER_MICROSOFT) #if ETL_HAS_ATOMIC
#include <Windows.h>
#endif
#define REALTIME_TEST 0 #if defined(ETL_COMPILER_MICROSOFT)
#include <Windows.h>
#endif
#define REALTIME_TEST 0
//*************************************************************************** //***************************************************************************
// The set of messages. // The set of messages.
@ -130,7 +132,7 @@ namespace
Router1 router1; Router1 router1;
Bus1 bus1; Bus1 bus1;
using event_callback_type = etl::imessage_timer_atomic<std::atomic_uint32_t>::event_callback_type; using event_callback_type = etl::imessage_timer_atomic<etl::atomic_uint32_t>::event_callback_type;
class TimerInsertRemoveTest class TimerInsertRemoveTest
{ {
@ -170,7 +172,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_too_many_timers) TEST(message_timer_too_many_timers)
{ {
etl::message_timer_atomic<2, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<2, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot);
@ -188,7 +190,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_one_shot) TEST(message_timer_one_shot)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot);
@ -224,7 +226,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_one_shot_after_timeout) TEST(message_timer_one_shot_after_timeout)
{ {
etl::message_timer_atomic<1, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<1, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot);
router1.clear(); router1.clear();
@ -270,7 +272,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_repeating) TEST(message_timer_repeating)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -306,7 +308,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_repeating_bigger_step) TEST(message_timer_repeating_bigger_step)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -346,7 +348,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_repeating_stop_start) TEST(message_timer_repeating_stop_start)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -393,7 +395,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_repeating_register_unregister) TEST(message_timer_repeating_register_unregister)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1; etl::timer::id::type id1;
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -436,7 +438,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_repeating_clear) TEST(message_timer_repeating_clear)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -478,7 +480,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_route_through_bus) TEST(message_timer_route_through_bus)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, bus1, 37, etl::timer::mode::Single_Shot, ROUTER1); etl::timer::id::type id1 = timer_controller.register_timer(message1, bus1, 37, etl::timer::mode::Single_Shot, ROUTER1);
etl::timer::id::type id2 = timer_controller.register_timer(message2, bus1, 23, etl::timer::mode::Single_Shot, ROUTER1); etl::timer::id::type id2 = timer_controller.register_timer(message2, bus1, 23, etl::timer::mode::Single_Shot, ROUTER1);
@ -517,7 +519,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_immediate_delayed) TEST(message_timer_immediate_delayed)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -558,7 +560,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_one_shot_big_step_short_delay_insert) TEST(message_timer_one_shot_big_step_short_delay_insert)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 15, etl::timer::mode::Single_Shot); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 15, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 5, etl::timer::mode::Repeating); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 5, etl::timer::mode::Repeating);
@ -590,7 +592,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(callback_timer_one_shot_empty_list_huge_tick_before_insert) TEST(callback_timer_one_shot_empty_list_huge_tick_before_insert)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 5, etl::timer::mode::Single_Shot); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 5, etl::timer::mode::Single_Shot);
@ -628,7 +630,7 @@ namespace
//************************************************************************* //*************************************************************************
TEST(message_timer_time_to_next) TEST(message_timer_time_to_next)
{ {
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Repeating);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -679,7 +681,7 @@ namespace
TEST(message_timer_time_to_next_with_has_active_timer) TEST(message_timer_time_to_next_with_has_active_timer)
{ {
timerInsertRemoveTest.clear(); timerInsertRemoveTest.clear();
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot); etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot); etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot);
@ -734,18 +736,18 @@ namespace
} }
//************************************************************************* //*************************************************************************
#if REALTIME_TEST #if REALTIME_TEST
#if defined(ETL_TARGET_OS_WINDOWS) // Only Windows priority is currently #if defined(ETL_TARGET_OS_WINDOWS) // Only Windows priority is currently
// supported // supported
#define RAISE_THREAD_PRIORITY SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) #define RAISE_THREAD_PRIORITY SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)
#define FIX_PROCESSOR_AFFINITY SetThreadAffinityMask(GetCurrentThread(), 1); #define FIX_PROCESSOR_AFFINITY SetThreadAffinityMask(GetCurrentThread(), 1);
#else #else
#define RAISE_THREAD_PRIORITY #define RAISE_THREAD_PRIORITY
#define FIX_PROCESSOR_AFFINITY #define FIX_PROCESSOR_AFFINITY
#endif #endif
etl::message_timer_atomic<3, std::atomic_uint32_t> controller; etl::message_timer_atomic<3, etl::atomic_uint32_t> controller;
void timer_event() void timer_event()
{ {
@ -821,6 +823,8 @@ namespace
CHECK_EQUAL(10U, router1.message2.size()); CHECK_EQUAL(10U, router1.message2.size());
CHECK(router1.message2.size() < 65U); CHECK(router1.message2.size() < 65U);
} }
#endif #endif
} }
} // namespace } // namespace
#endif // ETL_HAS_ATOMIC

View File

@ -36,6 +36,8 @@ SOFTWARE.
#include "etl/reference_counted_message_pool.h" #include "etl/reference_counted_message_pool.h"
#include "etl/shared_message.h" #include "etl/shared_message.h"
#if ETL_HAS_ATOMIC
namespace namespace
{ {
constexpr etl::message_id_t MessageId1 = 1U; constexpr etl::message_id_t MessageId1 = 1U;
@ -216,9 +218,9 @@ namespace
etl::atomic_counted_message_pool message_pool(memory_allocator); etl::atomic_counted_message_pool message_pool(memory_allocator);
#include "etl/private/diagnostic_pessimizing_move_push.h" #include "etl/private/diagnostic_pessimizing_move_push.h"
etl::shared_message sm(std::move(etl::shared_message(message_pool, Message1()))); etl::shared_message sm(std::move(etl::shared_message(message_pool, Message1())));
#include "etl/private/diagnostic_pop.h" #include "etl/private/diagnostic_pop.h"
CHECK_EQUAL(1, sm.get_reference_count()); CHECK_EQUAL(1, sm.get_reference_count());
} }
@ -228,9 +230,9 @@ namespace
{ {
message_1_instantiations = 0; message_1_instantiations = 0;
#include "etl/private/diagnostic_pessimizing_move_push.h" #include "etl/private/diagnostic_pessimizing_move_push.h"
etl::shared_message sm(std::move(common_message_pool.create_message<Message1>())); etl::shared_message sm(std::move(common_message_pool.create_message<Message1>()));
#include "etl/private/diagnostic_pop.h" #include "etl/private/diagnostic_pop.h"
CHECK_EQUAL(1, sm.get_reference_count()); CHECK_EQUAL(1, sm.get_reference_count());
CHECK_EQUAL(1, message_1_instantiations); CHECK_EQUAL(1, message_1_instantiations);
@ -239,9 +241,9 @@ namespace
//************************************************************************* //*************************************************************************
TEST(test_move_constructor_with_parametrized_constructed_message) TEST(test_move_constructor_with_parametrized_constructed_message)
{ {
#include "etl/private/diagnostic_pessimizing_move_push.h" #include "etl/private/diagnostic_pessimizing_move_push.h"
etl::shared_message sm(std::move(etl::shared_message(common_message_pool, Message1(1)))); etl::shared_message sm(std::move(etl::shared_message(common_message_pool, Message1(1))));
#include "etl/private/diagnostic_pop.h" #include "etl/private/diagnostic_pop.h"
CHECK_EQUAL(1, sm.get_reference_count()); CHECK_EQUAL(1, sm.get_reference_count());
} }
@ -251,9 +253,9 @@ namespace
{ {
message_1_instantiations = 0; message_1_instantiations = 0;
#include "etl/private/diagnostic_pessimizing_move_push.h" #include "etl/private/diagnostic_pessimizing_move_push.h"
etl::shared_message sm(std::move(common_message_pool.create_message<Message1>(1))); etl::shared_message sm(std::move(common_message_pool.create_message<Message1>(1)));
#include "etl/private/diagnostic_pop.h" #include "etl/private/diagnostic_pop.h"
CHECK_EQUAL(1, sm.get_reference_count()); CHECK_EQUAL(1, sm.get_reference_count());
CHECK_EQUAL(1, message_1_instantiations); CHECK_EQUAL(1, message_1_instantiations);
@ -298,9 +300,9 @@ namespace
etl::atomic_counted_message_pool message_pool(memory_allocator); etl::atomic_counted_message_pool message_pool(memory_allocator);
etl::shared_message sm2 = etl::shared_message(message_pool, Message1(2)); etl::shared_message sm2 = etl::shared_message(message_pool, Message1(2));
#include "etl/private/diagnostic_pessimizing_move_push.h" #include "etl/private/diagnostic_pessimizing_move_push.h"
sm2 = std::move(etl::shared_message(message_pool, Message1(3))); sm2 = std::move(etl::shared_message(message_pool, Message1(3)));
#include "etl/private/diagnostic_pop.h" #include "etl/private/diagnostic_pop.h"
CHECK_EQUAL(1, sm2.get_reference_count()); CHECK_EQUAL(1, sm2.get_reference_count());
CHECK(sm2.is_valid()); CHECK(sm2.is_valid());
} }
@ -374,3 +376,5 @@ namespace
} }
} }
} // namespace } // namespace
#endif // ETL_HAS_ATOMIC

View File

@ -43,6 +43,7 @@ SOFTWARE.
#include "data.h" #include "data.h"
#include "etl/char_traits.h"
#include "etl/hash.h" #include "etl/hash.h"
#include "etl/unordered_map.h" #include "etl/unordered_map.h"

View File

@ -41,6 +41,7 @@ SOFTWARE.
#include "data.h" #include "data.h"
#include "etl/char_traits.h"
#include "etl/unordered_multimap.h" #include "etl/unordered_multimap.h"
namespace etl namespace etl

View File

@ -40,6 +40,7 @@ SOFTWARE.
#include "data.h" #include "data.h"
#include "etl/char_traits.h"
#include "etl/checksum.h" #include "etl/checksum.h"
#include "etl/unordered_multiset.h" #include "etl/unordered_multiset.h"

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "data.h" #include "data.h"
#include "etl/char_traits.h"
#include "etl/checksum.h" #include "etl/checksum.h"
#include "etl/hash.h" #include "etl/hash.h"
#include "etl/unordered_set.h" #include "etl/unordered_set.h"