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"
#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"
#elif defined(ETL_COMPILER_ARM5)
#include "atomic/atomic_arm.h"

View File

@ -118,12 +118,12 @@ namespace etl
{
public:
atomic()
ETL_CONSTEXPR atomic()
: value(T())
{
}
atomic(T v)
ETL_CONSTEXPR atomic(T v)
: value(v)
{
}
@ -410,7 +410,7 @@ namespace etl
{
public:
atomic()
ETL_CONSTEXPR atomic()
: value(0U)
{
}
@ -656,12 +656,12 @@ namespace etl
{
public:
atomic()
ETL_CONSTEXPR atomic()
: value(0U)
{
}
atomic(bool v)
ETL_CONSTEXPR atomic(bool v)
: value(char(v))
{
}
@ -997,12 +997,12 @@ namespace etl
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Only integral types are supported");
atomic()
ETL_CONSTEXPR atomic()
: value(0)
{
}
atomic(T v)
ETL_CONSTEXPR atomic(T v)
: value(v)
{
}
@ -1401,7 +1401,7 @@ namespace etl
{
public:
atomic()
ETL_CONSTEXPR atomic()
: value(0U)
{
}
@ -1711,12 +1711,12 @@ namespace etl
{
public:
atomic()
ETL_CONSTEXPR atomic()
: value(0U)
{
}
atomic(bool v)
ETL_CONSTEXPR atomic(bool 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_ALWAYS_LOCK_FREE 0
#else
#if ((ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) || defined(ETL_COMPILER_ARM5) || defined(ETL_COMPILER_ARM6) \
|| defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_CLANG))
#if ((ETL_USING_CPP11 && ETL_USING_STL) || defined(ETL_COMPILER_ARM5) || defined(ETL_COMPILER_ARM6) || defined(ETL_COMPILER_GCC) \
|| defined(ETL_COMPILER_CLANG))
#define ETL_HAS_ATOMIC 1
#else
#define ETL_HAS_ATOMIC 0
#endif
#if ((ETL_USING_CPP17 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) || defined(ETL_COMPILER_ARM5) || defined(ETL_COMPILER_ARM6) \
|| defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_CLANG))
#if ((ETL_USING_CPP17 && ETL_USING_STL) || defined(ETL_COMPILER_ARM5) || defined(ETL_COMPILER_ARM6) || defined(ETL_COMPILER_GCC) \
|| defined(ETL_COMPILER_CLANG))
#define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 1
#else
#define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 0

View File

@ -891,5 +891,37 @@ namespace
CHECK_EQUAL(0, atomic_value.load());
}
#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

View File

@ -37,11 +37,13 @@ SOFTWARE.
#include <thread>
#include <vector>
#if defined(ETL_COMPILER_MICROSOFT)
#include <Windows.h>
#endif
#if ETL_HAS_ATOMIC
#define REALTIME_TEST 0
#if defined(ETL_COMPILER_MICROSOFT)
#include <Windows.h>
#endif
#define REALTIME_TEST 0
//***************************************************************************
// The set of messages.
@ -130,7 +132,7 @@ namespace
Router1 router1;
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
{
@ -170,7 +172,7 @@ namespace
//*************************************************************************
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 id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot);
@ -188,7 +190,7 @@ namespace
//*************************************************************************
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 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)
{
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);
router1.clear();
@ -270,7 +272,7 @@ namespace
//*************************************************************************
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 id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -306,7 +308,7 @@ namespace
//*************************************************************************
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 id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -346,7 +348,7 @@ namespace
//*************************************************************************
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 id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -393,7 +395,7 @@ namespace
//*************************************************************************
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 id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -436,7 +438,7 @@ namespace
//*************************************************************************
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 id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Repeating);
@ -478,7 +480,7 @@ namespace
//*************************************************************************
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 id2 = timer_controller.register_timer(message2, bus1, 23, etl::timer::mode::Single_Shot, ROUTER1);
@ -517,7 +519,7 @@ namespace
//*************************************************************************
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 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)
{
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 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)
{
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);
@ -628,7 +630,7 @@ namespace
//*************************************************************************
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 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)
{
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 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
// supported
#define RAISE_THREAD_PRIORITY SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)
#define FIX_PROCESSOR_AFFINITY SetThreadAffinityMask(GetCurrentThread(), 1);
#else
#define RAISE_THREAD_PRIORITY
#define FIX_PROCESSOR_AFFINITY
#endif
#if defined(ETL_TARGET_OS_WINDOWS) // Only Windows priority is currently
// supported
#define RAISE_THREAD_PRIORITY SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)
#define FIX_PROCESSOR_AFFINITY SetThreadAffinityMask(GetCurrentThread(), 1);
#else
#define RAISE_THREAD_PRIORITY
#define FIX_PROCESSOR_AFFINITY
#endif
etl::message_timer_atomic<3, std::atomic_uint32_t> controller;
etl::message_timer_atomic<3, etl::atomic_uint32_t> controller;
void timer_event()
{
@ -821,6 +823,8 @@ namespace
CHECK_EQUAL(10U, router1.message2.size());
CHECK(router1.message2.size() < 65U);
}
#endif
#endif
}
} // namespace
#endif // ETL_HAS_ATOMIC

View File

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

View File

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

View File

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

View File

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

View File

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