From 4b2b45c8a1c496da1d7e3c91e859d525a27cba38 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 9 Jul 2020 10:47:54 +0200 Subject: [PATCH] Introduce AtomicDuration --- lib/base/atomic.hpp | 38 ++++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 1 + test/base-atomic.cpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 test/base-atomic.cpp diff --git a/lib/base/atomic.hpp b/lib/base/atomic.hpp index 855850336..841151612 100644 --- a/lib/base/atomic.hpp +++ b/lib/base/atomic.hpp @@ -4,6 +4,7 @@ #define ATOMIC_H #include +#include #include #include #include @@ -34,6 +35,43 @@ public: } }; +/** + * Accumulates time durations atomically. + * + * @ingroup base + */ +class AtomicDuration +{ +public: + using Clock = std::chrono::steady_clock; + + /** + * Adds the elapsedTime to this instance. + * + * May be called multiple times to accumulate time. + * + * @param elapsedTime The distance between two time points + * + * @return This instance for method chaining + */ + AtomicDuration& operator+=(const Clock::duration& elapsedTime) noexcept + { + m_Sum.fetch_add(elapsedTime.count(), std::memory_order_relaxed); + return *this; + } + + /** + * @return The total accumulated time in seconds + */ + operator double() const noexcept + { + return std::chrono::duration(Clock::duration(m_Sum.load(std::memory_order_relaxed))).count(); + } + +private: + Atomic m_Sum {0}; +}; + /** * Wraps any T into a std::atomic-like interface that locks using a mutex. * diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cb815da73..c317d4ebe 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -89,6 +89,7 @@ set(base_test_SOURCES icingaapplication-fixture.cpp utils.cpp base-array.cpp + base-atomic.cpp base-base64.cpp base-convert.cpp base-dictionary.cpp diff --git a/test/base-atomic.cpp b/test/base-atomic.cpp new file mode 100644 index 000000000..1bdead38d --- /dev/null +++ b/test/base-atomic.cpp @@ -0,0 +1,34 @@ +/* Icinga 2 | (c) 2025 Icinga GmbH | GPLv2+ */ + +#include "base/atomic.hpp" +#include + +using namespace icinga; + +BOOST_AUTO_TEST_SUITE(base_atomic) + +BOOST_AUTO_TEST_CASE(duration_none) +{ + BOOST_CHECK_EQUAL(static_cast(AtomicDuration()), 0); +} + +BOOST_AUTO_TEST_CASE(duration_one) +{ + AtomicDuration sum; + + sum += std::chrono::seconds(1); + + BOOST_CHECK_EQUAL(static_cast(sum), 1); +} + +BOOST_AUTO_TEST_CASE(duration_two) +{ + AtomicDuration sum; + + sum += std::chrono::seconds(1); + sum += std::chrono::seconds(2); + + BOOST_CHECK_EQUAL(static_cast(sum), 3); +} + +BOOST_AUTO_TEST_SUITE_END()