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