HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
counters.hpp
1// Copyright Take Vos 2019-2021.
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 tt {
25namespace detail {
26
27class counter {
28public:
35 [[nodiscard]] static counter *get_if(std::string const &name) noexcept
36 {
37 ttlet lock = std::scoped_lock(_mutex);
38 ttlet &map_ = _map.get_or_make();
39 ttlet it = map_.find(name);
40 if (it == map_.cend()) {
41 return nullptr;
42 } else {
43 tt_axiom(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 }
56
57 operator uint64_t() const noexcept
58 {
59 return _total_count.load(std::memory_order::relaxed);
60 }
61
62 static void log() noexcept
63 {
64 ttlet lock = std::scoped_lock(_mutex);
65 log_header();
66 for (ttlet &[string, counter]: _map.get_or_make()) {
67 tt_axiom(counter);
68 counter->log(string);
69 }
70 }
71
72 static void log_header() noexcept;
73
76 void log(std::string const &tag) noexcept;
77
78 counter &operator++() noexcept
79 {
80 _total_count.fetch_add(1, std::memory_order::relaxed);
81 return *this;
82 }
83
84 uint64_t operator++(int) noexcept
85 {
86 return _total_count.fetch_add(1, std::memory_order::relaxed);
87 }
88
91 void add_duration(uint64_t duration) noexcept
92 {
93 _total_count.fetch_add(1, std::memory_order::relaxed);
94 fetch_max(_duration_max, duration, std::memory_order::relaxed);
95 fetch_min(_duration_min, duration, std::memory_order::relaxed);
96
97 // Combine duration with count in a single atomic.
98 tt_axiom(duration <= (std::numeric_limits<uint64_t>::max() >> 10));
99 duration <<= 16;
100 ++duration;
101 _duration_avg.fetch_add(duration, std::memory_order::relaxed);
102 }
103
104protected:
105 using map_type = std::map<std::string, counter *>;
106
110 constinit static inline unfair_mutex_impl<false> _mutex;
111 constinit static inline atomic_unique_ptr<map_type> _map;
112
113 std::atomic<uint64_t> _total_count = 0;
114 std::atomic<uint64_t> _prev_count = 0;
115 std::atomic<uint64_t> _duration_max = 0;
117
123 std::atomic<uint64_t> _duration_avg = 0;
124};
125
126template<basic_fixed_string Tag>
127class tagged_counter : public counter {
128public:
129 tagged_counter() noexcept : counter()
130 {
131 ttlet lock = std::scoped_lock(_mutex);
132 _map.get_or_make()[std::string{Tag}] = this;
133 }
134};
135
136} // namespace detail
137
138template<basic_fixed_string Tag>
139inline detail::tagged_counter<Tag> global_counter;
140
141[[nodiscard]] inline detail::counter *get_global_counter_if(std::string const &name)
142{
143 return detail::counter::get_if(name);
144}
145
146} // namespace tt
STL namespace.
Definition atomic.hpp:43
Definition counters.hpp:27
void add_duration(uint64_t duration) noexcept
Add a duration.
Definition counters.hpp:91
static counter * get_if(std::string const &name) noexcept
Get the named counter.
Definition counters.hpp:35
Definition counters.hpp:127
Definition log.hpp:113
An unfair mutex This is a fast implementation of a mutex which does not fairly arbitrate between mult...
Definition unfair_mutex.hpp:33
T fetch_add(T... args)
T load(T... args)
T max(T... args)