userver: userver/utils/statistics/relaxed_counter.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
relaxed_counter.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/statistics/relaxed_counter.hpp
4/// @brief @copybrief utils::statistics::RelaxedCounter
5
6#include <atomic>
7
8#include <userver/utils/statistics/fwd.hpp>
9
10USERVER_NAMESPACE_BEGIN
11
12namespace utils::statistics {
13
14/// @brief Atomic counter of type T with relaxed memory ordering
15template <class T>
16class RelaxedCounter final {
17 public:
18 using ValueType = T;
19
20 constexpr RelaxedCounter() noexcept = default;
21 constexpr RelaxedCounter(T desired) noexcept : val_(desired) {}
22
23 RelaxedCounter(const RelaxedCounter& other) noexcept : val_(other.Load()) {}
24
25 RelaxedCounter& operator=(const RelaxedCounter& other) noexcept {
26 if (this == &other) return *this;
27
28 Store(other.Load());
29 return *this;
30 }
31
32 RelaxedCounter& operator=(T desired) noexcept {
33 Store(desired);
34 return *this;
35 }
36
37 void Store(T desired) noexcept {
38 val_.store(desired, std::memory_order_relaxed);
39 }
40
41 T Load() const noexcept { return val_.load(std::memory_order_relaxed); }
42
43 operator T() const noexcept { return Load(); }
44
45 RelaxedCounter& operator++() noexcept {
46 val_.fetch_add(1, std::memory_order_relaxed);
47 return *this;
48 }
49
50 T operator++(int) noexcept {
51 return val_.fetch_add(1, std::memory_order_relaxed);
52 }
53
54 RelaxedCounter& operator--() noexcept {
55 val_.fetch_sub(1, std::memory_order_relaxed);
56 return *this;
57 }
58
59 T operator--(int) noexcept {
60 return val_.fetch_sub(1, std::memory_order_relaxed);
61 }
62
63 RelaxedCounter& operator+=(T arg) noexcept {
64 val_.fetch_add(arg, std::memory_order_relaxed);
65 return *this;
66 }
67
68 RelaxedCounter& operator-=(T arg) noexcept {
69 val_.fetch_sub(arg, std::memory_order_relaxed);
70 return *this;
71 }
72
73 private:
74 static_assert(std::atomic<T>::is_always_lock_free);
75
76 std::atomic<T> val_{T{}};
77};
78
79template <typename T>
80void DumpMetric(Writer& writer, const RelaxedCounter<T>& value) {
81 writer = value.Load();
82}
83
84} // namespace utils::statistics
85
86USERVER_NAMESPACE_END