Improve compilation time by 25% by reducing number of template class instantiation.

This commit is contained in:
Ivica Siladic
2023-12-03 11:52:04 +01:00
parent 64a003e2ed
commit d00acde499
13 changed files with 127 additions and 110 deletions

View File

@@ -93,12 +93,17 @@ public:
) { ) {
using Signature = void (error_code, std::string); using Signature = void (error_code, std::string);
auto initiate = [this](auto handler, auth_step_e step, std::string data) { auto initiation = [](
_auth_fun->async_auth(step, std::move(data), std::move(handler)); auto handler, any_authenticator& self,
auth_step_e step, std::string data
) {
self._auth_fun->async_auth(
step, std::move(data), std::move(handler)
);
}; };
return asio::async_initiate<CompletionToken, Signature>( return asio::async_initiate<CompletionToken, Signature>(
initiate, token, step, std::move(data) initiation, token, std::ref(*this), step, std::move(data)
); );
} }
}; };

View File

@@ -15,7 +15,6 @@
#include <async_mqtt5/detail/control_packet.hpp> #include <async_mqtt5/detail/control_packet.hpp>
#include <async_mqtt5/detail/internal_types.hpp> #include <async_mqtt5/detail/internal_types.hpp>
#include <async_mqtt5/impl/internal/codecs/base_decoders.hpp>
#include <async_mqtt5/impl/internal/codecs/message_decoders.hpp> #include <async_mqtt5/impl/internal/codecs/message_decoders.hpp>
@@ -49,19 +48,21 @@ public:
template <typename ClientService, typename Handler> template <typename ClientService, typename Handler>
class assemble_op { class assemble_op {
using client_service = ClientService; using client_service = ClientService;
using handler_type = Handler;
struct on_read {}; struct on_read {};
static constexpr size_t max_packet_size = 65536; static constexpr size_t max_packet_size = 65536;
client_service& _svc; client_service& _svc;
Handler _handler; handler_type _handler;
std::string& _read_buff; std::string& _read_buff;
data_span& _data_span; data_span& _data_span;
public: public:
assemble_op( assemble_op(
client_service& svc, Handler&& handler, client_service& svc, handler_type&& handler,
std::string& read_buff, data_span& active_span std::string& read_buff, data_span& active_span
) : ) :
_svc(svc), _svc(svc),
@@ -77,7 +78,7 @@ public:
return _svc.get_executor(); return _svc.get_executor();
} }
using allocator_type = asio::associated_allocator_t<Handler>; using allocator_type = asio::associated_allocator_t<handler_type>;
allocator_type get_allocator() const noexcept { allocator_type get_allocator() const noexcept {
return asio::get_associated_allocator(_handler); return asio::get_associated_allocator(_handler);
} }
@@ -214,10 +215,7 @@ private:
) { ) {
asio::dispatch( asio::dispatch(
get_executor(), get_executor(),
asio::prepend( asio::prepend(std::move(_handler), ec, control_code, first, last)
std::move(_handler), ec, control_code,
first, last
)
); );
} }
}; };

View File

@@ -24,6 +24,7 @@ template <
> >
class autoconnect_stream { class autoconnect_stream {
public: public:
using self_type = autoconnect_stream<StreamType, StreamContext>;
using stream_type = StreamType; using stream_type = StreamType;
using stream_context_type = StreamContext; using stream_context_type = StreamContext;
using executor_type = typename stream_type::executor_type; using executor_type = typename stream_type::executor_type;
@@ -38,16 +39,16 @@ private:
stream_ptr _stream_ptr; stream_ptr _stream_ptr;
stream_context_type& _stream_context; stream_context_type& _stream_context;
template <typename Stream, typename Handler>
friend class reconnect_op;
template <typename Owner, typename Handler> template <typename Owner, typename Handler>
friend class read_op; friend class read_op;
template <typename Owner, typename Handler> template <typename Owner, typename Handler>
friend class write_op; friend class write_op;
template <typename Owner, typename DisconnectContext, typename Handler> template <typename Stream>
friend class reconnect_op;
template <typename Owner, typename DisconnectContext>
friend class disconnect_op; friend class disconnect_op;
public: public:
@@ -116,16 +117,17 @@ public:
decltype(auto) async_read_some( decltype(auto) async_read_some(
const BufferType& buffer, duration wait_for, CompletionToken&& token const BufferType& buffer, duration wait_for, CompletionToken&& token
) { ) {
auto initiation = [this]( using Signature = void (error_code, size_t);
auto handler, const BufferType& buffer, duration wait_for
auto initiation = [](
auto handler, self_type& self,
const BufferType& buffer, duration wait_for
) { ) {
read_op { *this, std::move(handler) } read_op { self, std::move(handler) }.perform(buffer, wait_for);
.perform(buffer, wait_for);
}; };
return asio::async_initiate<CompletionToken, void (error_code, size_t)>( return asio::async_initiate<CompletionToken, Signature>(
std::move(initiation), token, initiation, token, std::ref(*this), buffer, wait_for
buffer, wait_for
); );
} }
@@ -133,14 +135,16 @@ public:
decltype(auto) async_write( decltype(auto) async_write(
const BufferType& buffer, CompletionToken&& token const BufferType& buffer, CompletionToken&& token
) { ) {
auto initiation = [this]( using Signature = void (error_code, size_t);
auto handler, const BufferType& buffer
auto initiation = [](
auto handler, self_type& self, const BufferType& buffer
) { ) {
write_op { *this, std::move(handler) }.perform(buffer); write_op { self, std::move(handler) }.perform(buffer);
}; };
return asio::async_initiate<CompletionToken, void (error_code, size_t)>( return asio::async_initiate<CompletionToken, Signature>(
std::move(initiation), token, buffer initiation, token, std::ref(*this), buffer
); );
} }
@@ -176,12 +180,14 @@ private:
template <typename CompletionToken> template <typename CompletionToken>
decltype(auto) async_reconnect(stream_ptr s, CompletionToken&& token) { decltype(auto) async_reconnect(stream_ptr s, CompletionToken&& token) {
auto initiation = [this](auto handler, stream_ptr s) { using Signature = void (error_code);
reconnect_op { *this, std::move(handler) }.perform(s);
auto initiation = [](auto handler, self_type& self, stream_ptr s) {
reconnect_op { self, std::move(handler) }.perform(s);
}; };
return asio::async_initiate<CompletionToken, void (error_code)>( return asio::async_initiate<CompletionToken, Signature>(
std::move(initiation), token, s initiation, token, std::ref(*this), s
); );
} }
}; };

View File

@@ -126,6 +126,7 @@ template <
typename TlsContext = std::monostate typename TlsContext = std::monostate
> >
class client_service { class client_service {
using self_type = client_service<StreamType, TlsContext>;
using stream_context_type = stream_context<StreamType, TlsContext>; using stream_context_type = stream_context<StreamType, TlsContext>;
using stream_type = autoconnect_stream< using stream_type = autoconnect_stream<
StreamType, stream_context_type StreamType, stream_context_type
@@ -281,18 +282,21 @@ public:
template <typename CompletionToken> template <typename CompletionToken>
decltype(auto) async_assemble(duration wait_for, CompletionToken&& token) { decltype(auto) async_assemble(duration wait_for, CompletionToken&& token) {
auto initiation = [this] (auto handler, duration wait_for) mutable { using Signature = void (error_code, uint8_t, byte_citer, byte_citer);
auto initiation = [] (
auto handler, self_type& self,
duration wait_for, std::string& read_buff, data_span& active_span
) {
assemble_op { assemble_op {
*this, std::move(handler), self, std::move(handler), read_buff, active_span
_read_buff, _active_span
}.perform(wait_for, asio::transfer_at_least(0)); }.perform(wait_for, asio::transfer_at_least(0));
}; };
using Signature = void (
error_code, uint8_t, byte_citer, byte_citer
);
return asio::async_initiate<CompletionToken, Signature> ( return asio::async_initiate<CompletionToken, Signature> (
std::move(initiation), token, wait_for initiation,
token, std::ref(*this),
wait_for, std::ref(_read_buff), std::ref(_active_span)
); );
} }

View File

@@ -7,26 +7,23 @@
#include <boost/asio/prepend.hpp> #include <boost/asio/prepend.hpp>
#include <boost/asio/read.hpp> #include <boost/asio/read.hpp>
#include <boost/asio/write.hpp> #include <boost/asio/write.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/any_completion_handler.hpp>
#include <boost/beast/websocket.hpp> #include <boost/beast/websocket.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <async_mqtt5/error.hpp> #include <async_mqtt5/error.hpp>
#include <async_mqtt5/detail/async_traits.hpp> #include <async_mqtt5/detail/async_traits.hpp>
#include <async_mqtt5/detail/control_packet.hpp> #include <async_mqtt5/detail/control_packet.hpp>
#include <async_mqtt5/detail/internal_types.hpp> #include <async_mqtt5/detail/internal_types.hpp>
#include <async_mqtt5/impl/internal/codecs/base_decoders.hpp>
#include <async_mqtt5/impl/internal/codecs/message_decoders.hpp> #include <async_mqtt5/impl/internal/codecs/message_decoders.hpp>
#include <async_mqtt5/impl/internal/codecs/message_encoders.hpp> #include <async_mqtt5/impl/internal/codecs/message_encoders.hpp>
namespace async_mqtt5::detail { namespace async_mqtt5::detail {
template < template <typename Stream>
typename Stream, typename Handler
>
class connect_op { class connect_op {
static constexpr size_t min_packet_sz = 5; static constexpr size_t min_packet_sz = 5;
@@ -43,18 +40,22 @@ class connect_op {
Stream& _stream; Stream& _stream;
mqtt_context& _ctx; mqtt_context& _ctx;
Handler _handler;
using handler_type = asio::any_completion_handler<void (error_code)>;
handler_type _handler;
std::unique_ptr<std::string> _buffer_ptr; std::unique_ptr<std::string> _buffer_ptr;
using endpoint = asio::ip::tcp::endpoint; using endpoint = asio::ip::tcp::endpoint;
using epoints = asio::ip::tcp::resolver::results_type; using epoints = asio::ip::tcp::resolver::results_type;
public: public:
template <typename Handler>
connect_op( connect_op(
Stream& stream, Handler&& handler, mqtt_context& ctx Stream& stream, Handler&& handler, mqtt_context& ctx
) : ) :
_stream(stream), _ctx(ctx), _stream(stream), _ctx(ctx),
_handler(std::move(handler)) _handler(std::forward<Handler>(handler))
{} {}
connect_op(connect_op&&) noexcept = default; connect_op(connect_op&&) noexcept = default;
@@ -65,13 +66,13 @@ public:
return _stream.get_executor(); return _stream.get_executor();
} }
using allocator_type = asio::associated_allocator_t<Handler>; using allocator_type = asio::associated_allocator_t<handler_type>;
allocator_type get_allocator() const noexcept { allocator_type get_allocator() const noexcept {
return asio::get_associated_allocator(_handler); return asio::get_associated_allocator(_handler);
} }
using cancellation_slot_type = using cancellation_slot_type =
asio::associated_cancellation_slot_t<Handler>; asio::associated_cancellation_slot_t<handler_type>;
cancellation_slot_type get_cancellation_slot() const noexcept { cancellation_slot_type get_cancellation_slot() const noexcept {
return asio::get_associated_cancellation_slot(_handler); return asio::get_associated_cancellation_slot(_handler);
} }
@@ -233,6 +234,7 @@ public:
auto varlen = decoders::type_parse( auto varlen = decoders::type_parse(
varlen_ptr, _buffer_ptr->cend(), decoders::basic::varint_ varlen_ptr, _buffer_ptr->cend(), decoders::basic::varint_
); );
if (!varlen) if (!varlen)
complete(asio::error::try_again); complete(asio::error::try_again);

View File

@@ -19,8 +19,7 @@ namespace asio = boost::asio;
template < template <
typename ClientService, typename ClientService,
typename DisconnectContext, typename DisconnectContext
typename Handler
> >
class disconnect_op { class disconnect_op {
using client_service = ClientService; using client_service = ClientService;
@@ -29,12 +28,15 @@ class disconnect_op {
std::shared_ptr<client_service> _svc_ptr; std::shared_ptr<client_service> _svc_ptr;
DisconnectContext _context; DisconnectContext _context;
cancellable_handler<
Handler, using handler_type = cancellable_handler<
asio::any_completion_handler<void (error_code)>,
typename ClientService::executor_type typename ClientService::executor_type
> _handler; >;
handler_type _handler;
public: public:
template <typename Handler>
disconnect_op( disconnect_op(
const std::shared_ptr<client_service>& svc_ptr, const std::shared_ptr<client_service>& svc_ptr,
DisconnectContext&& context, Handler&& handler DisconnectContext&& context, Handler&& handler
@@ -52,7 +54,7 @@ public:
return _svc_ptr->get_executor(); return _svc_ptr->get_executor();
} }
using allocator_type = asio::associated_allocator_t<Handler>; using allocator_type = asio::associated_allocator_t<handler_type>;
allocator_type get_allocator() const noexcept { allocator_type get_allocator() const noexcept {
return asio::get_associated_allocator(_handler); return asio::get_associated_allocator(_handler);
} }

View File

@@ -6,10 +6,8 @@
#include <boost/asio/dispatch.hpp> #include <boost/asio/dispatch.hpp>
#include <boost/asio/post.hpp> #include <boost/asio/post.hpp>
#include <boost/asio/prepend.hpp> #include <boost/asio/prepend.hpp>
#include <boost/asio/experimental/parallel_group.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/asio/experimental/parallel_group.hpp>
#include <boost/spirit/home/x3.hpp> #include <boost/spirit/home/x3.hpp>
@@ -26,13 +24,13 @@ class resolve_op {
struct on_resolve {}; struct on_resolve {};
Owner& _owner; Owner& _owner;
Handler _handler;
using handler_type = Handler;
handler_type _handler;
public: public:
resolve_op( resolve_op(Owner& owner, Handler&& handler) :
Owner& owner, Handler&& handler) : _owner(owner), _handler(std::move(handler))
_owner(owner),
_handler(std::move(handler))
{} {}
resolve_op(resolve_op&&) noexcept = default; resolve_op(resolve_op&&) noexcept = default;
@@ -43,13 +41,13 @@ public:
return _owner.get_executor(); return _owner.get_executor();
} }
using allocator_type = asio::associated_allocator_t<Handler>; using allocator_type = asio::associated_allocator_t<handler_type>;
allocator_type get_allocator() const noexcept { allocator_type get_allocator() const noexcept {
return asio::get_associated_allocator(_handler); return asio::get_associated_allocator(_handler);
} }
using cancellation_slot_type = using cancellation_slot_type =
asio::associated_cancellation_slot_t<Handler>; asio::associated_cancellation_slot_t<handler_type>;
cancellation_slot_type get_cancellation_slot() const noexcept { cancellation_slot_type get_cancellation_slot() const noexcept {
return asio::get_associated_cancellation_slot(_handler); return asio::get_associated_cancellation_slot(_handler);
} }
@@ -165,15 +163,14 @@ public:
template <typename CompletionToken> template <typename CompletionToken>
decltype(auto) async_next_endpoint(CompletionToken&& token) { decltype(auto) async_next_endpoint(CompletionToken&& token) {
auto initiation = [this](auto handler) { using Signature = void (error_code, epoints, authority_path);
resolve_op { *this, std::move(handler) }.perform();
auto initiation = [](auto handler, endpoints& self) {
resolve_op { self, std::move(handler) }.perform();
}; };
return asio::async_initiate< return asio::async_initiate<CompletionToken, Signature>(
CompletionToken, initiation, token, std::ref(*this)
void (error_code, epoints, authority_path)
>(
std::move(initiation), token
); );
} }

View File

@@ -5,9 +5,7 @@
#include <string> #include <string>
#include <async_mqtt5/detail/internal_types.hpp> #include <async_mqtt5/detail/internal_types.hpp>
#include <async_mqtt5/impl/internal/codecs/base_decoders.hpp> #include <async_mqtt5/impl/internal/codecs/base_decoders.hpp>
#include <async_mqtt5/impl/internal/codecs/message_decoders.hpp>
namespace async_mqtt5::decoders { namespace async_mqtt5::decoders {

View File

@@ -5,9 +5,7 @@
#include <optional> #include <optional>
#include <async_mqtt5/types.hpp> #include <async_mqtt5/types.hpp>
#include <async_mqtt5/impl/internal/codecs/base_encoders.hpp> #include <async_mqtt5/impl/internal/codecs/base_encoders.hpp>
#include <async_mqtt5/impl/internal/codecs/message_encoders.hpp>
namespace async_mqtt5::encoders { namespace async_mqtt5::encoders {

View File

@@ -6,6 +6,7 @@
#include <async_mqtt5/error.hpp> #include <async_mqtt5/error.hpp>
#include <async_mqtt5/detail/control_packet.hpp> #include <async_mqtt5/detail/control_packet.hpp>
#include <async_mqtt5/detail/any_authenticator.hpp>
#include <async_mqtt5/impl/internal/codecs/message_decoders.hpp> #include <async_mqtt5/impl/internal/codecs/message_decoders.hpp>
#include <async_mqtt5/impl/internal/codecs/message_encoders.hpp> #include <async_mqtt5/impl/internal/codecs/message_encoders.hpp>
@@ -25,9 +26,7 @@ class re_auth_op {
any_authenticator& _auth; any_authenticator& _auth;
public: public:
re_auth_op( re_auth_op(const std::shared_ptr<client_service>& svc_ptr) :
const std::shared_ptr<client_service>& svc_ptr
) :
_svc_ptr(svc_ptr), _svc_ptr(svc_ptr),
_auth(_svc_ptr->_stream_context.mqtt_context().authenticator) _auth(_svc_ptr->_stream_context.mqtt_context().authenticator)
{} {}
@@ -75,10 +74,10 @@ public:
disconnect_rc_e::protocol_error disconnect_rc_e::protocol_error
); );
auto auth_step = auth_rc == reason_codes::success auto auth_step = auth_rc == reason_codes::success ?
? auth_step_e::server_final auth_step_e::server_final : auth_step_e::server_challenge;
: auth_step_e::server_challenge;
auto data = auth_props[prop::authentication_data].value_or(""); auto data = auth_props[prop::authentication_data].value_or("");
return _auth.async_auth( return _auth.async_auth(
auth_step, std::move(data), auth_step, std::move(data),
asio::prepend(std::move(*this), on_auth_data {}, auth_step) asio::prepend(std::move(*this), on_auth_data {}, auth_step)
@@ -100,9 +99,9 @@ public:
auth_props props; auth_props props;
props[prop::authentication_method] = _auth.method(); props[prop::authentication_method] = _auth.method();
props[prop::authentication_data] = std::move(data); props[prop::authentication_data] = std::move(data);
auto rc = auth_step == auth_step_e::client_initial auto rc = auth_step == auth_step_e::client_initial ?
? reason_codes::reauthenticate reason_codes::reauthenticate : reason_codes::continue_authentication;
: reason_codes::continue_authentication;
auto packet = control_packet<allocator_type>::of( auto packet = control_packet<allocator_type>::of(
no_pid, get_allocator(), no_pid, get_allocator(),
encoders::encode_auth, encoders::encode_auth,
@@ -110,6 +109,7 @@ public:
); );
const auto& wire_data = packet.wire_data(); const auto& wire_data = packet.wire_data();
_svc_ptr->async_send( _svc_ptr->async_send(
wire_data, wire_data,
no_serial, send_flag::none, no_serial, send_flag::none,
@@ -121,10 +121,8 @@ private:
void on_auth_fail(std::string message, disconnect_rc_e reason) { void on_auth_fail(std::string message, disconnect_rc_e reason) {
auto props = disconnect_props{}; auto props = disconnect_props{};
props[prop::reason_string] = std::move(message); props[prop::reason_string] = std::move(message);
async_disconnect(
reason, props, false, _svc_ptr, async_disconnect(reason, props, false, _svc_ptr, asio::detached);
asio::detached
);
} }
}; };

View File

@@ -19,7 +19,9 @@ class read_op {
struct on_reconnect {}; struct on_reconnect {};
Owner& _owner; Owner& _owner;
Handler _handler;
using handler_type = Handler;
handler_type _handler;
public: public:
read_op(Owner& owner, Handler&& handler) : read_op(Owner& owner, Handler&& handler) :
@@ -35,7 +37,7 @@ public:
return _owner.get_executor(); return _owner.get_executor();
} }
using allocator_type = asio::associated_allocator_t<Handler>; using allocator_type = asio::associated_allocator_t<handler_type>;
allocator_type get_allocator() const noexcept { allocator_type get_allocator() const noexcept {
return asio::get_associated_allocator(_handler); return asio::get_associated_allocator(_handler);
} }
@@ -107,7 +109,8 @@ private:
static bool should_reconnect(error_code ec) { static bool should_reconnect(error_code ec) {
using namespace asio::error; using namespace asio::error;
return ec == connection_aborted || ec == not_connected || return ec == connection_aborted || ec == not_connected ||
ec == timed_out || ec == connection_reset || ec == broken_pipe; ec == timed_out || ec == connection_reset ||
ec == broken_pipe || ec == asio::error::eof;
} }
}; };

View File

@@ -4,6 +4,7 @@
#include <boost/asio/deferred.hpp> #include <boost/asio/deferred.hpp>
#include <boost/asio/dispatch.hpp> #include <boost/asio/dispatch.hpp>
#include <boost/asio/prepend.hpp> #include <boost/asio/prepend.hpp>
#include <boost/asio/any_completion_handler.hpp>
#include <boost/asio/experimental/parallel_group.hpp> #include <boost/asio/experimental/parallel_group.hpp>
@@ -19,7 +20,7 @@ namespace async_mqtt5::detail {
namespace asio = boost::asio; namespace asio = boost::asio;
template <typename Owner, typename Handler> template <typename Owner>
class reconnect_op { class reconnect_op {
struct on_locked {}; struct on_locked {};
struct on_next_endpoint {}; struct on_next_endpoint {};
@@ -27,16 +28,20 @@ class reconnect_op {
struct on_backoff {}; struct on_backoff {};
Owner& _owner; Owner& _owner;
Handler _handler;
using handler_type = asio::any_completion_handler<void (error_code)>;
handler_type _handler;
std::unique_ptr<std::string> _buffer_ptr; std::unique_ptr<std::string> _buffer_ptr;
using endpoint = asio::ip::tcp::endpoint; using endpoint = asio::ip::tcp::endpoint;
using epoints = asio::ip::tcp::resolver::results_type; using epoints = asio::ip::tcp::resolver::results_type;
public: public:
template <typename Handler>
reconnect_op(Owner& owner, Handler&& handler) : reconnect_op(Owner& owner, Handler&& handler) :
_owner(owner), _owner(owner),
_handler(std::move(handler)) _handler(std::forward<Handler>(handler))
{} {}
reconnect_op(reconnect_op&&) noexcept = default; reconnect_op(reconnect_op&&) noexcept = default;
@@ -47,13 +52,13 @@ public:
return _owner.get_executor(); return _owner.get_executor();
} }
using allocator_type = asio::associated_allocator_t<Handler>; using allocator_type = asio::associated_allocator_t<handler_type>;
allocator_type get_allocator() const noexcept { allocator_type get_allocator() const noexcept {
return asio::get_associated_allocator(_handler); return asio::get_associated_allocator(_handler);
} }
using cancellation_slot_type = using cancellation_slot_type =
asio::associated_cancellation_slot_t<Handler>; asio::associated_cancellation_slot_t<handler_type>;
cancellation_slot_type get_cancellation_slot() const noexcept { cancellation_slot_type get_cancellation_slot() const noexcept {
return asio::get_associated_cancellation_slot(_handler); return asio::get_associated_cancellation_slot(_handler);
} }
@@ -122,19 +127,19 @@ public:
// wait max 5 seconds for the connect (handshake) op to finish // wait max 5 seconds for the connect (handshake) op to finish
_owner._connect_timer.expires_from_now(std::chrono::seconds(5)); _owner._connect_timer.expires_from_now(std::chrono::seconds(5));
auto init_connect = [this, sptr]( auto init_connect = [](
auto handler, const auto& eps, auto ap auto handler, typename Owner::stream_type& stream,
mqtt_context& context, const epoints& eps, authority_path ap
) { ) {
connect_op { connect_op { stream, std::move(handler), context }
*sptr, std::move(handler), .perform(eps, std::move(ap));
_owner._stream_context.mqtt_context()
}.perform(eps, std::move(ap));
}; };
auto timed_connect = asioex::make_parallel_group( auto timed_connect = asioex::make_parallel_group(
asio::async_initiate<const asio::deferred_t, void (error_code)>( asio::async_initiate<const asio::deferred_t, void (error_code)>(
std::move(init_connect), asio::deferred, init_connect, asio::deferred, std::ref(*sptr),
std::move(eps), std::move(ap) std::ref(_owner._stream_context.mqtt_context()),
eps, std::move(ap)
), ),
_owner._connect_timer.async_wait(asio::deferred) _owner._connect_timer.async_wait(asio::deferred)
); );
@@ -185,7 +190,6 @@ private:
asio::prepend(std::move(_handler), ec) asio::prepend(std::move(_handler), ec)
); );
} }
}; };

View File

@@ -15,13 +15,15 @@ class write_op {
struct on_reconnect {}; struct on_reconnect {};
Owner& _owner; Owner& _owner;
Handler _handler;
using handler_type = Handler;
handler_type _handler;
public: public:
write_op( write_op(
Owner& owner, Handler&& handler) : Owner& owner, Handler&& handler) :
_owner(owner), _owner(owner),
_handler(std::forward<Handler>(handler)) _handler(std::move(handler))
{} {}
write_op(write_op&&) noexcept = default; write_op(write_op&&) noexcept = default;
@@ -32,7 +34,7 @@ public:
return _owner.get_executor(); return _owner.get_executor();
} }
using allocator_type = asio::associated_allocator_t<Handler>; using allocator_type = asio::associated_allocator_t<handler_type>;
allocator_type get_allocator() const noexcept { allocator_type get_allocator() const noexcept {
return asio::get_associated_allocator(_handler); return asio::get_associated_allocator(_handler);
} }