userver: userver/utils/statistics/relaxed_counter.hpp Source File
Loading...
Searching...
No Matches
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 {
17public:
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) {
27 return *this;
28 }
29
30 Store(other.Load());
31 return *this;
32 }
33
34 RelaxedCounter& operator=(T desired) noexcept {
35 Store(desired);
36 return *this;
37 }
38
39 void Store(T desired) noexcept { val_.store(desired, std::memory_order_relaxed); }
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 { return val_.fetch_add(1, std::memory_order_relaxed); }
51
52 RelaxedCounter& operator--() noexcept {
53 val_.fetch_sub(1, std::memory_order_relaxed);
54 return *this;
55 }
56
57 T operator--(int) noexcept { return val_.fetch_sub(1, std::memory_order_relaxed); }
58
59 RelaxedCounter& operator+=(T arg) noexcept {
60 val_.fetch_add(arg, std::memory_order_relaxed);
61 return *this;
62 }
63
64 RelaxedCounter& operator-=(T arg) noexcept {
65 val_.fetch_sub(arg, std::memory_order_relaxed);
66 return *this;
67 }
68
69private:
70 static_assert(std::atomic<T>::is_always_lock_free);
71
72 std::atomic<T> val_{T{}};
73};
74
75template <typename T>
76void DumpMetric(Writer& writer, const RelaxedCounter<T>& value) {
77 writer = value.Load();
78}
79
80template <typename T>
81void ResetMetric(RelaxedCounter<T>& value) {
82 value.Store(0);
83}
84
85} // namespace utils::statistics
86
87USERVER_NAMESPACE_END