88 lines
3.2 KiB
C++
88 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <tuple>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
#include <zmq.hpp>
|
|
|
|
#include "port_base.hpp"
|
|
#include "tuple.hpp"
|
|
|
|
enum class module_type_e : uint32_t {
|
|
STANDALONE,
|
|
INCOMPOSITION,
|
|
};
|
|
|
|
template <typename EnvDataType> class ModuleBase {
|
|
public:
|
|
ModuleBase(int32_t argc, char **argv, char **envp, const std::string &name)
|
|
: mc_name_(name), mc_cli_args_({
|
|
.argc = argc,
|
|
.argv = argv,
|
|
.envp = envp,
|
|
}) {}
|
|
|
|
inline const auto &name() const { return mc_name_; }
|
|
|
|
virtual const PortBase<EnvDataType> &port(const std::string &name) const = 0;
|
|
virtual void run(void (*entry)(int32_t, char **, char **, const std::unordered_map<std::string, const PortBase<EnvDataType> *> &)) const = 0;
|
|
|
|
protected:
|
|
const auto &cli__() const { return mc_cli_args_; }
|
|
|
|
private:
|
|
const std::string mc_name_;
|
|
|
|
const struct {
|
|
int32_t argc;
|
|
char **argv, **envp;
|
|
} mc_cli_args_;
|
|
};
|
|
|
|
template <typename... Ports> class Module : public ModuleBase<std::tuple_element_t<0, std::tuple<typename Ports::port_data_type_t...>>> {
|
|
public:
|
|
using port_data_type_t = std::tuple_element_t<0, std::tuple<typename Ports::port_data_type_t...>>;
|
|
|
|
Module(int32_t argc, char **argv, char **envp, const std::string &name, zmq::context_t &zmq_ctx, std::tuple<std::unique_ptr<Ports>...> &&ports)
|
|
: ModuleBase<port_data_type_t>(argc, argv, envp, name), mc_ports_([&]<size_t... Ids>(std::index_sequence<Ids...>) {
|
|
return std::make_tuple([&]<size_t Idx>() {
|
|
using port_type_t = std::remove_cvref_t<decltype(std::get<Idx>(ports))>;
|
|
auto &port = std::get<Idx>(ports);
|
|
|
|
return std::make_tuple(port->name(), std::hash<std::string>()(port->name()), std::forward<port_type_t>(port));
|
|
}.template operator()<Ids>()...);
|
|
}(std::make_index_sequence<sizeof...(Ports)>{})) {}
|
|
|
|
const PortBase<port_data_type_t> &port(const std::string &name) const override {
|
|
const PortBase<port_data_type_t> *ret = nullptr;
|
|
size_t hash = std::hash<std::string>()(name);
|
|
|
|
tp::for_each(mc_ports_, [&](const auto &p) {
|
|
if (!ret) {
|
|
const auto &[port_name, name_hash, port] = p;
|
|
if (name == port_name) {
|
|
ret = static_cast<const PortBase<port_data_type_t> *>(port.get());
|
|
}
|
|
}
|
|
});
|
|
|
|
if (!ret) {
|
|
throw std::runtime_error(fmt::format("Port with name '{}' not found in '{}' module\r\n", name, this->name()));
|
|
}
|
|
|
|
return *ret;
|
|
}
|
|
|
|
void run(void (*entry)(int32_t, char **, char **, const std::unordered_map<std::string, const PortBase<port_data_type_t> *> &)) const override {
|
|
entry(this->cli__().argc, this->cli__().argv, this->cli__().envp,
|
|
[&]<size_t... Ids>(std::index_sequence<Ids...>) -> std::unordered_map<std::string, const PortBase<port_data_type_t> *> {
|
|
return {std::make_pair(std::get<0u>(std::get<Ids>(ports_())), std::get<2u>(std::get<Ids>(ports_())).get())...};
|
|
}(std::make_index_sequence<std::tuple_size_v<std::remove_cvref_t<decltype(ports_())>>>{}));
|
|
}
|
|
|
|
private:
|
|
inline const auto &ports_() const { return mc_ports_; }
|
|
const std::tuple<std::tuple<std::string, size_t, std::unique_ptr<Ports>>...> mc_ports_;
|
|
};
|