openMSX
utils
ProfileCounters.hh
Go to the documentation of this file.
1
#ifndef PROFILECOUNTERS_HH
2
#define PROFILECOUNTERS_HH
3
4
#include "
enumerate.hh
"
5
#include <array>
6
#include <iostream>
7
8
//
9
// Quick and dirty reflection on C++ enums (in the future replace with c++23 reflexpr).
10
//
11
12
// Print an enum type as a string, for example:
13
// os << EnumTypeName<SomeEnumType>() << '\n';
14
template
<
typename
E>
struct
EnumTypeName
{};
15
// You _must_ overload 'operator<<' for all enum types for which you want this to work.
16
template
<
typename
E> std::ostream&
operator<<
(std::ostream& os,
EnumTypeName<E>
) =
delete
;
17
18
// Print an enum value as a string, for example:
19
// os << EnumValueName{myEnumValue} << '\n';
20
template
<
typename
E>
struct
EnumValueName
21
{
22
EnumValueName
(
E
e_) :
e
(e_) {}
23
E
e
;
24
};
25
// You _must_ overload 'operator<<' for all enum types for which you want this to work.
26
template
<
typename
E> std::ostream&
operator<<
(std::ostream& os,
EnumValueName<E>
evn) =
delete
;
27
28
29
30
31
// A collection of (simple) profile counters:
32
// - Counters start at zero.
33
// - An individual counter can be incremented by 1 via 'tick(<counter-id>)'.
34
// - When this 'ProfileCounters' object is destroyed it prints the value of each
35
// counter.
36
//
37
// Template parameters:
38
// - bool ENABLED:
39
// when false, the optimizer should be able to completely optimize-out all
40
// profile related code
41
// - typename ENUM:
42
// Must be a c++ enum (or enum class) which satisfies the following requirements:
43
// * The numerical values must be 0, 1, ... IOW the values must be usable as
44
// indices in an array. (This is automatically the case if you don't
45
// manually assign numeric values).
46
// * There must be an enum value with the name 'NUM' which has a numerical
47
// value equal to the number of other values in this enum. (This is
48
// automatically the case if you put 'NUM' last in the list of enum
49
// values).
50
// * You must overload the following two functions for the type 'ENUM':
51
// std::ostream& operator<<(std::ostream& os, EnumTypeName<ENUM>);
52
// std::ostream& operator<<(std::ostream& os, EnumValueName<ENUM> evn);
53
//
54
// Example usage:
55
// enum class WidgetProfileCounter {
56
// CALCULATE,
57
// INVALIDATE,
58
// NUM // must be last
59
// };
60
// std::ostream& operator<<(std::ostream& os, EnumTypeName<WidgetProfileCounter>)
61
// {
62
// return os << "WidgetProfileCounter";
63
// }
64
// std::ostream& operator<<(std::ostream& os, EnumValueName<WidgetProfileCounter> evn)
65
// {
66
// std::string_view names[size_t(WidgetProfileCounter::NUM)] = {
67
// "calculate"sv, "invalidate"sv
68
// };
69
// return os << names[size_t(evn.e)];
70
// }
71
//
72
// constexpr bool PRINT_WIDGET_PROFILE = true; // possibly depending on some #define
73
//
74
// struct Widget : private ProfileCounters<PRINT_WIDGET_PROFILE, WidgetProfileCounter>
75
// {
76
// void calculate() {
77
// tick(WidgetProfileCounter::CALCULATE);
78
// // ...
79
// }
80
// void invalidate() {
81
// tick(WidgetProfileCounter::CALCULATE);
82
// // ...
83
// }
84
// };
85
86
template
<
bool
ENABLED,
typename
ENUM>
87
class
ProfileCounters
88
{
89
public
:
90
// Print counters on destruction.
91
~ProfileCounters
() {
92
std::cout <<
"-- Profile counters: "
<<
EnumTypeName<ENUM>
() <<
" -- "
<<
static_cast<
void
*
>
(
this
) <<
'\n'
;
93
for
(
auto
[i, count] :
enumerate
(counters)) {
94
std::cout <<
EnumValueName
{ENUM(i)} <<
": "
<< count <<
'\n'
;
95
}
96
}
97
98
// Increment
99
void
tick
(ENUM
e
)
const
{
100
++counters[size_t(
e
)];
101
}
102
103
private
:
104
static
constexpr
auto
NUM = size_t(
ENUM::NUM
);
// value 'ENUM::NUM' must exist
105
mutable
std::array<unsigned, NUM> counters = {};
106
};
107
108
109
// Specialization for when profiling is disabled.
110
// This class is simple enough so that it can be completely optimized away.
111
template
<
typename
ENUM>
112
class
ProfileCounters
<false, ENUM>
113
{
114
public
:
115
void
tick
(ENUM)
const
{
/*nothing*/
}
116
};
117
118
#endif
operator<<
std::ostream & operator<<(std::ostream &os, EnumTypeName< E >)=delete
ProfileCounters< false, ENUM >::tick
void tick(ENUM) const
Definition:
ProfileCounters.hh:115
ProfileCounters
Definition:
ProfileCounters.hh:88
ProfileCounters::tick
void tick(ENUM e) const
Definition:
ProfileCounters.hh:99
ProfileCounters::~ProfileCounters
~ProfileCounters()
Definition:
ProfileCounters.hh:91
enumerate.hh
enumerate
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
Definition:
enumerate.hh:28
Math::e
constexpr double e
Definition:
Math.hh:21
openmsx::CacheLine::NUM
constexpr unsigned NUM
Definition:
CacheLine.hh:8
openmsx::E
@ E
Definition:
CPUCore.cc:213
EnumTypeName
Definition:
ProfileCounters.hh:14
EnumValueName
Definition:
ProfileCounters.hh:21
EnumValueName::e
E e
Definition:
ProfileCounters.hh:23
EnumValueName::EnumValueName
EnumValueName(E e_)
Definition:
ProfileCounters.hh:22
Generated on Sun Dec 10 2023 15:13:14 for openMSX by
1.9.4