HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
counters.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2019, 2021-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
8#pragma once
9
10#include "architecture.hpp"
11#include "fixed_string.hpp"
12#include "time_stamp_count.hpp"
13#include "atomic.hpp"
14#include "unfair_mutex.hpp"
15#include <span>
16#include <typeinfo>
17#include <typeindex>
18#include <string>
19#include <atomic>
20#include <map>
21#include <memory>
22#include <mutex>
23
24namespace hi::inline v1 {
25namespace detail {
26
27class counter {
28public:
35 [[nodiscard]] static counter *get_if(std::string const& name) noexcept
36 {
37 hilet lock = std::scoped_lock(_mutex);
38 hilet& map_ = _map.get_or_make();
39 hilet it = map_.find(name);
40 if (it == map_.cend()) {
41 return nullptr;
42 } else {
43 hi_assert(it->second);
44 return it->second;
45 }
46 }
47
48 counter(counter const&) = delete;
49 counter(counter&&) = delete;
50 counter& operator=(counter const&) = delete;
51 counter& operator=(counter&&) = delete;
52
53 constexpr counter() noexcept {}
54
55 operator uint64_t() const noexcept
56 {
57 return _total_count.load(std::memory_order::relaxed);
58 }
59
60 static void log() noexcept
61 {
62 hilet lock = std::scoped_lock(_mutex);
63 log_header();
64 for (hilet & [ string, counter ] : _map.get_or_make()) {
65 hi_assert(counter);
66 counter->log(string);
67 }
68 }
69
70 static void log_header() noexcept;
71
74 void log(std::string const& tag) noexcept;
75
76 uint64_t operator++() noexcept
77 {
78 return _total_count.fetch_add(1, std::memory_order::relaxed) + 1;
79 }
80
81 uint64_t operator++(int) noexcept
82 {
83 return _total_count.fetch_add(1, std::memory_order::relaxed);
84 }
85
86 uint64_t operator--() noexcept
87 {
88 return _total_count.fetch_sub(1, std::memory_order::relaxed) + 1;
89 }
90
91 uint64_t operator--(int) noexcept
92 {
93 return _total_count.fetch_sub(1, std::memory_order::relaxed);
94 }
95
98 void add_duration(uint64_t duration) noexcept
99 {
100 _total_count.fetch_add(1, std::memory_order::relaxed);
101 fetch_max(_duration_max, duration, std::memory_order::relaxed);
102 fetch_min(_duration_min, duration, std::memory_order::relaxed);
103
104 // Combine duration with count in a single atomic.
105 hi_axiom(duration <= (std::numeric_limits<uint64_t>::max() >> 10));
106 duration <<= 16;
107 ++duration;
108 _duration_avg.fetch_add(duration, std::memory_order::relaxed);
109 }
110
111protected:
112 using map_type = std::map<std::string, counter *>;
113
117 constinit static inline unfair_mutex_impl<false> _mutex;
118 constinit static inline atomic_unique_ptr<map_type> _map;
119
120 std::atomic<uint64_t> _total_count = 0;
121 std::atomic<uint64_t> _prev_count = 0;
122 std::atomic<uint64_t> _duration_max = 0;
124
130 std::atomic<uint64_t> _duration_avg = 0;
131};
132
133template<fixed_string Tag>
134class tagged_counter : public counter {
135public:
136 tagged_counter() noexcept : counter()
137 {
138 hilet lock = std::scoped_lock(_mutex);
139 _map.get_or_make()[std::string{Tag}] = this;
140 }
141};
142
143} // namespace detail
144
145template<fixed_string Tag>
146inline detail::tagged_counter<Tag> global_counter;
147
148[[nodiscard]] inline detail::counter *get_global_counter_if(std::string const& name)
149{
150 return detail::counter::get_if(name);
151}
152
153} // namespace hi::inline v1
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:87
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
Functions and macros for handling architectural difference between compilers, CPUs and operating syst...
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:15
T fetch_max(std::atomic< T > &lhs, T rhs, std::memory_order order) noexcept
Lock-free fetch-then-max operation on an atomic.
Definition atomic.hpp:22
T fetch_min(std::atomic< T > &lhs, T rhs, std::memory_order order) noexcept
Lock-free fetch-then-min operation on an atomic.
Definition atomic.hpp:36
Definition atomic.hpp:48
Definition counters.hpp:27
static counter * get_if(std::string const &name) noexcept
Get the named counter.
Definition counters.hpp:35
void add_duration(uint64_t duration) noexcept
Add a duration.
Definition counters.hpp:98
Definition counters.hpp:134
An unfair mutex This is a fast implementation of a mutex which does not fairly arbitrate between mult...
Definition unfair_mutex.hpp:33
T max(T... args)