123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- #pragma once
- #include "address.hpp"
- #include "message.h"
- #include "extended_error.h"
- #include "forward.hpp"
- #include <unordered_map>
- namespace rotor {
- struct request_base_t {
-
- request_id_t id;
-
- address_ptr_t reply_to;
-
- address_ptr_t origin;
- };
- template <typename T, typename = void> struct request_wrapper_t {
-
- using request_t = T;
- };
- template <typename T> struct request_wrapper_t<T, std::enable_if_t<std::is_base_of_v<arc_base_t<T>, T>>> {
-
- using request_t = intrusive_ptr_t<T>;
- };
- template <typename T, typename = void> struct request_unwrapper_t {
-
- using request_t = T;
- };
- template <typename T> struct request_unwrapper_t<intrusive_ptr_t<T>> {
-
- using request_t = T;
- };
- template <typename T, typename = void> struct wrapped_request_t : request_base_t {
-
- using request_t = T;
-
- using response_t = typename T::response_t;
-
- template <typename... Args>
- wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_, Args &&...args)
- : request_base_t{id_, reply_to_, origin_}, request_payload{std::forward<Args>(args)...} {}
-
- T request_payload;
- };
- template <typename T> struct cancellation_t {
-
- request_id_t id;
-
- address_ptr_t source;
- };
- template <typename T>
- struct wrapped_request_t<T, std::enable_if_t<std::is_base_of_v<arc_base_t<T>, T>>> : request_base_t {
-
- using raw_request_t = T;
-
- using request_t = intrusive_ptr_t<T>;
-
- using response_t = typename T::response_t;
-
- wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_,
- const request_t &request_)
- : request_base_t{id_, reply_to_, origin_}, request_payload{request_} {}
-
- template <typename... Args, typename E = std::enable_if_t<std::is_constructible_v<raw_request_t, Args...>>>
- wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_, Args &&...args)
- : request_base_t{id_, reply_to_, origin_}, request_payload{new raw_request_t{std::forward<Args>(args)...}} {}
-
- request_t request_payload;
- };
- template <typename Response> struct response_helper_t {
-
- using response_t = Response;
-
- template <typename... Args> static Response construct(Args &&...args) {
- return Response{std::forward<Args>(args)...};
- }
- };
- template <typename Response> struct response_helper_t<intrusive_ptr_t<Response>> {
-
- using res_ptr_t = intrusive_ptr_t<Response>;
-
- using response_t = Response;
-
- template <typename... Args> static res_ptr_t construct(Args &&...args) {
- return res_ptr_t{new Response{std::forward<Args>(args)...}};
- }
-
- template <typename T, typename std::enable_if_t<std::is_same_v<T, res_ptr_t>>> static res_ptr_t construct(T &&ptr) {
- return res_ptr_t{std::forward<T>(ptr)};
- }
- };
- namespace details {
- template <class T, typename... Args> decltype(void(T{std::declval<Args>()...}), std::true_type()) test(int);
- template <class T, typename... Args> std::false_type test(...);
- template <class T, typename... Args> struct is_braces_constructible : decltype(test<T, Args...>(0)) {};
- template <class T, class... Args> constexpr auto is_braces_constructible_v = is_braces_constructible<T, Args...>::value;
- template <typename... Ts> struct size_of_t;
- template <typename T> struct size_of_t<T> : std::is_default_constructible<T> {};
- template <typename T, typename... Ts> struct size_of_t<T, Ts...> : public std::is_constructible<T, Ts...> {};
- template <typename T, typename... Args>
- inline constexpr bool is_somehow_constructible_v =
- std::is_constructible_v<T, Args...> || is_braces_constructible_v<T, Args...>;
- template <typename T, typename E = void, typename... Args>
- struct is_constructible : is_constructible<T, void, E, Args...> {};
- template <typename T> struct is_constructible<T, void> {
-
- static constexpr auto value = std::is_default_constructible_v<T>;
- };
- template <typename T, typename Arg> struct is_constructible<T, Arg> {
-
- static constexpr auto value = is_somehow_constructible_v<T, Arg>;
- };
- template <typename T, typename Arg> struct is_constructible<T, void, Arg> {
-
- static constexpr auto value = is_somehow_constructible_v<T, Arg>;
- };
- template <typename T, typename... Args> struct is_constructible<T, void, Args...> {
-
- static constexpr auto value = is_somehow_constructible_v<T, Args...>;
- };
- template <typename T, typename... Args> inline constexpr bool is_constructible_v = is_constructible<T, Args...>::value;
- }
- template <typename Request> struct wrapped_response_t {
-
- using request_t = typename request_unwrapper_t<Request>::request_t;
-
- using req_message_t = message_t<wrapped_request_t<request_t>>;
-
- using req_message_ptr_t = intrusive_ptr_t<req_message_t>;
-
- using response_t = typename request_t::response_t;
-
- using res_helper_t = response_helper_t<response_t>;
-
- using unwrapped_response_t = typename res_helper_t::response_t;
- static_assert(std::is_default_constructible_v<response_t>, "response type must be default-constructible");
-
- extended_error_ptr_t ee;
-
- req_message_ptr_t req;
-
- response_t res;
-
- wrapped_response_t(const extended_error_ptr_t &ee_, req_message_ptr_t message_)
- : ee{ee_}, req{std::move(message_)} {}
-
- template <typename Response, typename E = std::enable_if_t<std::is_same_v<response_t, std::remove_cv_t<Response>>>>
- wrapped_response_t(req_message_ptr_t message_, const extended_error_ptr_t &ee_, Response &&res_)
- : ee{ee_}, req{std::move(message_)}, res{std::forward<Response>(res_)} {}
-
- template <typename Req, typename... Args,
- typename E1 = std::enable_if_t<std::is_same_v<req_message_ptr_t, std::remove_cv_t<Req>>>,
- typename E2 = std::enable_if_t<details::is_constructible_v<unwrapped_response_t, Args...>>>
- wrapped_response_t(Req &&message_, Args &&...args)
- : ee{}, req{std::forward<Req>(message_)}, res{res_helper_t::construct(std::forward<Args>(args)...)} {}
-
- inline request_id_t request_id() const noexcept { return req->payload.id; }
- };
- typedef message_ptr_t(error_producer_t)(const address_ptr_t &reply_to, message_base_t &msg,
- const extended_error_ptr_t &ec) noexcept;
- struct request_curry_t {
-
- error_producer_t *fn;
-
- address_ptr_t origin;
-
- message_ptr_t request_message;
-
- actor_base_t *source;
- };
- template <typename R> struct request_traits_t {
-
- using request_t = typename request_unwrapper_t<R>::request_t;
-
- struct request {
-
- using type = request_t;
-
- using wrapped_t = wrapped_request_t<type>;
-
- using message_t = rotor::message_t<wrapped_t>;
-
- using message_ptr_t = intrusive_ptr_t<message_t>;
-
- using visitor_t = typename message_t::visitor_t;
- };
-
- struct response {
-
- using wrapped_t = wrapped_response_t<request_t>;
-
- using message_t = rotor::message_t<wrapped_t>;
-
- using message_ptr_t = intrusive_ptr_t<message_t>;
-
- using visitor_t = typename message_t::visitor_t;
- };
-
- struct cancel {
-
- using cancel_payload_t = cancellation_t<request_t>;
-
- using message_t = rotor::message_t<cancel_payload_t>;
-
- using visitor_t = typename message_t::visitor_t;
- };
-
- static message_ptr_t make_error_response(const address_ptr_t &reply_to, message_base_t &message,
- const extended_error_ptr_t &ee) noexcept {
- using reply_message_t = typename response::message_t;
- using request_message_ptr = typename request::message_ptr_t;
- auto &request = static_cast<typename request::message_t &>(message);
- auto req_ptr = request_message_ptr(&request);
- auto raw_reply = new reply_message_t{reply_to, ee, req_ptr};
- return message_ptr_t{raw_reply};
- }
- };
- template <typename T> struct [[nodiscard]] request_builder_t {
-
- template <typename... Args>
- request_builder_t(supervisor_t &sup_, actor_base_t &actor_, const address_ptr_t &destination_,
- const address_ptr_t &reply_to_, Args &&...args);
-
- request_id_t send(const pt::time_duration &send) noexcept;
- private:
- using traits_t = request_traits_t<T>;
- using request_message_t = typename traits_t::request::message_t;
- using request_message_ptr_t = typename traits_t::request::message_ptr_t;
- using response_message_t = typename traits_t::response::message_t;
- using response_message_ptr_t = typename traits_t::response::message_ptr_t;
- using wrapped_res_t = typename traits_t::response::wrapped_t;
- supervisor_t ⊃
- actor_base_t &actor;
- request_id_t request_id;
- const address_ptr_t &destination;
- const address_ptr_t &reply_to;
- bool do_install_handler;
- request_message_ptr_t req;
- address_ptr_t imaginary_address;
- void install_handler() noexcept;
- };
- }
|