#pragma once #include "src/tuple.hpp" #include #include #include #include #define ZMQ_BUILD_DRAFT_API #include #define FMT_HEADER_ONLY #include #include #include "adapter_base.hpp" #include "port_types.hpp" #include "utils.hpp" using namespace boost::callable_traits; template class PortBase { class AddressedPort_ { public: AddressedPort_(const PortBase *port, const std::string &address) : mc_addr_(address), mc_port_(port) {} template const auto &operator<<(const InType &in) const { mc_port_->send__(mc_addr_, &in, sizeof(InType), typeid(InType).hash_code()); return *this; } private: const std::string mc_addr_; const PortBase *mc_port_; }; 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()(name)), mc_endpoint_hash_(std::hash()(endpoint)) {} 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 &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); } template const PortBase &operator<<(const InType &in) const { send__("", &in, sizeof(InType), typeid(InType).hash_code()); return *this; } // void listen() const { listen__(m_ss_.get_token()); }; virtual void stop() const = 0; template auto &callback(const std::string &name) const { return GetCallbackHelper_>::type>(this).template operator()(name); } protected: virtual void stop__() const = 0; virtual void send__(const std::string &addr, const void *data, size_t size, size_t type_hash) const = 0; virtual void *get_adapter__(const std::string &name, size_t namehash, size_t typehash, size_t cbk_typehash) const = 0; private: const enum port_types_e mc_type_; const std::string mc_name_, mc_endpoint_; const size_t mc_name_hash_, mc_endpoint_hash_; template class GetCallbackHelper_; template class GetCallbackHelper_> { public: GetCallbackHelper_(const PortBase *port) : mc_port_(port) {} template auto &operator()(const std::string &name) const { using ret_type_t = std::remove_cvref_t>>; using arg_type_t = std::tuple_element_t<0, args_t>>; return (*static_cast, Aargs...> *>( mc_port_->get_adapter__(name, std::hash()(name), typeid(arg_type_t).hash_code(), typeid(typename AdapterBase, Aargs...>::callback_type_t).hash_code()))) .callback(); } private: const PortBase *mc_port_; }; };