rotor
Event loop friendly C++ actor micro-framework
 
Loading...
Searching...
No Matches
request.hpp
1#pragma once
2
3//
4// Copyright (c) 2019-2022 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
5//
6// Distributed under the MIT Software License
7//
8
9#include "address.hpp"
10#include "message.h"
11#include "extended_error.h"
12#include "forward.hpp"
13#include <unordered_map>
14
15namespace rotor {
16
34
43template <typename T, typename = void> struct request_wrapper_t {
45 using request_t = T;
46};
47
49template <typename T> struct request_wrapper_t<T, std::enable_if_t<std::is_base_of_v<arc_base_t<T>, T>>> {
52};
53
62template <typename T, typename = void> struct request_unwrapper_t {
64 using request_t = T;
65};
66
68template <typename T> struct request_unwrapper_t<intrusive_ptr_t<T>> {
70 using request_t = T;
71};
72
80template <typename T, typename = void> struct wrapped_request_t : request_base_t {
82 using request_t = T;
83
85 using response_t = typename T::response_t;
86
89 template <typename... Args>
90 wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_, Args &&...args)
91 : request_base_t{id_, reply_to_, origin_}, request_payload{std::forward<Args>(args)...} {}
92
95};
96
101template <typename T> struct cancellation_t {
104
107};
108
112template <typename T>
113struct wrapped_request_t<T, std::enable_if_t<std::is_base_of_v<arc_base_t<T>, T>>> : request_base_t {
115 using raw_request_t = T;
116
119
121 using response_t = typename T::response_t;
122
128 wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_,
129 const request_t &request_)
130 : request_base_t{id_, reply_to_, origin_}, request_payload{request_} {}
131
134 template <typename... Args, typename E = std::enable_if_t<std::is_constructible_v<raw_request_t, Args...>>>
135 wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_, Args &&...args)
136 : request_base_t{id_, reply_to_, origin_}, request_payload{new raw_request_t{std::forward<Args>(args)...}} {}
137
140};
141
145template <typename Response> struct response_helper_t {
147 using response_t = Response;
148
150 template <typename... Args> static Response construct(Args &&...args) {
151 return Response{std::forward<Args>(args)...};
152 }
153};
154
159template <typename Response> struct response_helper_t<intrusive_ptr_t<Response>> {
162
164 using response_t = Response;
165
167 template <typename... Args> static res_ptr_t construct(Args &&...args) {
168 return res_ptr_t{new Response{std::forward<Args>(args)...}};
169 }
170
172 template <typename T, typename std::enable_if_t<std::is_same_v<T, res_ptr_t>>> static res_ptr_t construct(T &&ptr) {
173 return res_ptr_t{std::forward<T>(ptr)};
174 }
175};
176
177namespace details {
178
179template <class T, typename... Args> decltype(void(T{std::declval<Args>()...}), std::true_type()) test(int);
180
181template <class T, typename... Args> std::false_type test(...);
182
183template <class T, typename... Args> struct is_braces_constructible : decltype(test<T, Args...>(0)) {};
184
185template <class T, class... Args> constexpr auto is_braces_constructible_v = is_braces_constructible<T, Args...>::value;
186
187template <typename... Ts> struct size_of_t;
188template <typename T> struct size_of_t<T> : std::is_default_constructible<T> {};
189template <typename T, typename... Ts> struct size_of_t<T, Ts...> : public std::is_constructible<T, Ts...> {};
190
191template <typename T, typename... Args>
192inline constexpr bool is_somehow_constructible_v =
193 std::is_constructible_v<T, Args...> || is_braces_constructible_v<T, Args...>;
194
196template <typename T, typename E = void, typename... Args>
197struct is_constructible : is_constructible<T, void, E, Args...> {};
198
200template <typename T> struct is_constructible<T, void> {
202 static constexpr auto value = std::is_default_constructible_v<T>;
203};
204
206template <typename T, typename Arg> struct is_constructible<T, Arg> {
208 static constexpr auto value = is_somehow_constructible_v<T, Arg>;
209};
210
212template <typename T, typename Arg> struct is_constructible<T, void, Arg> {
214 static constexpr auto value = is_somehow_constructible_v<T, Arg>;
215};
216
218template <typename T, typename... Args> struct is_constructible<T, void, Args...> {
220 static constexpr auto value = is_somehow_constructible_v<T, Args...>;
221};
222
223template <typename T, typename... Args> inline constexpr bool is_constructible_v = is_constructible<T, Args...>::value;
224
225} // namespace details
226
234template <typename Request> struct wrapped_response_t {
237
240
243
245 using response_t = typename request_t::response_t;
246
249
252
253 static_assert(std::is_default_constructible_v<response_t>, "response type must be default-constructible");
254
257
260
263
266 : ee{ee_}, req{std::move(message_)} {}
267
274 template <typename Response, typename E = std::enable_if_t<std::is_same_v<response_t, std::remove_cv_t<Response>>>>
275 wrapped_response_t(req_message_ptr_t message_, const extended_error_ptr_t &ee_, Response &&res_)
276 : ee{ee_}, req{std::move(message_)}, res{std::forward<Response>(res_)} {}
277
285 template <typename Req, typename... Args,
286 typename E1 = std::enable_if_t<std::is_same_v<req_message_ptr_t, std::remove_cv_t<Req>>>,
287 typename E2 = std::enable_if_t<details::is_constructible_v<unwrapped_response_t, Args...>>>
288 wrapped_response_t(Req &&message_, Args &&...args)
289 : ee{}, req{std::forward<Req>(message_)}, res{res_helper_t::construct(std::forward<Args>(args)...)} {}
290
292 inline request_id_t request_id() const noexcept { return req->payload.id; }
293};
294
297 const extended_error_ptr_t &ec) noexcept;
298
314
318template <typename R> struct request_traits_t {
321
340
357
371
374 const extended_error_ptr_t &ee) noexcept {
375 using reply_message_t = typename response::message_t;
376 using request_message_ptr = typename request::message_ptr_t;
377 auto &request = static_cast<typename request::message_t &>(message);
378 auto req_ptr = request_message_ptr(&request);
379 auto raw_reply = new reply_message_t{reply_to, ee, req_ptr};
380 return message_ptr_t{raw_reply};
381 }
382};
383
387template <typename T> struct [[nodiscard]] request_builder_t {
388
390 template <typename... Args>
391 request_builder_t(supervisor_t &sup_, actor_base_t &actor_, const address_ptr_t &destination_,
392 const address_ptr_t &reply_to_, Args &&...args);
393
399 request_id_t send(const pt::time_duration &send) noexcept;
400
401 private:
403 using request_message_t = typename traits_t::request::message_t;
404 using request_message_ptr_t = typename traits_t::request::message_ptr_t;
405 using response_message_t = typename traits_t::response::message_t;
406 using response_message_ptr_t = typename traits_t::response::message_ptr_t;
407 using wrapped_res_t = typename traits_t::response::wrapped_t;
408
409 supervisor_t &sup;
410 actor_base_t &actor;
411 request_id_t request_id;
412 const address_ptr_t &destination;
413 const address_ptr_t &reply_to;
414 bool do_install_handler;
415 request_message_ptr_t req;
416 address_ptr_t imaginary_address;
417
418 void install_handler() noexcept;
419};
420
421} // namespace rotor
Basic namespace for all rotor functionalities.
Definition rotor.hpp:21
intrusive_ptr_t< message_base_t > message_ptr_t
intrusive pointer for message
Definition message.h:115
message_ptr_t() error_producer_t(const address_ptr_t &reply_to, message_base_t &msg, const extended_error_ptr_t &ec) noexcept
free function type, which produces error response to the original request
Definition request.hpp:296
intrusive_ptr_t< address_t > address_ptr_t
intrusive pointer for address
Definition address.hpp:57
intrusive_ptr_t< extended_error_t > extended_error_ptr_t
intrusive pointer to extended error type
Definition extended_error.h:25
std::size_t request_id_t
timer identifier type in the scope of the actor
Definition forward.hpp:34
boost::intrusive_ptr< T > intrusive_ptr_t
alias for intrusive pointer
Definition arc.hpp:27
universal primitive of concurrent computation
Definition actor_base.h:47
Request cancellation payload.
Definition request.hpp:101
request_id_t id
unique (per supervisor) request id
Definition request.hpp:103
address_ptr_t source
actor address, which initiated the request
Definition request.hpp:106
Definition request.hpp:183
main helper to check constructability of T from Args...
Definition request.hpp:197
Definition request.hpp:187
Base class for rotor message.
Definition message.h:52
struct visitor_t concrete message type visitor
Definition message.h:93
the generic message meant to hold user-specific payload
Definition message.h:80
base class for request payload
Definition request.hpp:20
address_ptr_t origin
the source (original) actor address, which made an request
Definition request.hpp:32
address_ptr_t reply_to
destination address for reply
Definition request.hpp:29
request_id_t id
unique (per supervisor) request id
Definition request.hpp:22
builder pattern implementation for the original request
Definition request.hpp:387
the recorded context, which is needed to produce error response to the original request
Definition request.hpp:301
actor_base_t * source
actor, on which behalf the original request has been made
Definition request.hpp:312
message_ptr_t request_message
the original request message
Definition request.hpp:309
error_producer_t * fn
the free function, which produces error response
Definition request.hpp:303
address_ptr_t origin
destination address for the error response
Definition request.hpp:306
cancel request related types
Definition request.hpp:360
typename message_t::visitor_t visitor_t
alias for concrete message type visitor
Definition request.hpp:369
request related types
Definition request.hpp:324
intrusive_ptr_t< message_t > message_ptr_t
intrusive pointer type for request message
Definition request.hpp:335
typename message_t::visitor_t visitor_t
alias for concrete message type visitor
Definition request.hpp:338
request_t type
alias for possibly wrapped (to intrusive pointer) request payload type
Definition request.hpp:326
response related types
Definition request.hpp:343
rotor::message_t< wrapped_t > message_t
message type for wrapped response
Definition request.hpp:349
typename message_t::visitor_t visitor_t
alias for concrete message type visitor
Definition request.hpp:355
intrusive_ptr_t< message_t > message_ptr_t
intrusive pointer type for response message
Definition request.hpp:352
type helper to deduce request/response messages from original (user-supplied) request type
Definition request.hpp:318
typename request_unwrapper_t< R >::request_t request_t
alias for original request payload type
Definition request.hpp:320
static message_ptr_t make_error_response(const address_ptr_t &reply_to, message_base_t &message, const extended_error_ptr_t &ee) noexcept
helper free function to produce error reply to the original request
Definition request.hpp:373
T request_t
an alias for the original request type, if it was wrapped into intrusive poitner
Definition request.hpp:70
optionally unwraps request type from intrusive pointer
Definition request.hpp:62
T request_t
an alias for the original request type
Definition request.hpp:64
intrusive_ptr_t< T > request_t
an alias for the original request type, wrapped into intrusive pointer
Definition request.hpp:51
optionally wraps request type into intrusive pointer
Definition request.hpp:43
T request_t
an alias for the original request type
Definition request.hpp:45
static res_ptr_t construct(Args &&...args)
constructs intrusive pointer to user defined response payload
Definition request.hpp:167
static res_ptr_t construct(T &&ptr)
constructs user defined response payload and wraps it into intrusive pointer
Definition request.hpp:172
intrusive_ptr_t< Response > res_ptr_t
type for intrusive pointer user defined response payload
Definition request.hpp:161
Response response_t
Definition request.hpp:164
generic helper, which helps to construct user-defined response payload
Definition request.hpp:145
static Response construct(Args &&...args)
constructs user defined response payload
Definition request.hpp:150
Response response_t
Definition request.hpp:147
supervisor is responsible for managing actors (workers) lifetime
Definition supervisor.h:69
intrusive_ptr_t< T > request_t
alias for original request payload type wrapped into intrusive pointer
Definition request.hpp:118
request_t request_payload
intrusive pointer to user-supplied payload
Definition request.hpp:139
wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_, const request_t &request_)
makes an intrusive pointer for already constructed user-supplied payload
Definition request.hpp:128
T raw_request_t
alias for original (unwrapped) request payload type
Definition request.hpp:115
wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_, Args &&...args)
constructs wrapper for user-supplied payload from request-id and and destination reply address
Definition request.hpp:135
typename T::response_t response_t
alias for original (unwrapped) response payload type
Definition request.hpp:121
templated request, which is able to hold user-supplied payload
Definition request.hpp:80
T request_t
alias for original (unwrapped) request payload type
Definition request.hpp:82
wrapped_request_t(request_id_t id_, const address_ptr_t &reply_to_, const address_ptr_t &origin_, Args &&...args)
constructs wrapper for user-supplied payload from request-id and and destination reply address
Definition request.hpp:90
T request_payload
original, user-supplied payload
Definition request.hpp:94
typename T::response_t response_t
alias for original (unwrapped) response payload type
Definition request.hpp:85
trackable templated response which holds user-supplied response payload.
Definition request.hpp:234
req_message_ptr_t req
original request message, which contains request_id for request/response matching
Definition request.hpp:259
extended_error_ptr_t ee
pointer to extended error, used in the case of response failure
Definition request.hpp:256
typename request_t::response_t response_t
alias for possibly wrapped user-supplied response type
Definition request.hpp:245
intrusive_ptr_t< req_message_t > req_message_ptr_t
alias for intrusive pointer to message with wrapped request
Definition request.hpp:242
wrapped_response_t(const extended_error_ptr_t &ee_, req_message_ptr_t message_)
error-response constructor (response payload is empty)
Definition request.hpp:265
typename request_unwrapper_t< Request >::request_t request_t
alias for original user-supplied request type
Definition request.hpp:236
response_t res
user-supplied response payload
Definition request.hpp:262
wrapped_response_t(Req &&message_, Args &&...args)
successful-response constructor.
Definition request.hpp:288
typename res_helper_t::response_t unwrapped_response_t
alias user-supplied response type
Definition request.hpp:251
wrapped_response_t(req_message_ptr_t message_, const extended_error_ptr_t &ee_, Response &&res_)
"forward-constructor"
Definition request.hpp:275
request_id_t request_id() const noexcept
returns request id of the original request
Definition request.hpp:292