diff --git a/net/asio/adc_netservice_asio.h b/net/asio/adc_netservice_asio.h index 8c1d6e0..ab723b4 100644 --- a/net/asio/adc_netservice_asio.h +++ b/net/asio/adc_netservice_asio.h @@ -65,9 +65,23 @@ concept adc_asio_is_awaitable = requires { struct adc_asio_async_call_ctx_t { }; -template -concept adc_completion_token_c = traits::adc_is_callable || std::same_as || - std::same_as || adc_asio_is_future || adc_asio_is_awaitable; +// template +// concept adc_completion_token_c = traits::adc_is_callable || std::same_as || +// std::same_as || adc_asio_is_future || +// asio::completion_token_for; + + +// template +// concept adc_completion_token_c = +// std::same_as || asio::completion_token_for; + +template +concept adc_completion_token_c = + std::same_as || + (traits::adc_is_callable && + std::conditional_t, + std::true_type, + std::bool_constant>>::value); template + template 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) { - static_assert(std::is_same_v, "'async_call_ctx_t'-TYPE MUST NOT BE USED!"); + static_assert(!std::is_same_v, "'async_call_ctx_t'-TYPE MUST NOT BE USED!"); auto timer = getDeadlineTimer(timeout); @@ -148,79 +179,76 @@ public: } - template - auto asyncAccept(const endpoint_t& endpoint, - asio_async_ctx_t& ctx, - const TimeoutT& timeout = DEFAULT_ACCEPT_TIMEOUT) + template TokenT, + traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_SEND_TIMEOUT)> + auto asyncSend(const SMSGT& msg, TokenT&& token, const TimeoutT& timeout = DEFAULT_SEND_TIMEOUT) { - if constexpr (std::derived_from>) { - return; // there is no acceptor for UDP protocol - } + static_assert(!std::is_same_v, "'async_call_ctx_t'-TYPE MUST NOT BE USED!"); - 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 - 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 std::vector buff_seq; std::ranges::for_each(this->toProto(msg), [&buff_seq](const auto& el) { buff_seq.emplace_back(el); }); 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(token)), buff_seq, + timer = std::move(timer)](std::error_code ec, size_t) { timer->cancel(); - if (!ctx.use_future) { - ctx.send_comp_token(ec); + if constexpr (!adc_asio_is_future) { + std::get<0>(wrapper)(ec); } }; - if (ctx.use_future) { - comp_token = asio::use_future(comp_token); - } - - - if constexpr (std::derived_from>) { - return asio::async_write(_socket, buff_seq, comp_token); - } else if constexpr (std::derived_from>) { - return _socket.async_send(buff_seq, comp_token); - } else if constexpr (std::derived_from>) { - return _socket.async_send(buff_seq, comp_token); + if constexpr (adc_asio_is_future) { + if constexpr (std::derived_from>) { + return asio::async_write(_socket, buff_seq, asio::use_future(std::move(comp_token))); + } else if constexpr (std::derived_from>) { + return _socket.async_send(buff_seq, asio::use_future(std::move(comp_token))); + } else if constexpr (std::derived_from>) { + return _socket.async_send(buff_seq, asio::use_future(std::move(comp_token))); + } else { + static_assert(false, "UNKNOWN ASIO-LIBRARY SOCKET TYPE!!!"); + } } else { - static_assert(false, "UNKNOWN ASIO-LIBRARY SOCKET TYPE!!!"); + if constexpr (std::derived_from>) { + return asio::async_write(_socket, buff_seq, std::move(comp_token)); + } else if constexpr (std::derived_from>) { + return _socket.async_send(buff_seq, std::move(comp_token)); + } else if constexpr (std::derived_from>) { + return _socket.async_send(buff_seq, std::move(comp_token)); + } else { + static_assert(false, "UNKNOWN ASIO-LIBRARY SOCKET TYPE!!!"); + } } } - template - auto asyncReceive(asio_async_ctx_t& ctx, const TimeoutT& timeout = DEFAULT_RECEIVE_TIMEOUT) + template + auto asyncReceive(TokenT&& token, const TimeoutT& timeout = DEFAULT_RECEIVE_TIMEOUT) { + static_assert(!std::is_same_v, "'async_call_ctx_t'-TYPE MUST NOT BE USED!"); + + // check completion token signature + if constexpr (!(adc_asio_is_future || std::is_same_v)) { + static_assert(traits::adc_func_traits::arity == 2, "INVALID COMPLETION TOKEN SIGNATURE!"); + static_assert(std::is_same_v>, std::error_code>, + "INVALID COMPLETION TOKEN SIGNATURE!"); + static_assert(traits::adc_output_char_range< + std::tuple_element_t<1, typename traits::adc_func_traits::args_t>>, + "INVALID COMPLETION TOKEN SIGNATURE!"); + } + + using msg_t = std::conditional_t< + adc_asio_is_future || std::is_same_v, RMSGT, + std::remove_cvref_t::args_t>>>; + if (_receiveQueue.size()) { // return message from queue auto async_init = [this](auto&& compl_hndl) { asio::post(_receiveStrand, [&compl_hndl, this]() { @@ -230,13 +258,11 @@ public: }); }; - if (ctx.use_future) { - return asio::async_initiate(async_init, - asio::use_future(ctx.receive_comp_token)); + if (adc_asio_is_future) { + return asio::async_initiate( + async_init, asio::use_future(ctx.receive_comp_token)); } else { - return asio::async_initiate(async_init, ctx.receive_comp_token); + return asio::async_initiate(async_init, ctx.receive_comp_token); } }