adding compiler

This commit is contained in:
Oleg Shishlyannikov 2025-12-01 23:58:27 +03:00
parent 394ece667d
commit 2af4150ce2
18 changed files with 123 additions and 52 deletions

View File

@ -1,2 +1,2 @@
CompileFlags:
Add: ['-std=gnu++23']
Add: ['-std=gnu++23', -I/opt/cling/include]

View File

@ -19,6 +19,14 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(inja)
# FetchContent_Declare(
# json
# GIT_REPOSITORY https://github.com/nlohmann/json
# GIT_PROGRESS TRUE
# GIT_TAG main
# )
# FetchContent_MakeAvailable(json)
FetchContent_Declare(
libzmq

View File

@ -37,7 +37,6 @@ public:
virtual callback_type_t &callback() const = 0;
inline const auto &name() const { return mc_name_; }
protected:
private:
const std::string mc_name_;
};

View File

@ -32,9 +32,9 @@ public:
using port_data_type_t = std::tuple_element_t<0, std::tuple<return_type_t<typename Adapters::encoder_type_t>...>>;
using callback_aargs_t = tp::tuple_tail<args_t<typename std::tuple_element_t<0, std::tuple<Adapters...>>::callback_type_t::signature_type>>::type;
Port(enum port_types_e pt, const std::string &name, const std::string &endpoint, zmq::context_t &zmq_ctx, std::tuple<std::unique_ptr<Adapters>...> &&adapters,
std::tuple<Args...> &&args)
: PortBase<port_data_type_t>(pt, name, endpoint, zmq_ctx),
Port(enum port_types_e pt, const std::string &name, const std::map<std::string, std::string> &endpoints, zmq::context_t &zmq_ctx,
std::tuple<std::unique_ptr<Adapters>...> &&adapters, std::tuple<Args...> &&args)
: PortBase<port_data_type_t>(pt, name, endpoints, zmq_ctx),
// Init adapters
mc_adapters_([&]<size_t... Ids>(std::index_sequence<Ids...>) {
@ -50,7 +50,7 @@ public:
typeid(adapter_callback_type_t).hash_code(), std::forward<std::unique_ptr<adapter_type_t>>(std::get<Idx>(adapters)));
}.template operator()<Ids>()...);
}(std::make_index_sequence<sizeof...(Adapters)>{})) {
std::apply([&, this](auto &&...args) { init_impl_(pt, zmq_ctx, std::move(endpoint), std::forward<Args>(args)...); }, std::forward<decltype(args)>(args));
std::apply([&, this](auto &&...args) { init_impl_(pt, zmq_ctx, std::move(endpoints), std::forward<Args>(args)...); }, std::forward<decltype(args)>(args));
}
~Port() override { stop(); }

View File

@ -34,16 +34,15 @@ template <typename EncodedType> class PortBase {
};
public:
PortBase(enum port_types_e port_type, const std::string &name, const std::string &endpoint, zmq::context_t &zmq_ctx)
: mc_type_(port_type), mc_name_(name), mc_endpoint_(endpoint), mc_name_hash_(std::hash<std::string>()(name)), mc_endpoint_hash_(std::hash<std::string>()(endpoint)) {}
PortBase(enum port_types_e port_type, const std::string &name, const std::map<std::string, std::string> &endpoints, zmq::context_t &zmq_ctx)
: mc_type_(port_type), mc_name_(name), mc_endpoints_(endpoints), mc_name_hash_(std::hash<std::string>()(name)) {}
virtual ~PortBase() = default;
inline const auto &type() const { return mc_type_; }
inline const auto &name() const { return mc_name_; }
inline const auto &endpoint() const { return mc_endpoint_; }
inline const auto &endpoints() const { return mc_endpoints_; }
inline const auto &name_hash() const { return mc_name_hash_; }
inline const auto &endpoint_hash() const { return mc_endpoint_hash_; }
const auto operator[](const std::string &address) const { return AddressedPort_(this, address); }
@ -52,9 +51,7 @@ public:
return *this;
}
// void listen() const { listen__(m_ss_.get_token()); };
virtual void stop() const = 0;
template <typename Signature> auto &callback(const std::string &name) const {
return GetCallbackHelper_<typename tp::tuple_tail<args_t<Signature>>::type>(this).template operator()<Signature>(name);
}
@ -66,8 +63,9 @@ protected:
private:
const enum port_types_e mc_type_;
const std::string mc_name_, mc_endpoint_;
const size_t mc_name_hash_, mc_endpoint_hash_;
const std::string mc_name_;
const std::map<std::string, std::string> mc_endpoints_;
const size_t mc_name_hash_;
template <typename...> class GetCallbackHelper_;
template <typename... Aargs> class GetCallbackHelper_<std::tuple<Aargs...>> {

View File

@ -9,8 +9,8 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::DEALER, Port, Callback> : public PortImplBase<Port, Callback> {
public:
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)) {}
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {}
// Send to socket depending on implementation
void send(const std::string &addr, const msgpack::sbuffer &data) const override {};

View File

@ -3,8 +3,8 @@
#include "port.hpp"
template <typename... Adapters, typename... Args>
auto makePort(enum port_types_e pt, const std::string &name, const std::string &endpoint, zmq::context_t &zmq_ctx, std::tuple<std::unique_ptr<Adapters>...> &&adapters,
std::tuple<Args...> &&args = {}) {
return std::make_unique<Port<std::tuple<Adapters...>, std::tuple<Args...>>>(pt, name, endpoint, zmq_ctx, std::forward<std::tuple<std::unique_ptr<Adapters>...>>(adapters),
auto makePort(enum port_types_e pt, const std::string &name, const std::map<std::string, std::string> &endpoints, zmq::context_t &zmq_ctx,
std::tuple<std::unique_ptr<Adapters>...> &&adapters, std::tuple<Args...> &&args = {}) {
return std::make_unique<Port<std::tuple<Adapters...>, std::tuple<Args...>>>(pt, name, endpoints, zmq_ctx, std::forward<std::tuple<std::unique_ptr<Adapters>...>>(adapters),
std::forward<std::tuple<Args...>>(args));
}

View File

@ -18,8 +18,8 @@ public:
MSGPACK_DEFINE(typehash, data);
};
PortImplBase(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: mc_endpoint__(endpoint), m_ctx__(zmq_ctx), mc_cbk__(callback), mc_port__(port) {}
PortImplBase(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: mc_endpoints__(endpoints), m_ctx__(zmq_ctx), mc_cbk__(callback), mc_port__(port) {}
virtual ~PortImplBase() = default;
virtual void send(const std::string &addr, const msgpack::sbuffer &data) const = 0;
@ -38,7 +38,7 @@ protected:
mutable std::future<void> m_listener_thread__;
mutable zmq::socket_t m_sock__;
zmq::context_t &m_ctx__;
const std::string mc_endpoint__;
const std::map<std::string, std::string> mc_endpoints__;
const Callback mc_cbk__;
const Port *mc_port__;
virtual void listen__(std::stop_token st) const = 0;

View File

@ -9,8 +9,14 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::PAIR, Port, Callback> : public PortImplBase<Port, Callback> {
public:
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)) {}
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {
this->m_sock__ = zmq::socket_t(this->m_ctx__, zmq::socket_type::push);
for (const auto &[_, ep] : this->mc_endpoints__) {
this->m_sock__.bind(ep);
}
}
// Send to socket depending on implementation
void send(const std::string &addr, const msgpack::sbuffer &data) const override {};

View File

@ -9,10 +9,13 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::PUB, Port, Callback> final : public PortImplBase<Port, Callback> {
public:
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)) {
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {
this->m_sock__ = zmq::socket_t(this->m_ctx__, zmq::socket_type::pub);
this->m_sock__.bind(this->mc_endpoint__);
for (const auto &[_, ep] : this->mc_endpoints__) {
this->m_sock__.bind(ep);
}
}
~PortImpl() override {}

View File

@ -12,10 +12,13 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::PULL, Port, Callback> : public PortImplBase<Port, Callback> {
public:
using base_t = PortImplBase<Port, Callback>;
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)) {
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {
this->m_sock__ = zmq::socket_t(this->m_ctx__, zmq::socket_type::pull);
this->m_sock__.connect(this->mc_endpoint__);
for (const auto &[_, ep] : this->mc_endpoints__) {
this->m_sock__.connect(ep);
}
listen__(this->stop_source().get_token());
}

View File

@ -9,10 +9,13 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::PUSH, Port, Callback> : public PortImplBase<Port, Callback> {
public:
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)) {
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {
this->m_sock__ = zmq::socket_t(this->m_ctx__, zmq::socket_type::push);
this->m_sock__.bind(this->mc_endpoint__);
for (const auto &[_, ep] : this->mc_endpoints__) {
this->m_sock__.bind(ep);
}
}
// Send to socket depending on implementation

View File

@ -16,10 +16,12 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::REP, Port, Callback> : public PortImplBase<Port, Callback> {
public:
using base_t = PortImplBase<Port, Callback>;
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)) {
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {
this->m_sock__ = zmq::socket_t(this->m_ctx__, zmq::socket_type::rep);
this->m_sock__.bind(this->mc_endpoint__);
for (const auto &[_, ep] : this->mc_endpoints__) {
this->m_sock__.bind(ep);
}
listen__(this->stop_source().get_token());
}

View File

@ -2,6 +2,7 @@
#include "port_impl_base.hpp"
#include "port_types.hpp"
#include <stdexcept>
#define FMT_HEADER_ONLY
#include <fmt/format.h>
@ -10,10 +11,13 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::REQ, Port, Callback> : public PortImplBase<Port, Callback> {
public:
using base_t = PortImplBase<Port, Callback>;
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)) {
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {
this->m_sock__ = zmq::socket_t(this->m_ctx__, zmq::socket_type::req);
this->m_sock__.connect(this->mc_endpoint__);
for (const auto &[_, ep] : this->mc_endpoints__) {
this->m_sock__.connect(ep);
}
}
void send(const std::string &addr, const msgpack::sbuffer &data) const override {

View File

@ -9,8 +9,8 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::ROUTER, Port, Callback> : public PortImplBase<Port, Callback> {
public:
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)) {}
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {}
// Send to socket depending on implementation
void send(const std::string &addr, const msgpack::sbuffer &data) const override {};

View File

@ -16,10 +16,13 @@
template <typename Port, typename Callback> class PortImpl<port_types_e::SUB, Port, Callback> : public PortImplBase<Port, Callback> {
public:
using base_t = PortImplBase<Port, Callback>;
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::string &endpoint, const std::list<std::string> &topics, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoint, std::forward<Callback>(callback)), mc_topics_(topics) {
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, const std::list<std::string> &topics, Callback &&callback)
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)), mc_topics_(topics) {
this->m_sock__ = zmq::socket_t(this->m_ctx__, zmq::socket_type::sub);
this->m_sock__.connect(this->mc_endpoint__);
for (const auto &[_, ep] : this->mc_endpoints__) {
this->m_sock__.connect(ep);
}
for (const auto &topic : mc_topics_) {
this->m_sock__.set(zmq::sockopt::subscribe, topic);

View File

@ -8,11 +8,29 @@ enum class port_types_e : uint32_t {
SUB,
REQ,
REP,
ROUTER,
DEALER,
PUSH,
PULL,
PAIR,
RADIO,
DISH,
ROUTER,
DEALER,
};
template <enum port_types_e, typename...> class PortImpl;
struct endpoints_base_s {};
template <auto> struct endpoints_s;
template<> struct endpoints_s<port_types_e::PUB> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::SUB> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::REQ> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::REP> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::PUSH> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::PULL> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::PAIR> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::RADIO> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::DISH> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::ROUTER> : endpoints_base_s {};
template<> struct endpoints_s<port_types_e::DEALER> : endpoints_base_s {};

View File

@ -119,7 +119,11 @@ int main(int argc, char *argv[], char *envp[]) {
// TODO: merge all builders to one complex "Module" builder
auto publisher_module = makeModule(argc, argv, envp, "publisher_module", zmq_ctx,
std::tuple{
makePort(PUB, "publisher_port", "inproc://PUB-SUB" /* This port will publish messages here */, zmq_ctx,
makePort(PUB, "publisher_port",
{
{"test", "inproc://PUB-SUB"},
} /* This port will publish messages here */,
zmq_ctx,
std::tuple{
AdapterBuilder()
.encodeDataBy(&codecs.encoders.from_int)
@ -147,7 +151,11 @@ int main(int argc, char *argv[], char *envp[]) {
// Make module that contains only 1 port working on SUBSCRIBER pattern
auto subscriber_module = makeModule(argc, argv, envp, "subscriber_module", zmq_ctx,
std::tuple{
makePort(SUB, "subscriber_port", "inproc://PUB-SUB" /* this port will read data here */, zmq_ctx,
makePort(SUB, "subscriber_port",
{
{"test", "inproc://PUB-SUB"},
} /* this port will read data here */,
zmq_ctx,
std::tuple{
AdapterBuilder()
.encodeDataBy(&codecs.encoders.from_int)
@ -180,7 +188,11 @@ int main(int argc, char *argv[], char *envp[]) {
auto pusher_module = makeModule(argc, argv, envp, "pusher_module", zmq_ctx,
std::tuple{
makePort(PUSH, "push_port", "inproc://PUSH-PULL" /* This port will publish messages here */, zmq_ctx,
makePort(PUSH, "push_port",
{
{"test", "inproc://PUSH-PULL"},
} /* This port will publish messages here */,
zmq_ctx,
std::tuple{
AdapterBuilder()
.encodeDataBy(&codecs.encoders.from_int)
@ -207,7 +219,11 @@ int main(int argc, char *argv[], char *envp[]) {
auto puller_module = makeModule(argc, argv, envp, "puller_module", zmq_ctx,
std::tuple{
makePort(PULL, "pull_port", "inproc://PUSH-PULL" /* This port will publish messages here */, zmq_ctx,
makePort(PULL, "pull_port",
{
{"test", "inproc://PUSH-PULL"},
} /* This port will publish messages here */,
zmq_ctx,
std::tuple{
AdapterBuilder()
.encodeDataBy(&codecs.encoders.from_int)
@ -234,7 +250,11 @@ int main(int argc, char *argv[], char *envp[]) {
auto req_module = makeModule(argc, argv, envp, "req_module", zmq_ctx,
std::tuple{
makePort(REQ, "req_port", "inproc://REQ-REP" /* This port will publish messages here */, zmq_ctx,
makePort(REQ, "req_port",
{
{"test", "inproc://REQ-REP"},
} /* This port will publish messages here */,
zmq_ctx,
std::tuple{
AdapterBuilder()
.encodeDataBy(&codecs.encoders.from_int)
@ -261,7 +281,11 @@ int main(int argc, char *argv[], char *envp[]) {
auto rep_module = makeModule(argc, argv, envp, "rep_module", zmq_ctx,
std::tuple{
makePort(REP, "rep_port", "inproc://REQ-REP" /* This port will publish messages here */, zmq_ctx,
makePort(REP, "rep_port",
{
{"test", "inproc://REQ-REP"},
} /* This port will publish messages here */,
zmq_ctx,
std::tuple{
AdapterBuilder()
.encodeDataBy(&codecs.encoders.from_int)