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 {
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