9 #ifndef EAGINE_MESSAGE_BUS_INVOKER_HPP
10 #define EAGINE_MESSAGE_BUS_INVOKER_HPP
12 #include "../callable_ref.hpp"
13 #include "../serialize/block_sink.hpp"
14 #include "../serialize/block_source.hpp"
24 class result_context {
27 const message_context& msg_ctx,
32 , _invocation_id{invc_id} {}
34 auto msg_context() const noexcept -> const message_context& {
42 auto invocation_id() const noexcept {
43 return _invocation_id;
47 const message_context& _msg_ctx;
52 template <
typename Result,
typename Deserializer,
typename Source,
bool NoExcept>
53 class callback_invoker_base {
56 auto fulfill_by(
const message_context& msg_ctx, stored_message& response)
60 _source.reset(response.content());
61 Deserializer read_backend(_source);
63 if(response.has_serializer_id(read_backend.type_id())) {
64 const auto errors{
deserialize(result, read_backend)};
66 const result_context res_ctx{
67 msg_ctx, response.source_id, response.sequence_no};
68 _callback(res_ctx, std::move(result));
76 callable_ref<void(
const result_context&, Result&&) noexcept(NoExcept)>;
77 _callback_t _callback{};
83 template <
typename Deserializer,
typename Source,
bool NoExcept>
84 class callback_invoker_base<void, Deserializer, Source, NoExcept> {
87 auto fulfill_by(
const message_context& msg_ctx, stored_message& response)
89 const result_context res_ctx{
90 msg_ctx, response.source_id, response.sequence_no};
96 using _callback_t = basic_callable_ref<void() noexcept(NoExcept), NoExcept>;
97 _callback_t _callback{};
103 typename Deserializer,
106 std::size_t MaxDataSize>
107 class callback_invoker
108 :
public callback_invoker_base<
109 std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<Signature>>>,
112 is_noexcept_function_v<Signature>> {
115 std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<Signature>>>;
116 using base = callback_invoker_base<
120 is_noexcept_function_v<Signature>>;
121 using _callback_t =
typename base::_callback_t;
126 template <
typename Class,
typename MfcT, MfcT Mfc>
127 auto operator()(Class* that, member_function_constant<MfcT, Mfc> func)
128 -> callback_invoker& {
129 this->_callback = _callback_t{that, func};
133 template <
typename Class,
typename MfcT, MfcT Mfc>
134 auto operator()(
const Class* that, member_function_constant<MfcT, Mfc> func)
135 -> callback_invoker& {
136 this->_callback = _callback_t{that, func};
140 template <
typename... Args>
146 Args&&... args) ->
bool {
147 auto tupl{std::tie(std::forward<Args>(args)...)};
150 Serializer write_backend(_sink);
152 const auto errors =
serialize(tupl, write_backend);
154 message_view
message{_sink.done()};
155 message.set_serializer_id(write_backend.type_id());
156 message.set_target_id(target_id);
157 bus.post(msg_id, message);
164 template <
typename... Args>
169 Args&&... args) ->
bool {
170 std::array<byte, MaxDataSize> temp{};
172 bus, target_id, msg_id,
cover(temp), std::forward<Args>(args)...);
175 constexpr
auto map_fulfill_by(message_id msg_id) noexcept {
181 constexpr
auto operator[](message_id msg_id) noexcept {
182 return map_fulfill_by(msg_id);
189 template <
typename Result,
typename Deserializer,
typename Source>
192 auto fulfill_by(
const message_context&, stored_message& message) ->
bool {
193 const auto invocation_id =
message.sequence_no;
194 std::remove_cv_t<std::remove_reference_t<Result>> result{};
196 _source.reset(
message.content());
197 Deserializer read_backend(_source);
199 if(
message.has_serializer_id(read_backend.type_id())) {
200 const auto errors{
deserialize(result, read_backend)};
202 _results.fulfill(invocation_id, result);
208 constexpr
auto map_fulfill_by(message_id msg_id) noexcept {
215 constexpr
auto operator[](message_id msg_id) noexcept {
216 return map_fulfill_by(msg_id);
219 auto has_pending() const noexcept ->
bool {
220 return _results.has_some();
223 auto is_done() const noexcept ->
bool {
224 return _results.has_none();
228 pending_promises<Result> _results{};
237 typename Deserializer,
240 std::size_t MaxDataSize>
247 typename Deserializer,
250 std::size_t MaxDataSize>
251 class invoker<Result(Params...), Serializer, Deserializer, Sink, Source, MaxDataSize>
252 :
public invoker_base<Result, Deserializer, Source> {
259 std::add_lvalue_reference_t<std::add_const_t<Params>>... args)
261 auto [invocation_id, result] = this->_results.make();
263 auto tupl{std::tie(args...)};
265 block_data_sink sink(buffer);
266 Serializer write_backend(sink);
268 const auto errors =
serialize(tupl, write_backend);
270 message_view
message{sink.done()};
271 message.set_serializer_id(write_backend.type_id());
272 message.set_target_id(target_id);
273 message.set_sequence_no(invocation_id);
274 bus.post(msg_id, message);
285 std::add_lvalue_reference_t<std::add_const_t<Params>>... args)
287 std::array<byte, MaxDataSize> buffer{};
288 return invoke_on(bus, target_id, msg_id,
cover(buffer), args...);
294 std::add_lvalue_reference_t<std::add_const_t<Params>>... args)
303 typename Deserializer,
306 std::size_t MaxDataSize>
307 class invoker<Result(), Serializer, Deserializer, Sink, Source, MaxDataSize>
308 :
public invoker_base<Result, Deserializer, Source> {
315 auto [invocation_id, result] = this->_results.make();
318 message.set_target_id(target_id);
319 message.set_sequence_no(invocation_id);
320 bus.post(msg_id, message);
325 auto invoke_on(endpoint& bus,
identifier_t target_id, message_id msg_id)
327 return invoke_on(bus, target_id, msg_id, {});
330 auto invoke(endpoint& bus, message_id msg_id) -> future<Result> {
337 #endif // EAGINE_MESSAGE_BUS_INVOKER_HPP