280 lines
8.4 KiB
C++
280 lines
8.4 KiB
C++
#ifndef AAB5E4D2_A05B_4F2F_B76A_406A5A569D55
|
|
#define AAB5E4D2_A05B_4F2F_B76A_406A5A569D55
|
|
|
|
#include "mana_api.hpp"
|
|
#include "mana_arena.h"
|
|
#include <cassert>
|
|
#include <chrono>
|
|
#include <mesytec-mnode/mnode_cpp_types.h>
|
|
#include <mesytec-mnode/mnode_string.hpp>
|
|
#include <mesytec-mvlc/cpp_compat.h>
|
|
#include <mesytec-mvlc/util/data_filter.h>
|
|
#include <nlohmann/json.hpp>
|
|
|
|
namespace mesytec::mnode::mana
|
|
{
|
|
|
|
namespace detail
|
|
{
|
|
inline void set(mana_offset_ptr_t &ptr, void *p)
|
|
{
|
|
assert(p != reinterpret_cast<u8 *>(&ptr) + 1);
|
|
|
|
if (p)
|
|
{
|
|
ptr.offset = reinterpret_cast<u8 *>(p) - reinterpret_cast<u8 *>(&ptr);
|
|
// spdlog::info("detail::set: &ptr={}, p={}, offset={}", fmt::ptr(&ptr), fmt::ptr(p),
|
|
// ptr.offset);
|
|
}
|
|
else
|
|
{
|
|
ptr.offset = 1;
|
|
}
|
|
}
|
|
} // namespace detail
|
|
|
|
inline bool is_null(const mana_offset_ptr_t &ptr) { return ptr.offset == 1; }
|
|
|
|
inline void *get(mana_offset_ptr_t &ptr)
|
|
{
|
|
return is_null(ptr) ? nullptr : reinterpret_cast<u8 *>(&ptr) + ptr.offset;
|
|
}
|
|
|
|
template <typename T> T *get(mana_offset_ptr_t &ptr); // to catch unsupported types
|
|
|
|
template <typename T> T *get_(mana_offset_ptr_t &ptr, mana_data_type_t expected)
|
|
{
|
|
if (ptr.data_type != expected)
|
|
return nullptr;
|
|
|
|
return reinterpret_cast<T *>(get(ptr));
|
|
}
|
|
|
|
template <> u32 *get(mana_offset_ptr_t &ptr) { return get_<u32>(ptr, mana_uint32); }
|
|
template <> u64 *get(mana_offset_ptr_t &ptr) { return get_<u64>(ptr, mana_uint64); }
|
|
template <> s8 *get(mana_offset_ptr_t &ptr) { return get_<s8>(ptr, mana_sint8); }
|
|
template <> char *get(mana_offset_ptr_t &ptr) { return get_<char>(ptr, mana_sint8); }
|
|
template <> float *get(mana_offset_ptr_t &ptr) { return get_<float>(ptr, mana_float); }
|
|
template <> double *get(mana_offset_ptr_t &ptr) { return get_<double>(ptr, mana_double); }
|
|
|
|
inline void set(mana_offset_ptr_t &ptr, mana_data_type_t data_type, void *p)
|
|
{
|
|
ptr.data_type = data_type;
|
|
detail::set(ptr, p);
|
|
}
|
|
|
|
inline void set(mana_offset_ptr_t &ptr, std::nullptr_t) { set(ptr, mana_uint32, nullptr); }
|
|
inline void set(mana_offset_ptr_t &ptr, u32 *p) { set(ptr, mana_uint32, p); }
|
|
inline void set(mana_offset_ptr_t &ptr, u64 *p) { set(ptr, mana_uint64, p); }
|
|
inline void set(mana_offset_ptr_t &ptr, s8 *p) { set(ptr, mana_sint8, p); }
|
|
inline void set(mana_offset_ptr_t &ptr, char *p) { set(ptr, mana_sint8, p); }
|
|
inline void set(mana_offset_ptr_t &ptr, float *p) { set(ptr, mana_float, p); }
|
|
inline void set(mana_offset_ptr_t &ptr, double *p) { set(ptr, mana_double, p); }
|
|
|
|
template <typename T>
|
|
T *push_offset_array(mana::Arena &arena, mana_offset_array_t &dest, size_t size)
|
|
{
|
|
T *ptr = arena.push_t<T>(size);
|
|
mana::set(dest.ptr, mana_custom, ptr);
|
|
dest.size_bytes = size * sizeof(T);
|
|
return ptr;
|
|
}
|
|
|
|
template <typename T>
|
|
T *push_typed_offset_array(mana::Arena &arena, mana_offset_array_t &dest, size_t size)
|
|
{
|
|
T *ptr = arena.push_t<T>(size);
|
|
mana::set(dest.ptr, ptr);
|
|
dest.size_bytes = size * sizeof(T);
|
|
return ptr;
|
|
}
|
|
|
|
template <typename T> size_t element_count(mana_offset_array_t &array)
|
|
{
|
|
return array.size_bytes / sizeof(T);
|
|
}
|
|
|
|
template <typename T> mvlc::util::span<T> get_span(mana_offset_array_t &array)
|
|
{
|
|
auto ptr = reinterpret_cast<T *>(get(array.ptr));
|
|
auto size = element_count<T>(array);
|
|
return {ptr, size};
|
|
}
|
|
|
|
inline nlohmann::json make_array_descriptor(const std::string &name, mana_data_type_t data_type,
|
|
size_t size, size_t bits = 0)
|
|
{
|
|
nlohmann::json j;
|
|
j["name"] = name;
|
|
j["data_type"] = data_type;
|
|
j["size"] = size;
|
|
j["bits"] = bits;
|
|
return j;
|
|
}
|
|
|
|
inline nlohmann::json make_array_descriptor(const std::string &name, const std::string &bit_filter)
|
|
{
|
|
auto f = mvlc::util::make_filter_with_caches(bit_filter);
|
|
size_t size = 1;
|
|
|
|
if (auto c = mvlc::util::get_cache_entry(f, 'A'))
|
|
size = 1u << c->extractBits;
|
|
|
|
size_t bits = 0;
|
|
|
|
if (auto c = mvlc::util::get_cache_entry(f, 'D'))
|
|
bits = c->extractBits;
|
|
|
|
return make_array_descriptor(name, mana_float, size, bits);
|
|
}
|
|
|
|
class ManaSinkPerfProxy: public IManaSink
|
|
{
|
|
public:
|
|
struct Perf
|
|
{
|
|
using clock = std::chrono::high_resolution_clock;
|
|
using time_point = std::chrono::time_point<clock>;
|
|
using duration = std::chrono::microseconds;
|
|
template <typename T> static duration duration_cast(const T &dt)
|
|
{
|
|
return std::chrono::duration_cast<duration>(dt);
|
|
}
|
|
std::vector<size_t> eventHits;
|
|
std::vector<size_t> eventBytes;
|
|
duration dt_init;
|
|
duration dt_shutdown;
|
|
duration dt_beginRun;
|
|
duration dt_endRun;
|
|
std::vector<duration> dt_processEvent;
|
|
time_point t_beginRun;
|
|
time_point t_endRun;
|
|
};
|
|
|
|
explicit ManaSinkPerfProxy(IManaSink *sink)
|
|
: sink_(sink)
|
|
{
|
|
}
|
|
|
|
const Perf &perf() const { return perf_; }
|
|
|
|
void init(int plugin_argc, const char **plugin_argv) override
|
|
{
|
|
auto t = Perf::clock::now();
|
|
sink_->init(plugin_argc, plugin_argv);
|
|
perf_.dt_init = Perf::duration_cast(Perf::clock::now() - t);
|
|
}
|
|
|
|
void shutdown() override
|
|
{
|
|
auto t = Perf::clock::now();
|
|
sink_->shutdown();
|
|
perf_.dt_shutdown = Perf::duration_cast(Perf::clock::now() - t);
|
|
}
|
|
|
|
void begin_run(const char *descriptor_json) override
|
|
{
|
|
perf_.eventHits.clear();
|
|
perf_.eventBytes.clear();
|
|
perf_.dt_beginRun = perf_.dt_endRun = {};
|
|
perf_.dt_processEvent.clear();
|
|
perf_.t_endRun = {};
|
|
|
|
auto t = Perf::clock::now();
|
|
sink_->begin_run(descriptor_json);
|
|
perf_.t_beginRun = Perf::clock::now();
|
|
perf_.dt_beginRun = Perf::duration_cast(Perf::clock::now() - t);
|
|
}
|
|
|
|
void end_run(const char *descriptor_json) override
|
|
{
|
|
auto t = Perf::clock::now();
|
|
sink_->end_run(descriptor_json);
|
|
perf_.t_endRun = Perf::clock::now();
|
|
perf_.dt_endRun = Perf::duration_cast(perf_.t_endRun - t);
|
|
}
|
|
|
|
void process_event(uint16_t eventIndex, mana_offset_array_t *arrays, size_t arrayCount,
|
|
size_t totalBytes) override
|
|
{
|
|
size_t size = eventIndex + 1;
|
|
perf_.eventHits.resize(std::max(perf_.eventHits.size(), size));
|
|
perf_.eventBytes.resize(std::max(perf_.eventBytes.size(), size));
|
|
perf_.dt_processEvent.resize(std::max(perf_.dt_processEvent.size(), size));
|
|
|
|
auto t = Perf::clock::now();
|
|
sink_->process_event(eventIndex, arrays, arrayCount, totalBytes);
|
|
auto dt = Perf::duration_cast(Perf::clock::now() - t);
|
|
|
|
perf_.eventHits[eventIndex]++;
|
|
perf_.eventBytes[eventIndex] += totalBytes;
|
|
perf_.dt_processEvent[eventIndex] += dt;
|
|
}
|
|
|
|
void process_system_event(const uint32_t *data, size_t size) override
|
|
{
|
|
sink_->process_system_event(data, size);
|
|
}
|
|
|
|
private:
|
|
IManaSink *sink_;
|
|
Perf perf_;
|
|
};
|
|
|
|
// wraps a mana_api.h mana_sink_plugin_t instance
|
|
struct ManaCSink: public IManaSink
|
|
{
|
|
mana_sink_plugin_t plugin_;
|
|
void *context_ = nullptr;
|
|
|
|
explicit ManaCSink(mana_sink_plugin_t plugin)
|
|
: plugin_(plugin)
|
|
{
|
|
}
|
|
|
|
void init(int plugin_argc, const char **plugin_argv) override
|
|
{
|
|
context_ = plugin_.init(plugin_argc, plugin_argv);
|
|
}
|
|
void shutdown() override { plugin_.shutdown(context_); }
|
|
void begin_run(const char *descriptor_json) override
|
|
{
|
|
plugin_.begin_run(context_, descriptor_json);
|
|
}
|
|
void end_run(const char *descriptor_json) override
|
|
{
|
|
plugin_.end_run(context_, descriptor_json);
|
|
}
|
|
void process_event(uint16_t eventIndex, mana_offset_array_t *arrays, size_t arrayCount,
|
|
size_t totalBytes) override
|
|
{
|
|
plugin_.process_event(context_, eventIndex, arrays, arrayCount, totalBytes);
|
|
}
|
|
void process_system_event(const uint32_t *data, size_t size) override
|
|
{
|
|
plugin_.process_system_event(context_, data, size);
|
|
}
|
|
};
|
|
|
|
struct ObjectPath
|
|
{
|
|
std::string path;
|
|
std::string objectName;
|
|
std::vector<std::string> components;
|
|
|
|
ObjectPath(const std::string &path, const std::string &sep = "\\.")
|
|
: path(path)
|
|
{
|
|
split_string(path, std::regex(sep), std::back_inserter(components));
|
|
|
|
if (!components.empty())
|
|
{
|
|
objectName = components.back();
|
|
components.pop_back();
|
|
}
|
|
}
|
|
};
|
|
|
|
} // namespace mesytec::mnode::mana
|
|
|
|
#endif /* AAB5E4D2_A05B_4F2F_B76A_406A5A569D55 */
|