-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathi-accept-scoped-notes.h
128 lines (108 loc) · 4.29 KB
/
i-accept-scoped-notes.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//
#ifndef I_ACCEPT_SCOPED_NOTES_H
#define I_ACCEPT_SCOPED_NOTES_H
/// \file
/// \brief Accept scoped notes interface
#include <cstdarg>
#include <cstdint>
#include <type_traits>
#include "assert-printf.h"
#include "i-state-access.h"
#include "i-uarch-state-access.h"
#include "meta.h"
#include "scoped-note.h"
namespace cartesi {
/// \class i_accept_scoped_notes
/// \brief Interface that lets a state access class accept scoped notes.
/// \tparam DERIVED Derived class implementing the interface. (An example of CRTP.)
template <typename DERIVED>
class i_accept_scoped_notes { // CRTP
/// \brief Returns object cast as the derived class
DERIVED &derived() {
return *static_cast<DERIVED *>(this);
}
/// \brief Returns object cast as the derived class
const DERIVED &derived() const {
return *static_cast<const DERIVED *>(this);
}
public:
/// \brief Works as vprintf if we are dumping scoped notes, otherwise does nothing
static void dsn_vprintf([[maybe_unused]] const char *fmt, [[maybe_unused]] va_list ap) {
#ifdef DUMP_SCOPED_NOTE
if constexpr (is_an_i_state_access_v<DERIVED>) {
DERIVED::dsa_vprintf(fmt, ap);
} else if (is_an_i_uarch_state_access_v<DERIVED>) {
DERIVED::dusa_vprintf(fmt, ap);
} else {
d_vprintf(fmt, ap);
}
#endif
}
/// \brief Works as printf if we are dumping scoped notes, otherwise does nothing
// Better to use C-style variadic function that checks for format!
// NOLINTNEXTLINE(cert-dcl50-cpp)
__attribute__((__format__(__printf__, 1, 2))) static void dsn_printf([[maybe_unused]] const char *fmt, ...) {
#ifdef DUMP_SCOPED_NOTE
va_list ap;
va_start(ap, fmt);
dsn_vprintf(fmt, ap);
va_end(ap);
#endif
}
/// \brief Adds a begin bracket annotation to the log
/// \param text String with the text for the annotation
void push_begin_bracket(const char *text) const {
derived().do_push_begin_bracket(text);
dsn_printf("----> begin %s (%s)\n", text, derived().get_name());
}
/// \brief Adds an end bracket annotation to the log
/// \param text String with the text for the annotation
void push_end_bracket(const char *text) const {
derived().do_push_end_bracket(text);
dsn_printf("<---- end %s (%s)\n", text, derived().get_name());
}
/// \brief Adds annotations to the state, bracketing a scope
/// \param text String with the text for the annotation
/// \returns An object that, when constructed and destroyed issues an annonation.
auto make_scoped_note(const char *text) const {
return derived().do_make_scoped_note(text);
}
protected:
// Default implementation for classes that do not use scoped notes
// (It still will dump the scoped notes when requested)
auto do_make_scoped_note([[maybe_unused]] const char *text) const {
#ifdef DUMP_SCOPED_NOTE
return scoped_note{*this, text};
#else
return 0;
#endif
}
void do_push_begin_bracket(const char * /*text*/) const {
;
}
void do_push_end_bracket(const char * /*text*/) const {
;
}
};
/// \brief SFINAE test implementation of the i_accept_scoped_notes interface
template <typename DERIVED>
using is_an_i_accept_scoped_notes =
std::integral_constant<bool, is_template_base_of_v<i_accept_scoped_notes, std::remove_cvref_t<DERIVED>>>;
template <typename DERIVED>
constexpr bool is_an_i_accept_scoped_note_v = is_an_i_accept_scoped_notes<DERIVED>::value;
} // namespace cartesi
#endif