From 386e3f47e4f61179d9bdc82005a0ddac8204b53a Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 6 Nov 2024 12:53:47 +0100 Subject: [PATCH 1/4] Inherit Atomic#operator=() from base class --- lib/base/atomic.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/base/atomic.hpp b/lib/base/atomic.hpp index a3efaf801..a8dd01519 100644 --- a/lib/base/atomic.hpp +++ b/lib/base/atomic.hpp @@ -26,6 +26,8 @@ namespace icinga template class Atomic : public std::atomic { public: + using std::atomic::operator=; + /** * The only safe constructor of std::atomic#atomic * From 7de65af4cbca7a6dacebb5d5b02dea1a85e1281e Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Mon, 25 Nov 2024 10:33:17 +0100 Subject: [PATCH 2/4] Introduce Locked#Locked(T) --- lib/base/atomic.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/base/atomic.hpp b/lib/base/atomic.hpp index a8dd01519..f603235b4 100644 --- a/lib/base/atomic.hpp +++ b/lib/base/atomic.hpp @@ -87,6 +87,12 @@ template class Locked { public: + Locked() = default; + + Locked(T desired) : m_Value(std::move(desired)) + { + } + inline T load() const { std::unique_lock lock(m_Mutex); From 98159b33dd3d03fe85cf135d6ce53731f34544f8 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Mon, 25 Nov 2024 10:46:11 +0100 Subject: [PATCH 3/4] mkclass: use std::atomic#atomic(T), not std::atomic#atomic() --- tools/mkclass/classcompiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index b17486cfe..fc964b4a7 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -1069,7 +1069,9 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) if (field.Attributes & FANoStorage) continue; - m_Header << "\tAtomicOrLocked<" << field.Type.GetRealType() << "> m_" << field.GetFriendlyName() << ";" << std::endl; + m_Header << "\ttypedef " << field.Type.GetRealType() << " " << field.GetFriendlyName() << "_t;" << std::endl + << "\tAtomicOrLocked<" << field.GetFriendlyName() << "_t> m_" << field.GetFriendlyName() + << " {" << field.GetFriendlyName() << "_t()};" << std::endl; } /* signal */ From 77e842c27fb40f0effac895d0824d3eccf0ad4b9 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 6 Nov 2024 13:30:28 +0100 Subject: [PATCH 4/4] Consistently use Atomic, and not std::atomic Atomic enforces usage of its only safe constructor, in contrast to std::atomic. "The default-initialized std::atomic does not contain a T object, and its only valid uses are destruction and initialization by std::atomic_init, see LWG issue 2334." -- https://en.cppreference.com/w/cpp/atomic/atomic/atomic --- lib/base/atomic.hpp | 4 ++-- lib/base/io-engine.cpp | 5 +++-- lib/base/io-engine.hpp | 4 ++-- lib/base/lazy-init.hpp | 5 ++--- lib/base/logger.cpp | 2 +- lib/base/logger.hpp | 2 +- lib/base/namespace.hpp | 4 ++-- lib/base/object.cpp | 5 ----- lib/base/object.hpp | 6 +++--- lib/base/tlsstream.hpp | 5 ++--- lib/base/workqueue.cpp | 2 +- lib/base/workqueue.hpp | 4 ++-- lib/config/applyrule.hpp | 4 ++-- lib/config/configitem.cpp | 6 +++--- lib/icinga/scheduleddowntime.cpp | 2 +- lib/icinga/scheduleddowntime.hpp | 4 ++-- lib/icingadb/icingadb.hpp | 4 ++-- lib/perfdata/influxdbcommonwriter.hpp | 5 +++-- lib/remote/apilistener-authority.cpp | 2 +- lib/remote/apilistener.hpp | 3 +-- lib/remote/configstageshandler.hpp | 1 + 21 files changed, 37 insertions(+), 42 deletions(-) diff --git a/lib/base/atomic.hpp b/lib/base/atomic.hpp index f603235b4..45346bac0 100644 --- a/lib/base/atomic.hpp +++ b/lib/base/atomic.hpp @@ -113,12 +113,12 @@ private: }; /** - * Type alias for std::atomic if possible, otherwise Locked is used as a fallback. + * Type alias for Atomic if possible, otherwise Locked is used as a fallback. * * @ingroup base */ template -using AtomicOrLocked = std::conditional_t, std::atomic, Locked>; +using AtomicOrLocked = std::conditional_t, Atomic, Locked>; } diff --git a/lib/base/io-engine.cpp b/lib/base/io-engine.cpp index 9da8d1f54..e869e4f2b 100644 --- a/lib/base/io-engine.cpp +++ b/lib/base/io-engine.cpp @@ -142,9 +142,10 @@ boost::asio::io_context& IoEngine::GetIoContext() return m_IoContext; } -IoEngine::IoEngine() : m_IoContext(), m_KeepAlive(boost::asio::make_work_guard(m_IoContext)), m_Threads(decltype(m_Threads)::size_type(Configuration::Concurrency * 2u)) +IoEngine::IoEngine() : m_IoContext(), m_KeepAlive(boost::asio::make_work_guard(m_IoContext)), + m_Threads(decltype(m_Threads)::size_type(Configuration::Concurrency * 2u)), + m_CpuBoundSemaphore(Configuration::Concurrency * 3u / 2u) { - m_CpuBoundSemaphore.store(Configuration::Concurrency * 3u / 2u); for (auto& thread : m_Threads) { thread = std::thread(&IoEngine::RunEventLoop, this); diff --git a/lib/base/io-engine.hpp b/lib/base/io-engine.hpp index cc2eb72de..d68afe0f0 100644 --- a/lib/base/io-engine.hpp +++ b/lib/base/io-engine.hpp @@ -10,7 +10,7 @@ #include "base/lazy-init.hpp" #include "base/logger.hpp" #include "base/shared.hpp" -#include +#include #include #include #include @@ -173,7 +173,7 @@ private: boost::asio::executor_work_guard m_KeepAlive; std::vector m_Threads; - std::atomic_uint_fast32_t m_CpuBoundSemaphore; + Atomic m_CpuBoundSemaphore; std::mutex m_CpuBoundWaitingMutex; std::vector::Ptr>> m_CpuBoundWaiting; }; diff --git a/lib/base/lazy-init.hpp b/lib/base/lazy-init.hpp index fc70fd773..b27ab8e93 100644 --- a/lib/base/lazy-init.hpp +++ b/lib/base/lazy-init.hpp @@ -4,7 +4,7 @@ #ifndef LAZY_INIT #define LAZY_INIT -#include +#include "base/atomic.hpp" #include #include #include @@ -25,7 +25,6 @@ public: inline LazyInit(std::function initializer = []() { return T(); }) : m_Initializer(std::move(initializer)) { - m_Underlying.store(nullptr, std::memory_order_release); } LazyInit(const LazyInit&) = delete; @@ -65,7 +64,7 @@ public: private: std::function m_Initializer; std::mutex m_Mutex; - std::atomic m_Underlying; + Atomic m_Underlying {nullptr}; }; } diff --git a/lib/base/logger.cpp b/lib/base/logger.cpp index 5172e3a83..e004dbfee 100644 --- a/lib/base/logger.cpp +++ b/lib/base/logger.cpp @@ -35,7 +35,7 @@ REGISTER_TYPE(Logger); std::set Logger::m_Loggers; std::mutex Logger::m_Mutex; bool Logger::m_ConsoleLogEnabled = true; -std::atomic Logger::m_EarlyLoggingEnabled (true); +Atomic Logger::m_EarlyLoggingEnabled (true); bool Logger::m_TimestampEnabled = true; LogSeverity Logger::m_ConsoleLogSeverity = LogInformation; std::mutex Logger::m_UpdateMinLogSeverityMutex; diff --git a/lib/base/logger.hpp b/lib/base/logger.hpp index 0e929d300..7e399cc10 100644 --- a/lib/base/logger.hpp +++ b/lib/base/logger.hpp @@ -101,7 +101,7 @@ private: static std::mutex m_Mutex; static std::set m_Loggers; static bool m_ConsoleLogEnabled; - static std::atomic m_EarlyLoggingEnabled; + static Atomic m_EarlyLoggingEnabled; static bool m_TimestampEnabled; static LogSeverity m_ConsoleLogSeverity; static std::mutex m_UpdateMinLogSeverityMutex; diff --git a/lib/base/namespace.hpp b/lib/base/namespace.hpp index c707c0e60..23d05e61b 100644 --- a/lib/base/namespace.hpp +++ b/lib/base/namespace.hpp @@ -5,12 +5,12 @@ #define NAMESPACE_H #include "base/i2-base.hpp" +#include "base/atomic.hpp" #include "base/object.hpp" #include "base/objectlock.hpp" #include "base/shared-object.hpp" #include "base/value.hpp" #include "base/debuginfo.hpp" -#include #include #include #include @@ -96,7 +96,7 @@ private: std::map m_Data; mutable std::shared_timed_mutex m_DataMutex; bool m_ConstValues; - std::atomic m_Frozen; + Atomic m_Frozen; }; Namespace::Iterator begin(const Namespace::Ptr& x); diff --git a/lib/base/object.cpp b/lib/base/object.cpp index f75e7c101..30d461b2a 100644 --- a/lib/base/object.cpp +++ b/lib/base/object.cpp @@ -28,11 +28,6 @@ static Timer::Ptr l_ObjectCountTimer; */ Object::Object() { - m_References.store(0); - -#ifdef I2_DEBUG - m_LockOwner.store(decltype(m_LockOwner.load())()); -#endif /* I2_DEBUG */ } /** diff --git a/lib/base/object.hpp b/lib/base/object.hpp index 054dc6c93..286d44e2e 100644 --- a/lib/base/object.hpp +++ b/lib/base/object.hpp @@ -5,10 +5,10 @@ #define OBJECT_H #include "base/i2-base.hpp" +#include "base/atomic.hpp" #include "base/debug.hpp" #include "base/intrusive-ptr.hpp" #include -#include #include #include #include @@ -194,11 +194,11 @@ private: Object(const Object& other) = delete; Object& operator=(const Object& rhs) = delete; - mutable std::atomic m_References; + mutable Atomic m_References {0}; mutable std::recursive_mutex m_Mutex; #ifdef I2_DEBUG - mutable std::atomic m_LockOwner; + mutable Atomic m_LockOwner {std::thread::id()}; mutable size_t m_LockCount = 0; #endif /* I2_DEBUG */ diff --git a/lib/base/tlsstream.hpp b/lib/base/tlsstream.hpp index a19a3f025..2cc1d065f 100644 --- a/lib/base/tlsstream.hpp +++ b/lib/base/tlsstream.hpp @@ -5,13 +5,13 @@ #define TLSSTREAM_H #include "base/i2-base.hpp" +#include "base/atomic.hpp" #include "base/shared.hpp" #include "base/socket.hpp" #include "base/stream.hpp" #include "base/tlsutility.hpp" #include "base/fifo.hpp" #include "base/utility.hpp" -#include #include #include #include @@ -32,7 +32,6 @@ public: template SeenStream(Args&&... args) : ARS(std::forward(args)...) { - m_Seen.store(nullptr); } template @@ -55,7 +54,7 @@ public: } private: - std::atomic m_Seen; + Atomic m_Seen {nullptr}; }; struct UnbufferedAsioTlsStreamParams diff --git a/lib/base/workqueue.cpp b/lib/base/workqueue.cpp index a4793c0ae..dfca3dd47 100644 --- a/lib/base/workqueue.cpp +++ b/lib/base/workqueue.cpp @@ -12,7 +12,7 @@ using namespace icinga; -std::atomic WorkQueue::m_NextID(1); +Atomic WorkQueue::m_NextID (1); boost::thread_specific_ptr l_ThreadWorkQueue; WorkQueue::WorkQueue(size_t maxItems, int threadCount, LogSeverity statsLogLevel) diff --git a/lib/base/workqueue.hpp b/lib/base/workqueue.hpp index fc3711555..f59a5c716 100644 --- a/lib/base/workqueue.hpp +++ b/lib/base/workqueue.hpp @@ -5,6 +5,7 @@ #define WORKQUEUE_H #include "base/i2-base.hpp" +#include "base/atomic.hpp" #include "base/timer.hpp" #include "base/ringbuffer.hpp" #include "base/logger.hpp" @@ -14,7 +15,6 @@ #include #include #include -#include namespace icinga { @@ -122,7 +122,7 @@ protected: private: int m_ID; String m_Name; - static std::atomic m_NextID; + static Atomic m_NextID; int m_ThreadCount; bool m_Spawned{false}; diff --git a/lib/config/applyrule.hpp b/lib/config/applyrule.hpp index 0acc1c994..a0950ed90 100644 --- a/lib/config/applyrule.hpp +++ b/lib/config/applyrule.hpp @@ -6,11 +6,11 @@ #include "config/i2-config.hpp" #include "config/expression.hpp" +#include "base/atomic.hpp" #include "base/debuginfo.hpp" #include "base/shared-object.hpp" #include "base/type.hpp" #include -#include namespace icinga { @@ -105,7 +105,7 @@ private: bool m_IgnoreOnError; DebugInfo m_DebugInfo; Dictionary::Ptr m_Scope; - std::atomic m_HasMatches; + Atomic m_HasMatches; static TypeMap m_Types; static RuleMap m_Rules; diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 7687e50be..b86a95b7d 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -7,6 +7,7 @@ #include "config/objectrule.hpp" #include "config/configcompiler.hpp" #include "base/application.hpp" +#include "base/atomic.hpp" #include "base/configtype.hpp" #include "base/objectlock.hpp" #include "base/convert.hpp" @@ -22,7 +23,6 @@ #include "base/function.hpp" #include "base/utility.hpp" #include -#include #include #include #include @@ -450,7 +450,7 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue #endif /* I2_DEBUG */ for (auto& type : Type::GetConfigTypesSortedByLoadDependencies()) { - std::atomic committed_items(0); + Atomic committed_items (0); { auto items (itemsByType.find(type.get())); @@ -496,7 +496,7 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue #endif /* I2_DEBUG */ for (auto& type : Type::GetConfigTypesSortedByLoadDependencies()) { - std::atomic notified_items(0); + Atomic notified_items (0); { auto items (itemsByType.find(type.get())); diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index 6afdf602c..137f0c0d9 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -391,4 +391,4 @@ bool ScheduledDowntime::AllConfigIsLoaded() return m_AllConfigLoaded.load(); } -std::atomic ScheduledDowntime::m_AllConfigLoaded (false); +Atomic ScheduledDowntime::m_AllConfigLoaded (false); diff --git a/lib/icinga/scheduleddowntime.hpp b/lib/icinga/scheduleddowntime.hpp index 8ede9666c..2673393ca 100644 --- a/lib/icinga/scheduleddowntime.hpp +++ b/lib/icinga/scheduleddowntime.hpp @@ -5,9 +5,9 @@ #define SCHEDULEDDOWNTIME_H #include "icinga/i2-icinga.hpp" +#include "base/atomic.hpp" #include "icinga/scheduleddowntime-ti.hpp" #include "icinga/checkable.hpp" -#include namespace icinga { @@ -50,7 +50,7 @@ private: void CreateNextDowntime(); void RemoveObsoleteDowntimes(); - static std::atomic m_AllConfigLoaded; + static Atomic m_AllConfigLoaded; static bool EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter); static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule, bool skipFilter = false); diff --git a/lib/icingadb/icingadb.hpp b/lib/icingadb/icingadb.hpp index 647a00b67..87da7be6d 100644 --- a/lib/icingadb/icingadb.hpp +++ b/lib/icingadb/icingadb.hpp @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -456,7 +456,7 @@ private: */ RedisConnection::Ptr m_RconWorker; std::unordered_map m_Rcons; - std::atomic_size_t m_PendingRcons; + Atomic m_PendingRcons {0}; struct { DumpedGlobals CustomVar, ActionUrl, NotesUrl, IconImage, DependencyGroup; diff --git a/lib/perfdata/influxdbcommonwriter.hpp b/lib/perfdata/influxdbcommonwriter.hpp index cfda02501..c6a18a759 100644 --- a/lib/perfdata/influxdbcommonwriter.hpp +++ b/lib/perfdata/influxdbcommonwriter.hpp @@ -5,13 +5,14 @@ #define INFLUXDBCOMMONWRITER_H #include "perfdata/influxdbcommonwriter-ti.hpp" +#include "base/atomic.hpp" #include "icinga/checkable.hpp" #include "base/configobject.hpp" #include "base/perfdatavalue.hpp" #include "base/workqueue.hpp" #include "remote/url.hpp" #include "perfdata/perfdatawriterconnection.hpp" -#include +#include namespace icinga { @@ -49,7 +50,7 @@ private: std::atomic_bool m_FlushTimerInQueue{false}; WorkQueue m_WorkQueue{10000000, 1}; std::vector m_DataBuffer; - std::atomic_size_t m_DataBufferSize{0}; + Atomic m_DataBufferSize {0}; Shared::Ptr m_SslContext; PerfdataWriterConnection::Ptr m_Connection; diff --git a/lib/remote/apilistener-authority.cpp b/lib/remote/apilistener-authority.cpp index 8c593ccf6..0b13f86fa 100644 --- a/lib/remote/apilistener-authority.cpp +++ b/lib/remote/apilistener-authority.cpp @@ -9,7 +9,7 @@ using namespace icinga; -std::atomic ApiListener::m_UpdatedObjectAuthority (false); +Atomic ApiListener::m_UpdatedObjectAuthority (false); void ApiListener::UpdateObjectAuthority() { diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index 26f9718f9..17c1c8c16 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -19,7 +19,6 @@ #include "base/tlsstream.hpp" #include "base/threadpool.hpp" #include "base/wait-group.hpp" -#include #include #include #include @@ -194,7 +193,7 @@ private: StoppableWaitGroup::Ptr m_WaitGroup = new StoppableWaitGroup(); static ApiListener::Ptr m_Instance; - static std::atomic m_UpdatedObjectAuthority; + static Atomic m_UpdatedObjectAuthority; boost::signals2::signal m_OnListenerShutdown; StoppableWaitGroup::Ptr m_ListenerWaitGroup = new StoppableWaitGroup(); diff --git a/lib/remote/configstageshandler.hpp b/lib/remote/configstageshandler.hpp index 8dda34122..0279010b7 100644 --- a/lib/remote/configstageshandler.hpp +++ b/lib/remote/configstageshandler.hpp @@ -4,6 +4,7 @@ #ifndef CONFIGSTAGESHANDLER_H #define CONFIGSTAGESHANDLER_H +#include "base/atomic.hpp" #include "remote/httphandler.hpp" namespace icinga