rotor
Event loop friendly C++ actor micro-framework
 
Loading...
Searching...
No Matches
forwarder.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 "rotor/actor_base.h"
10#include "rotor/asio/supervisor_asio.h"
11#include <boost/asio.hpp>
12#include <tuple>
13
14namespace rotor::asio {
15
16namespace {
17namespace to {
18struct supervisor {};
19} // namespace to
20} // namespace
21} // namespace rotor::asio
22
23namespace rotor {
24
26template <> inline auto &actor_base_t::access<asio::to::supervisor>() noexcept { return supervisor; }
27
28namespace asio {
29
30namespace asio = boost::asio;
31
32namespace details {
33
34namespace count {
35using _0 = std::integral_constant<size_t, 0>;
36using _1 = std::integral_constant<size_t, 1>;
37} // namespace count
38
40template <typename T> struct callback_traits {};
41
43template <typename Class, typename M> struct callback_traits<void (Class::*)(M &) noexcept> {
45 using args_count = count::_1;
46
48 using arg_type = M &;
49};
50
52template <typename Class, typename M> struct callback_traits<void (Class::*)(M) noexcept> {
54 using args_count = count::_1;
55
57 using arg_type = M;
58};
59
61template <typename Class> struct callback_traits<void (Class::*)() noexcept> {
63 using args_count = count::_0;
64
66 using arg_type = void;
67};
68
69} // namespace details
70
72template <typename Actor> inline boost::asio::io_context::strand &get_strand(Actor &actor);
73
75template <typename Actor, typename Handler, typename ErrHandler> struct forwarder_base_t;
76
78template <typename Actor, typename Handler> struct forwarder_base_t<Actor, Handler, void> {
81
84
86 forwarder_base_t(Actor &actor_, Handler &&handler_) : typed_actor{&actor_}, handler{std::move(handler_)} {}
87
90
92 Handler handler;
93};
94
96template <typename Actor, typename Handler, typename ErrHandler>
97struct forwarder_base_t : forwarder_base_t<Actor, Handler, void> {
100
104 forwarder_base_t(Actor &actor_, Handler &&handler_, ErrHandler &&err_handler_)
105 : base_t{actor_, std::move(handler_)}, err_handler{std::move(err_handler_)} {}
106
108 ErrHandler err_handler;
109};
110
111template <typename Actor, typename Handler, typename ArgsCount, typename ErrHandler> struct forwarder_t {};
112
121template <typename Actor, typename Handler, typename ErrHandler>
122struct forwarder_t<Actor, Handler, details::count::_0, ErrHandler> : forwarder_base_t<Actor, Handler, ErrHandler> {
125 using base_t::base_t;
126
130 template <typename T = void> inline void operator()(const boost::system::error_code &ec) noexcept {
131 auto &typed_actor = base_t::typed_actor;
132 auto &sup = static_cast<supervisor_asio_t &>(typed_actor->get_supervisor());
133 auto &strand = get_strand(sup);
134 if (ec) {
135 asio::defer(strand, [actor = base_t::typed_actor, handler = std::move(base_t::err_handler), ec]() {
136 ((*actor).*handler)(ec);
137 actor->get_supervisor().do_process();
138 });
139 } else {
140 asio::defer(strand, [actor = base_t::typed_actor, handler = std::move(base_t::handler)]() {
141 ((*actor).*handler)();
142 actor->get_supervisor().do_process();
143 });
144 }
145 }
146};
147
149template <typename Actor, typename Handler, typename ErrHandler>
150struct forwarder_t<Actor, Handler, details::count::_1, ErrHandler> : forwarder_base_t<Actor, Handler, ErrHandler> {
153 using base_t::base_t;
154
158 template <typename T> inline void operator()(const boost::system::error_code &ec, T arg) noexcept {
159 auto &typed_actor = base_t::typed_actor;
160 auto &sup = static_cast<supervisor_asio_t &>(typed_actor->get_supervisor());
161 auto &strand = get_strand(sup);
162 if (ec) {
163 asio::defer(strand, [actor = base_t::typed_actor, handler = std::move(base_t::err_handler), ec = ec]() {
164 ((*actor).*handler)(ec);
165 actor->get_supervisor().do_process();
166 });
167 } else {
168 asio::defer(strand, [actor = base_t::typed_actor, handler = std::move(base_t::handler),
169 arg = std::move(arg)]() mutable {
170 ((*actor).*handler)(std::move(arg));
171 actor->get_supervisor().do_process();
172 });
173 }
174 }
175};
176
178template <typename Actor, typename Handler>
179struct forwarder_t<Actor, Handler, details::count::_0, void> : forwarder_base_t<Actor, Handler, void> {
182 using base_t::base_t;
183
187 template <typename T = void> inline void operator()() noexcept {
188 auto &typed_actor = base_t::typed_actor;
189 auto &sup = static_cast<supervisor_asio_t &>(typed_actor->get_supervisor());
190 auto &strand = get_strand(sup);
191 asio::defer(strand, [actor = base_t::typed_actor, handler = std::move(base_t::handler)]() {
192 ((*actor).*handler)();
193 actor->get_supervisor().do_process();
194 });
195 }
196};
197
199template <typename Actor, typename Handler>
200struct forwarder_t<Actor, Handler, details::count::_1, void> : forwarder_base_t<Actor, Handler, void> {
203 using base_t::base_t;
204
208 template <typename T> inline void operator()(T arg) noexcept {
209 auto &typed_actor = base_t::typed_actor;
210 auto &sup = static_cast<supervisor_asio_t &>(typed_actor->get_supervisor());
211 auto &strand = get_strand(sup);
212 asio::defer(strand, [actor = base_t::typed_actor, handler = std::move(base_t::handler),
213 arg = std::move(arg)]() mutable {
214 ((*actor).*handler)(std::move(arg));
215 actor->get_supervisor().do_process();
216 });
217 }
218};
219
221template <typename Actor, typename Handler>
222forwarder_t(Actor &, Handler &&)
224
226template <typename Actor, typename Handler, typename ErrHandler>
227forwarder_t(Actor &, Handler &&, ErrHandler &&)
229
230} // namespace asio
231
232} // namespace rotor
namespace for boost::asio adapters for rotor
Definition asio.hpp:22
boost::asio::io_context::strand & get_strand(Actor &actor)
return strand of the boost::asio aware actor
Definition supervisor_asio.h:132
Basic namespace for all rotor functionalities.
Definition rotor.hpp:21
boost::intrusive_ptr< T > intrusive_ptr_t
alias for intrusive pointer
Definition arc.hpp:27
M & arg_type
argument type is a reference
Definition forwarder.hpp:48
count::_1 args_count
number of arguments for asio callback (1)
Definition forwarder.hpp:45
M arg_type
argument type is a value
Definition forwarder.hpp:57
count::_1 args_count
number of arguments for asio callback (1)
Definition forwarder.hpp:54
void arg_type
argument type is missing (void)
Definition forwarder.hpp:66
count::_0 args_count
number of arguments for asio callback (0)
Definition forwarder.hpp:63
asio callback decomposer into 1 possible argument type and total arguments count (0 or 1)
Definition forwarder.hpp:40
partial specialization of forwarder base when there is no error handler
Definition forwarder.hpp:78
typed_actor_ptr_t typed_actor
Definition forwarder.hpp:89
Handler handler
Definition forwarder.hpp:92
forwarder_base_t(Actor &actor_, Handler &&handler_)
constructs forwarder_base for the actor from it handler function
Definition forwarder.hpp:86
intrusive_ptr_t< Actor > typed_actor_ptr_t
alias for intrusive pointer for an actor type
Definition forwarder.hpp:80
templated forwarder base class
Definition forwarder.hpp:97
ErrHandler err_handler
Definition forwarder.hpp:108
forwarder_base_t(Actor &actor_, Handler &&handler_, ErrHandler &&err_handler_)
constructs forwarder_base for the actor from it's member functions: positive result handler and error...
Definition forwarder.hpp:104
void operator()(const boost::system::error_code &ec) noexcept
mimics boost::asio handler, which will be forwarded/decomposed into two different methods of the acto...
Definition forwarder.hpp:130
void operator()() noexcept
mimics boost::asio handler, which will be forwarded/decomposed into two different methods of the acto...
Definition forwarder.hpp:187
void operator()(const boost::system::error_code &ec, T arg) noexcept
mimics boost::asio handler, which will be forwarded/decomposed into two different methods of the acto...
Definition forwarder.hpp:158
void operator()(T arg) noexcept
mimics boost::asio handler, which will be forwarded to the appropriate actor's member method.
Definition forwarder.hpp:208
Definition forwarder.hpp:111
delivers rotor-messages on top of boost asio event loop using strand for serialization
Definition supervisor_asio.h:56