This commit is contained in:
2024-09-15 01:25:58 +03:00
parent a7626bfe5e
commit d33c101d70
5 changed files with 95 additions and 48 deletions

View File

@@ -48,11 +48,10 @@ concept adc_asio_stream_transport_proto_c =
std::derived_from<T, asio::ip::tcp> || std::derived_from<T, asio::local::stream_protocol>;
template <adc_asio_transport_proto_c TRANSPORT_PROTOT,
interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT,
traits::adc_output_char_range RMSGT = std::vector<char>>
class AdcNetServiceASIOBase : public TRANSPORT_PROTOT, public SESSION_PROTOT
class AdcNetServiceASIOBase : public SESSION_PROTOT
{
public:
typedef std::string netservice_ident_t;
@@ -74,13 +73,7 @@ public:
static constexpr std::chrono::duration DEFAULT_RECEIVE_TIMEOUT = std::chrono::seconds(5);
AdcNetServiceASIOBase(const netservice_ident_t& ident, asio::io_context& ctx)
: TRANSPORT_PROTOT(),
SESSION_PROTOT(),
_ident(ident),
_ioContext(ctx),
_receiveStrand(_ioContext),
_receiveQueue(),
_socket(_ioContext)
: SESSION_PROTOT(), _ident(ident), _ioContext(ctx), _receiveStrand(ctx), _receiveQueue(), _socket(ctx)
{
}
@@ -88,10 +81,7 @@ public:
virtual ~AdcNetServiceASIOBase() {}
netservice_ident_t ident() const
{
return _ident;
}
netservice_ident_t ident() const { return _ident; }
void clear()
@@ -109,15 +99,32 @@ public:
{
auto timer = getDeadlineTimer(timeout);
if (ctx.use_future) {
return _socket.async_connect(
endpoint, asio::use_future([&ctx, timer = std::move(timer)](std::error_code) { timer->cancel(); }));
} else {
return _socket.async_connect(endpoint, [&ctx, timer = std::move(timer)](std::error_code ec) {
auto comp_token = [&ctx, timer = std::move(timer), this](std::error_code ec) {
if (isTimeout(timer, ec)) {
ec = std::make_error_code(std::errc::timed_out);
} else {
timer->cancel();
}
if (!ctx.use_future) {
ctx.connect_comp_token(ec);
});
}
};
if (ctx.use_future) {
comp_token = asio::use_future(comp_token);
}
return _socket.async_connect(endpoint, comp_token);
// if (ctx.use_future) {
// return _socket.async_connect(
// endpoint, asio::use_future([&ctx, timer = std::move(timer)](std::error_code) { timer->cancel(); }));
// } else {
// return _socket.async_connect(endpoint, [&ctx, timer = std::move(timer)](std::error_code ec) {
// timer->cancel();
// ctx.connect_comp_token(ec);
// });
// }
}
@@ -195,19 +202,22 @@ public:
auto asyncReceive(asio_async_ctx_t& ctx, const TimeoutT& timeout = DEFAULT_RECEIVE_TIMEOUT)
{
if (_receiveQueue.size()) { // return message from queue
//
// !!!!!!!!!!! see documentation for composed operation and async_initiate
//
asio::post(_receiveStrand, [&ctx, this]() {
RMSGT msg = _receiveQueue.front();
_receiveQueue.pop();
if (ctx.use_future) {
return msg;
} else {
ctx.receive_comp_token(std::error_code(), std::move(msg));
return;
}
});
auto async_init = [this](auto&& compl_hndl) {
asio::post(_receiveStrand, [&compl_hndl, this]() {
RMSGT msg = _receiveQueue.front();
_receiveQueue.pop();
compl_hndl(std::error_code(), std::move(msg));
});
};
if (ctx.use_future) {
return asio::async_initiate<decltype(asio_async_ctx_t::receive_comp_token),
void(std::error_code, RMSGT)>(async_init,
asio::use_future(ctx.receive_comp_token));
} else {
return asio::async_initiate<decltype(asio_async_ctx_t::receive_comp_token),
void(std::error_code, RMSGT)>(async_init, ctx.receive_comp_token);
}
}
auto out_flags = std::make_unique<asio::socket_base::message_flags>();
@@ -216,8 +226,8 @@ public:
auto s_res = std::make_shared<std::invoke_result_t<decltype(SESSION_PROTOT::search), RMSGT>>();
// NOTE: this competion token is safe (_streamBuffer access) in multithread context since all the instances will
// be executed in serialized execution manner (see asio::strand)
// NOTE: this completion token is safe (_streamBuffer access) in multithread context since all the instances
// will be executed in serialized execution manner (see asio::strand)
auto comp_token = [&ctx, s_res, timer = std::move(timer), out_flags = std::move(out_flags), this](
std::error_code ec, size_t nbytes) {
timer->cancel();
@@ -354,15 +364,9 @@ public:
return ftr.get();
}
void setShutdownType(asio::socket_base::shutdown_type shutdown_type)
{
_shutdownType = shutdown_type;
}
void setShutdownType(asio::socket_base::shutdown_type shutdown_type) { _shutdownType = shutdown_type; }
asio::socket_base::shutdown_type getShutdownType() const
{
return _shutdownType;
}
asio::socket_base::shutdown_type getShutdownType() const { return _shutdownType; }
std::error_code close()
{
@@ -381,7 +385,6 @@ protected:
asio::io_context& _ioContext;
asio::io_context::strand _receiveStrand;
asio::io_context::strand _sendStrand;
socket_t _socket;
@@ -396,20 +399,27 @@ protected:
template <traits::adc_time_duration_c TimeoutT>
std::unique_ptr<asio::steady_timer> getDeadlineTimer(const TimeoutT& timeout, bool arm = true)
{
std::unique_ptr<asio::steady_timer> timer(_socket.get_executor());
auto timer = std::make_unique<asio::steady_timer>(_socket.get_executor());
if (arm) {
timer->expires_after(timeout);
timer->async_wait([this](const std::error_code& ec) {
if (!ec) {
_socket.cancel(std::make_error_code(std::errc::timed_out));
_socket.cancel();
}
});
}
return timer;
}
template <typename TimerT>
bool isTimeout(const std::unique_ptr<TimerT>& timer, const std::error_code& ec)
{
auto exp_time = timer->expiry();
return (exp_time < std::chrono::steady_clock::now()) && (ec == asio::error::operation_aborted);
}
};
} // namespace adc::impl