123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- #pragma once
- #include "actor_base.h"
- #include "message.h"
- #include "forward.hpp"
- #include <functional>
- #include <memory>
- #include <typeindex>
- #include <typeinfo>
- #include <type_traits>
- namespace rotor {
- template <typename M, typename F> struct lambda_holder_t {
-
- F fn;
-
- explicit lambda_holder_t(F &&fn_) : fn(std::forward<F>(fn_)) {}
-
- using message_t = M;
-
- using payload_t = typename M::payload_t;
- };
- template <typename M, typename F> constexpr lambda_holder_t<M, F> lambda(F &&fn) {
- return lambda_holder_t<M, F>(std::forward<F>(fn));
- }
- template <typename T> struct handler_traits {};
- template <typename A, typename M> struct handler_traits<void (A::*)(M &)> {
-
- using pointer_t = void (A::*)(M &);
-
- static auto const constexpr has_noexcept =
- noexcept((std::declval<A>().*std::declval<pointer_t>())(std::declval<M &>()));
- static_assert(has_noexcept, "message handler should have 'noexcept' specification");
- };
- template <typename A, typename M> struct handler_traits<void (A::*)(M &) noexcept> {
-
- static auto const constexpr has_valid_message = std::is_base_of_v<message_base_t, M>;
-
- static auto const constexpr is_actor = std::is_base_of_v<actor_base_t, A>;
-
- static auto const constexpr is_plugin = std::is_base_of_v<plugin::plugin_base_t, A>;
-
- static auto const constexpr is_lambda = false;
-
- using message_t = M;
-
- using payload_t = typename M::payload_t;
-
- using backend_t = A;
- static_assert(is_actor || is_plugin, "message handler should be either actor or plugin");
- };
- template <typename M, typename H> struct handler_traits<lambda_holder_t<M, H>> {
-
- static auto const constexpr has_valid_message = std::is_base_of_v<message_base_t, M>;
- static_assert(has_valid_message, "lambda does not process valid message");
-
- static auto const constexpr is_actor = false;
-
- static auto const constexpr is_plugin = false;
-
- static auto const constexpr is_lambda = true;
- };
- struct handler_base_t : public arc_base_t<handler_base_t> {
-
- const void *message_type;
-
- const void *handler_type;
-
- actor_base_t *actor_ptr;
-
- size_t precalc_hash;
-
- explicit handler_base_t(actor_base_t &actor, const void *message_type_, const void *handler_type_) noexcept;
-
- inline bool operator==(const handler_base_t &rhs) const noexcept {
- return handler_type == rhs.handler_type && actor_ptr == rhs.actor_ptr;
- }
-
- virtual void call(message_ptr_t &) noexcept = 0;
-
- virtual handler_ptr_t upgrade(const void *tag) noexcept;
- virtual ~handler_base_t();
-
- virtual bool select(message_ptr_t &) noexcept = 0;
-
- virtual void call_no_check(message_ptr_t &) noexcept = 0;
- };
- struct continuation_t {
-
- virtual void operator()() const noexcept = 0;
- };
- struct handler_intercepted_t : public handler_base_t {
-
- handler_intercepted_t(handler_ptr_t backend_, const void *tag_) noexcept;
- handler_ptr_t upgrade(const void *tag) noexcept override;
- void call(message_ptr_t &) noexcept override;
- bool select(message_ptr_t &message) noexcept override;
- void call_no_check(message_ptr_t &message) noexcept override;
- private:
- handler_ptr_t backend;
- const void *tag;
- };
- namespace details {
- template <typename Handler>
- inline constexpr bool is_actor_handler_v =
- handler_traits<Handler>::is_actor && !handler_traits<Handler>::is_plugin &&
- handler_traits<Handler>::has_valid_message && !handler_traits<Handler>::is_lambda;
- template <typename Handler> inline constexpr bool is_lambda_handler_v = handler_traits<Handler>::is_lambda;
- template <typename Handler>
- inline constexpr bool is_plugin_handler_v =
- handler_traits<Handler>::has_valid_message &&handler_traits<Handler>::is_plugin &&
- !handler_traits<Handler>::is_actor && !handler_traits<Handler>::is_lambda;
- namespace {
- namespace to {
- struct actor {};
- }
- }
- }
- template <> inline auto &plugin::plugin_base_t::access<details::to::actor>() noexcept { return actor; }
- template <typename Handler, typename Enable = void> struct handler_t;
- template <typename Handler>
- struct handler_t<Handler, std::enable_if_t<details::is_actor_handler_v<Handler>>> : public handler_base_t {
-
- static const void *handler_type;
-
- Handler handler;
-
- explicit handler_t(actor_base_t &actor, Handler &&handler_)
- : handler_base_t{actor, final_message_t::message_type, handler_type}, handler{handler_} {}
- void call(message_ptr_t &message) noexcept override {
- if (message->type_index == final_message_t::message_type) {
- auto final_message = static_cast<final_message_t *>(message.get());
- auto &final_obj = static_cast<backend_t &>(*actor_ptr);
- (final_obj.*handler)(*final_message);
- }
- }
- bool select(message_ptr_t &message) noexcept override {
- return message->type_index == final_message_t::message_type;
- }
- void call_no_check(message_ptr_t &message) noexcept override {
- auto final_message = static_cast<final_message_t *>(message.get());
- auto &final_obj = static_cast<backend_t &>(*actor_ptr);
- (final_obj.*handler)(*final_message);
- }
- private:
- using traits = handler_traits<Handler>;
- using backend_t = typename traits::backend_t;
- using final_message_t = typename traits::message_t;
- };
- template <typename Handler>
- const void *handler_t<Handler, std::enable_if_t<details::is_actor_handler_v<Handler>>>::handler_type =
- static_cast<const void *>(typeid(Handler).name());
- template <typename Handler>
- struct handler_t<Handler, std::enable_if_t<details::is_plugin_handler_v<Handler>>> : public handler_base_t {
-
- static const void *handler_type;
-
- plugin::plugin_base_t &plugin;
-
- Handler handler;
-
- explicit handler_t(plugin::plugin_base_t &plugin_, Handler &&handler_)
- : handler_base_t{*plugin_.access<details::to::actor>(), final_message_t::message_type, handler_type},
- plugin{plugin_}, handler{handler_} {}
- void call(message_ptr_t &message) noexcept override {
- if (message->type_index == final_message_t::message_type) {
- auto final_message = static_cast<final_message_t *>(message.get());
- auto &final_obj = static_cast<backend_t &>(plugin);
- (final_obj.*handler)(*final_message);
- }
- }
- bool select(message_ptr_t &message) noexcept override {
- return message->type_index == final_message_t::message_type;
- }
- void call_no_check(message_ptr_t &message) noexcept override {
- auto final_message = static_cast<final_message_t *>(message.get());
- auto &final_obj = static_cast<backend_t &>(plugin);
- (final_obj.*handler)(*final_message);
- }
- private:
- using traits = handler_traits<Handler>;
- using backend_t = typename traits::backend_t;
- using final_message_t = typename traits::message_t;
- };
- template <typename Handler>
- const void *handler_t<Handler, std::enable_if_t<details::is_plugin_handler_v<Handler>>>::handler_type =
- static_cast<const void *>(typeid(Handler).name());
- template <typename Handler, typename M>
- struct handler_t<lambda_holder_t<Handler, M>,
- std::enable_if_t<details::is_lambda_handler_v<lambda_holder_t<Handler, M>>>> : public handler_base_t {
-
- using handler_backend_t = lambda_holder_t<Handler, M>;
-
- handler_backend_t handler;
-
- static const void *handler_type;
-
- explicit handler_t(actor_base_t &actor, handler_backend_t &&handler_)
- : handler_base_t{actor, final_message_t::message_type, handler_type}, handler{std::forward<handler_backend_t>(
- handler_)} {}
- void call(message_ptr_t &message) noexcept override {
- if (message->type_index == final_message_t::message_type) {
- auto final_message = static_cast<final_message_t *>(message.get());
- handler.fn(*final_message);
- }
- }
- bool select(message_ptr_t &message) noexcept override {
- return message->type_index == final_message_t::message_type;
- }
- void call_no_check(message_ptr_t &message) noexcept override {
- auto final_message = static_cast<final_message_t *>(message.get());
- handler.fn(*final_message);
- }
- private:
- using final_message_t = typename handler_backend_t::message_t;
- };
- template <typename Handler, typename M>
- const void *handler_t<lambda_holder_t<Handler, M>,
- std::enable_if_t<details::is_lambda_handler_v<lambda_holder_t<Handler, M>>>>::handler_type =
- static_cast<const void *>(typeid(Handler).name());
- }
- namespace std {
- template <> struct hash<rotor::handler_ptr_t> {
-
- size_t operator()(const rotor::handler_ptr_t &handler) const noexcept { return handler->precalc_hash; }
- };
- }
|