...
This commit is contained in:
parent
52de9a861b
commit
61cf7553af
@ -65,9 +65,23 @@ concept adc_asio_is_awaitable = requires {
|
|||||||
struct adc_asio_async_call_ctx_t {
|
struct adc_asio_async_call_ctx_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
// template <typename T>
|
||||||
concept adc_completion_token_c = traits::adc_is_callable<T> || std::same_as<T, adc_asio_async_call_ctx_t> ||
|
// concept adc_completion_token_c = traits::adc_is_callable<T> || std::same_as<T, adc_asio_async_call_ctx_t> ||
|
||||||
std::same_as<T, asio::deferred_t> || adc_asio_is_future<T> || adc_asio_is_awaitable<T>;
|
// std::same_as<T, asio::deferred_t> || adc_asio_is_future<T> ||
|
||||||
|
// asio::completion_token_for;
|
||||||
|
|
||||||
|
|
||||||
|
// template <typename T, typename SignatureT>
|
||||||
|
// concept adc_completion_token_c =
|
||||||
|
// std::same_as<T, adc_asio_async_call_ctx_t> || asio::completion_token_for<T, SignatureT>;
|
||||||
|
|
||||||
|
template <typename T, typename SignatureT = void>
|
||||||
|
concept adc_completion_token_c =
|
||||||
|
std::same_as<T, adc_asio_async_call_ctx_t> ||
|
||||||
|
(traits::adc_is_callable<T> &&
|
||||||
|
std::conditional_t<std::same_as<SignatureT, void>,
|
||||||
|
std::true_type,
|
||||||
|
std::bool_constant<asio::completion_token_for<T, SignatureT>>>::value);
|
||||||
|
|
||||||
|
|
||||||
template <adc_asio_transport_proto_c TRANSPORT_PROTOT,
|
template <adc_asio_transport_proto_c TRANSPORT_PROTOT,
|
||||||
@ -98,7 +112,23 @@ public:
|
|||||||
static constexpr std::chrono::duration DEFAULT_RECEIVE_TIMEOUT = std::chrono::seconds(5);
|
static constexpr std::chrono::duration DEFAULT_RECEIVE_TIMEOUT = std::chrono::seconds(5);
|
||||||
|
|
||||||
AdcNetServiceASIOBase(const netservice_ident_t& ident, asio::io_context& ctx)
|
AdcNetServiceASIOBase(const netservice_ident_t& ident, asio::io_context& ctx)
|
||||||
: SESSION_PROTOT(), _ident(ident), _ioContext(ctx), _receiveStrand(ctx), _receiveQueue(), _socket(ctx)
|
: SESSION_PROTOT(),
|
||||||
|
_ident(ident),
|
||||||
|
_ioContext(ctx),
|
||||||
|
_receiveStrand(_ioContext),
|
||||||
|
_receiveQueue(),
|
||||||
|
_socket(_ioContext)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AdcNetServiceASIOBase(const netservice_ident_t& ident, socket_t socket)
|
||||||
|
: SESSION_PROTOT(),
|
||||||
|
_ident(ident),
|
||||||
|
_ioContext(socket.get_executor()),
|
||||||
|
_receiveStrand(_ioContext),
|
||||||
|
_receiveQueue(),
|
||||||
|
_socket(std::move(socket))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,10 +150,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <adc_completion_token_c TokenT, traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_CONNECT_TIMEOUT)>
|
template <adc_completion_token_c<void(std::error_code)> TokenT,
|
||||||
|
traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_CONNECT_TIMEOUT)>
|
||||||
auto asyncConnect(const endpoint_t& endpoint, TokenT&& token, const TimeoutT& timeout = DEFAULT_CONNECT_TIMEOUT)
|
auto asyncConnect(const endpoint_t& endpoint, TokenT&& token, const TimeoutT& timeout = DEFAULT_CONNECT_TIMEOUT)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same_v<TokenT, async_call_ctx_t>, "'async_call_ctx_t'-TYPE MUST NOT BE USED!");
|
static_assert(!std::is_same_v<TokenT, async_call_ctx_t>, "'async_call_ctx_t'-TYPE MUST NOT BE USED!");
|
||||||
|
|
||||||
auto timer = getDeadlineTimer(timeout);
|
auto timer = getDeadlineTimer(timeout);
|
||||||
|
|
||||||
@ -148,79 +179,76 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_ACCEPT_TIMEOUT)>
|
template <traits::adc_input_char_range SMSGT,
|
||||||
auto asyncAccept(const endpoint_t& endpoint,
|
adc_completion_token_c<void(std::error_code ec)> TokenT,
|
||||||
asio_async_ctx_t& ctx,
|
traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_SEND_TIMEOUT)>
|
||||||
const TimeoutT& timeout = DEFAULT_ACCEPT_TIMEOUT)
|
auto asyncSend(const SMSGT& msg, TokenT&& token, const TimeoutT& timeout = DEFAULT_SEND_TIMEOUT)
|
||||||
{
|
{
|
||||||
if constexpr (std::derived_from<socket_t, asio::basic_datagram_socket<typename socket_t::protocol_type>>) {
|
static_assert(!std::is_same_v<TokenT, async_call_ctx_t>, "'async_call_ctx_t'-TYPE MUST NOT BE USED!");
|
||||||
return; // there is no acceptor for UDP protocol
|
|
||||||
}
|
|
||||||
|
|
||||||
typename TRANSPORT_PROTOT::acceptor acceptor;
|
|
||||||
try {
|
|
||||||
acceptor = typename TRANSPORT_PROTOT::acceptor(_ioContext, endpoint);
|
|
||||||
} catch (std::system_error err) {
|
|
||||||
if (ctx.use_future) { // emulation of asio::use_future behaivior?!
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
ctx.accept_comp_token(err.code());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto timer = getDeadlineTimer(timeout);
|
|
||||||
|
|
||||||
if (ctx.use_future) {
|
|
||||||
return _socket.async_accept(
|
|
||||||
endpoint, asio::use_future([&ctx, timer = std::move(timer)](std::error_code) { timer->cancel(); }));
|
|
||||||
} else {
|
|
||||||
return _socket.async_accept(endpoint, [&ctx, timer = std::move(timer)](std::error_code ec) {
|
|
||||||
timer->cancel();
|
|
||||||
ctx.accept_comp_token(ec);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <traits::adc_input_char_range SMSGT, traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_SEND_TIMEOUT)>
|
|
||||||
auto asyncSend(const SMSGT& msg, asio_async_ctx_t& ctx, const TimeoutT& timeout = DEFAULT_SEND_TIMEOUT)
|
|
||||||
{
|
|
||||||
// create buffer sequence of sending session protocol representation of the input message
|
// create buffer sequence of sending session protocol representation of the input message
|
||||||
std::vector<asio::const_buffer> buff_seq;
|
std::vector<asio::const_buffer> buff_seq;
|
||||||
std::ranges::for_each(this->toProto(msg), [&buff_seq](const auto& el) { buff_seq.emplace_back(el); });
|
std::ranges::for_each(this->toProto(msg), [&buff_seq](const auto& el) { buff_seq.emplace_back(el); });
|
||||||
|
|
||||||
auto timer = getDeadlineTimer(timeout);
|
auto timer = getDeadlineTimer(timeout);
|
||||||
|
|
||||||
auto comp_token = [&ctx, buff_seq, timer = std::move(timer)](std::error_code ec, size_t) {
|
auto comp_token = [wrapper = traits::adc_pf_wrapper(std::forward<TokenT>(token)), buff_seq,
|
||||||
|
timer = std::move(timer)](std::error_code ec, size_t) {
|
||||||
timer->cancel();
|
timer->cancel();
|
||||||
|
|
||||||
if (!ctx.use_future) {
|
if constexpr (!adc_asio_is_future<TokenT>) {
|
||||||
ctx.send_comp_token(ec);
|
std::get<0>(wrapper)(ec);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (ctx.use_future) {
|
if constexpr (adc_asio_is_future<TokenT>) {
|
||||||
comp_token = asio::use_future(comp_token);
|
if constexpr (std::derived_from<socket_t, asio::basic_stream_socket<typename socket_t::protocol_type>>) {
|
||||||
}
|
return asio::async_write(_socket, buff_seq, asio::use_future(std::move(comp_token)));
|
||||||
|
} else if constexpr (std::derived_from<socket_t,
|
||||||
|
asio::basic_datagram_socket<typename socket_t::protocol_type>>) {
|
||||||
if constexpr (std::derived_from<socket_t, asio::basic_stream_socket<typename socket_t::protocol_type>>) {
|
return _socket.async_send(buff_seq, asio::use_future(std::move(comp_token)));
|
||||||
return asio::async_write(_socket, buff_seq, comp_token);
|
} else if constexpr (std::derived_from<socket_t,
|
||||||
} else if constexpr (std::derived_from<socket_t,
|
asio::basic_seq_packet_socket<typename socket_t::protocol_type>>) {
|
||||||
asio::basic_datagram_socket<typename socket_t::protocol_type>>) {
|
return _socket.async_send(buff_seq, asio::use_future(std::move(comp_token)));
|
||||||
return _socket.async_send(buff_seq, comp_token);
|
} else {
|
||||||
} else if constexpr (std::derived_from<socket_t,
|
static_assert(false, "UNKNOWN ASIO-LIBRARY SOCKET TYPE!!!");
|
||||||
asio::basic_seq_packet_socket<typename socket_t::protocol_type>>) {
|
}
|
||||||
return _socket.async_send(buff_seq, comp_token);
|
|
||||||
} else {
|
} else {
|
||||||
static_assert(false, "UNKNOWN ASIO-LIBRARY SOCKET TYPE!!!");
|
if constexpr (std::derived_from<socket_t, asio::basic_stream_socket<typename socket_t::protocol_type>>) {
|
||||||
|
return asio::async_write(_socket, buff_seq, std::move(comp_token));
|
||||||
|
} else if constexpr (std::derived_from<socket_t,
|
||||||
|
asio::basic_datagram_socket<typename socket_t::protocol_type>>) {
|
||||||
|
return _socket.async_send(buff_seq, std::move(comp_token));
|
||||||
|
} else if constexpr (std::derived_from<socket_t,
|
||||||
|
asio::basic_seq_packet_socket<typename socket_t::protocol_type>>) {
|
||||||
|
return _socket.async_send(buff_seq, std::move(comp_token));
|
||||||
|
} else {
|
||||||
|
static_assert(false, "UNKNOWN ASIO-LIBRARY SOCKET TYPE!!!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_RECEIVE_TIMEOUT)>
|
template <adc_completion_token_c TokenT, traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_RECEIVE_TIMEOUT)>
|
||||||
auto asyncReceive(asio_async_ctx_t& ctx, const TimeoutT& timeout = DEFAULT_RECEIVE_TIMEOUT)
|
auto asyncReceive(TokenT&& token, const TimeoutT& timeout = DEFAULT_RECEIVE_TIMEOUT)
|
||||||
{
|
{
|
||||||
|
static_assert(!std::is_same_v<TokenT, async_call_ctx_t>, "'async_call_ctx_t'-TYPE MUST NOT BE USED!");
|
||||||
|
|
||||||
|
// check completion token signature
|
||||||
|
if constexpr (!(adc_asio_is_future<TokenT> || std::is_same_v<TokenT, asio::deferred_t>)) {
|
||||||
|
static_assert(traits::adc_func_traits<TokenT>::arity == 2, "INVALID COMPLETION TOKEN SIGNATURE!");
|
||||||
|
static_assert(std::is_same_v<std::remove_cvref_t<traits::adc_func_arg1_t<TokenT>>, std::error_code>,
|
||||||
|
"INVALID COMPLETION TOKEN SIGNATURE!");
|
||||||
|
static_assert(traits::adc_output_char_range<
|
||||||
|
std::tuple_element_t<1, typename traits::adc_func_traits<TokenT>::args_t>>,
|
||||||
|
"INVALID COMPLETION TOKEN SIGNATURE!");
|
||||||
|
}
|
||||||
|
|
||||||
|
using msg_t = std::conditional_t<
|
||||||
|
adc_asio_is_future<TokenT> || std::is_same_v<TokenT, asio::deferred_t>, RMSGT,
|
||||||
|
std::remove_cvref_t<std::tuple_element_t<1, typename traits::adc_func_traits<TokenT>::args_t>>>;
|
||||||
|
|
||||||
if (_receiveQueue.size()) { // return message from queue
|
if (_receiveQueue.size()) { // return message from queue
|
||||||
auto async_init = [this](auto&& compl_hndl) {
|
auto async_init = [this](auto&& compl_hndl) {
|
||||||
asio::post(_receiveStrand, [&compl_hndl, this]() {
|
asio::post(_receiveStrand, [&compl_hndl, this]() {
|
||||||
@ -230,13 +258,11 @@ public:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ctx.use_future) {
|
if (adc_asio_is_future<TokenT>) {
|
||||||
return asio::async_initiate<decltype(asio_async_ctx_t::receive_comp_token),
|
return asio::async_initiate<TokenT, void(std::error_code, msg_t)>(
|
||||||
void(std::error_code, RMSGT)>(async_init,
|
async_init, asio::use_future(ctx.receive_comp_token));
|
||||||
asio::use_future(ctx.receive_comp_token));
|
|
||||||
} else {
|
} else {
|
||||||
return asio::async_initiate<decltype(asio_async_ctx_t::receive_comp_token),
|
return asio::async_initiate<TokenT, void(std::error_code, msg_t)>(async_init, ctx.receive_comp_token);
|
||||||
void(std::error_code, RMSGT)>(async_init, ctx.receive_comp_token);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user