• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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