1/* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16// Autogenerated file -- DO NOT EDIT! 17 18#ifndef PANDA_EVENTS_GEN_H 19#define PANDA_EVENTS_GEN_H 20 21#include "macros.h" 22#include "os/mutex.h" 23#include "utils/list.h" 24#include "runtime/include/mem/panda_string.h" 25#include <fstream> 26#include <variant> 27#include <vector> 28 29namespace panda { 30 31namespace events { 32 33% EventsData.events.each do |event| 34% event.fields.select(&:is_enum?).each do |field| 35enum class <%= field.type %> { 36 <%= field.enums.map(&:upcase).join(', ') %> 37}; 38% end 39% end 40 41class EventsBase { 42public: 43 EventsBase() = default; 44 virtual ~EventsBase() = default; 45 NO_COPY_SEMANTIC(EventsBase); 46 NO_MOVE_SEMANTIC(EventsBase); 47 48% EventsData.events.each do |event| 49 virtual void <%= event.name.camelize %>(<%= event.fields.map {|f| f.arg_type}.join(', ') %>) {} // NOLINT 50% end 51 52 auto& GetLock() { 53 return lock_; 54 } 55private: 56 os::memory::Mutex lock_; 57}; 58 59% EventsData.events.each do |event| 60% event.fields.select(&:is_enum?).each do |field| 61inline std::ostream& operator<<(std::ostream& os, <%= field.type %> field) { 62 switch (field) { 63% field.enums.each do |enum| 64 case <%= field.type %>::<%= enum.upcase %>: os << "<%= enum.upcase %>"; break; 65% end 66 } 67 return os; 68} 69% end 70% end 71 72class EventsMemory : public events::EventsBase { 73 74public: 75% EventsData.events.each do |event| 76 struct <%= event.name.camelize %>Event{ 77% event.fields.each do |field| 78 <%= field.type %> <%= field.name %>; 79% end 80 }; 81% end 82 83 // NOLINTNEXTLINE(fuchsia-multiple-inheritance) 84 struct EventRecord : public ListNode, public std::variant<<%= EventsData.events.map{|e| e.name.camelize + 'Event'}.join(', ') %>> { 85 using VariantBase = std::variant<<%= EventsData.events.map{|e| e.name.camelize + 'Event'}.join(', ') %>>; 86% EventsData.events.each do |event| 87 explicit EventRecord(<%= event.name.camelize %>Event v) : VariantBase(v) {} 88% end 89 }; 90 91public: 92 EventsMemory() = default; 93 ~EventsMemory() override { 94 os::memory::LockHolder lock(GetLock()); 95 for (auto it = event_list_.begin(); it != event_list_.end(); ) { 96 delete &*(it++); 97 } 98 } 99 NO_COPY_SEMANTIC(EventsMemory); 100 NO_MOVE_SEMANTIC(EventsMemory); 101 102% EventsData.events.each do |event| 103 void <%= event.name.camelize %>(<%= event.fields.map {|f| f.arg_type + ' ' + f.name }.join(', ') %>) override { 104 os::memory::LockHolder lock(GetLock()); 105 auto event = new EventRecord(<%= event.name.camelize %>Event{<%= event.fields.map(&:name).join(', ') %>}); 106 last_ = event_list_.InsertAfter(last_, *event); 107 } 108% end 109 110 template<typename EventT, typename Func> 111 void EnumerateEvents(Func func) { 112 os::memory::LockHolder lock(GetLock()); 113 for (const auto& event : event_list_) { 114 if(auto p = std::get_if<EventT>(&event)) { 115 func(static_cast<const EventT&>(*p)); 116 } 117 } 118 } 119 120 template<typename EventT, typename Comp> 121 bool Find(Comp cmp) { 122 bool found = false; 123 EnumerateEvents<EventT>([&found, &cmp](const auto& event) { 124 if (cmp(event)) { 125 found = true; 126 return false; 127 } 128 return true; 129 }); 130 return found; 131 } 132 133 template<typename EventT, typename F = bool> 134 std::vector<const EventT*> Select([[maybe_unused]] F pred = false) { 135 std::vector<const EventT*> res; 136 if constexpr (std::is_same_v<F, bool>) { 137 EnumerateEvents<EventT>([&res](const auto& event) { res.push_back(&event); }); 138 } else { 139 EnumerateEvents<EventT>([&pred, &res](const auto& event) { 140 if (pred(&event)) { 141 res.push_back(&event); 142 } 143 }); 144 } 145 return res; 146 } 147 148private: 149 List<EventRecord> event_list_ GUARDED_BY(GetLock()); 150 List<EventRecord>::Iterator last_{event_list_.before_begin()}; 151}; 152 153class EventsCsv : public events::EventsBase { 154public: 155 EventsCsv() { 156 file_.open("events.csv"); 157 } 158 explicit EventsCsv(std::string_view path) { 159 file_.open(path.data()); 160 } 161 ~EventsCsv() override { 162 os::memory::LockHolder lock(GetLock()); 163 file_.close(); 164 } 165 NO_COPY_SEMANTIC(EventsCsv); 166 NO_MOVE_SEMANTIC(EventsCsv); 167 168% EventsData.events.each do |event| 169 void <%= event.name.camelize %>(<%= event.fields.map {|f| f.arg_type + ' ' + f.name }.join(', ') %>) override { 170 os::memory::LockHolder lock(GetLock()); 171 file_ << "<%= event.name.camelize %>," << <%= event.fields.map(&:name).join(" << ',' << ") %> << std::endl; 172 } 173% end 174 175private: 176 std::ofstream file_ GUARDED_BY(GetLock()); 177}; 178 179class EventsLog : public events::EventsBase { 180public: 181 EventsLog() { 182 Logger::EnableComponent(Logger::EVENTS); 183 } 184 ~EventsLog() override { 185 Logger::DisableComponent(Logger::EVENTS); 186 } 187 NO_COPY_SEMANTIC(EventsLog); 188 NO_MOVE_SEMANTIC(EventsLog); 189 190% EventsData.events.each do |event| 191 void <%= event.name.camelize %>(<%= event.fields.map {|f| f.arg_type + ' ' + f.name }.join(', ') %>) override { 192 LOG(INFO, EVENTS) << "<%= event.name.camelize %>," << <%= event.fields.map(&:name).join(" << ',' << ") %>; 193 } 194% end 195}; 196 197} // namespace events 198 199class Events { 200public: 201 enum StreamKind { CSV, MEMORY, LOG }; 202 203 template<StreamKind kind, typename... Args> 204 static void Create(Args&&... args) { 205 if constexpr (kind == StreamKind::CSV) { // NOLINT 206 pevents = new events::EventsCsv(std::forward<Args>(args)...); 207 } else if constexpr (kind == StreamKind::MEMORY) { // NOLINT 208 pevents = new events::EventsMemory; 209 } else if constexpr (kind == StreamKind::LOG) { // NOLINT 210 pevents = new events::EventsLog; 211 } else { // NOLINT 212 UNREACHABLE(); 213 } 214 } 215 216 template<typename... Args> 217 static void Create(std::string_view output, Args&&... args) { 218 if (output == "csv") { 219 pevents = new events::EventsCsv(std::forward<Args>(args)...); 220 } else if (output == "memory") { 221 pevents = new events::EventsMemory; 222 } else if (output == "log") { 223 pevents = new events::EventsLog; 224 } else { // NOLINT 225 UNREACHABLE(); 226 } 227 } 228 229 static void Destroy() { 230 delete pevents; 231 pevents = nullptr; 232 } 233 234 template<StreamKind kind> 235 static auto CastTo() { 236 if constexpr (kind == StreamKind::CSV) { // NOLINT 237 return static_cast<events::EventsCsv*>(pevents); 238 } else if constexpr (kind == StreamKind::MEMORY) { // NOLINT 239 return static_cast<events::EventsMemory*>(pevents); 240 } else { // NOLINT 241 UNREACHABLE(); 242 } 243 } 244 245 static bool IsEnabled() { 246 return pevents != nullptr; 247 } 248 249 static events::EventsBase* GetEvents() { 250 return pevents; 251 } 252 253private: 254 static inline events::EventsBase* pevents{nullptr}; 255}; 256 257#ifndef NDEBUG 258 259#define PANDA_EVENTS_ENABLED 260 261% EventsData.events.each do |event| 262% if !event.enable? 263// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 264#define EVENT_<%= event.name.upcase %>_ENABLED 0 265// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 266#define EVENT_<%= event.name.upcase %>(<%= event.fields.map(&:name).join(', ') %>) 267% else 268// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 269#define EVENT_<%= event.name.upcase %>_ENABLED 1 270// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 271#define EVENT_<%= event.name.upcase %>(<%= event.fields.map(&:name).join(', ') %>) \ 272 if (Events::IsEnabled()) { \ 273 Events::GetEvents()-><%= event.name.camelize %>(<%= event.fields.map(&:name).join(', ') %>); \ 274 } 275% end 276% end 277#else 278% EventsData.events.each do |event| 279// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 280#define EVENT_<%= event.name.upcase %>(<%= event.fields.map(&:name).join(', ') %>) 281% end 282#endif 283 284} // namespace panda 285 286#endif // PANDA_EVENTS_GEN_H 287