From 6a43eebdb320da24eb52738c068912457caff0b4 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Mon, 4 Dec 2023 12:32:09 +0100 Subject: [PATCH] C++11 support for deferred --- include/boost/mysql/any_connection.hpp | 178 +++++++----------- include/boost/mysql/detail/config.hpp | 7 + .../boost/mysql/detail/connection_impl.hpp | 111 ++++++++++- .../connection_pool/iddle_connection_list.hpp | 4 +- 4 files changed, 175 insertions(+), 125 deletions(-) diff --git a/include/boost/mysql/any_connection.hpp b/include/boost/mysql/any_connection.hpp index 31853f9bd..37c592cf2 100644 --- a/include/boost/mysql/any_connection.hpp +++ b/include/boost/mysql/any_connection.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -265,16 +266,16 @@ class any_connection * The handler signature for this operation is `void(boost::mysql::error_code)`. */ template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_connect(const connect_params& params, CompletionToken&& token) + auto async_connect(const connect_params& params, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_connect_t) { return async_connect(params, impl_.shared_diag(), std::forward(token)); } /// \copydoc async_connect template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_connect(const connect_params& params, diagnostics& diag, CompletionToken&& token) + auto async_connect(const connect_params& params, diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_connect_t) { auto stable_prms = detail::make_stable(params); return impl_.async_connect( @@ -303,8 +304,8 @@ class any_connection * The handler signature for this operation is `void(boost::mysql::error_code)`. */ template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_connect(const connect_params* params, diagnostics& diag, CompletionToken&& token) + auto async_connect(const connect_params* params, diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_connect_t) { BOOST_ASSERT(params != nullptr); return impl_.async_connect( @@ -336,14 +337,9 @@ class any_connection template < BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_RESULTS_TYPE ResultsType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_execute( - ExecutionRequest&& req, - ResultsType& result, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken> + auto async_execute(ExecutionRequest&& req, ResultsType& result, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t) { return async_execute( std::forward(req), @@ -357,15 +353,13 @@ class any_connection template < BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_RESULTS_TYPE ResultsType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_execute( + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken> + auto async_execute( ExecutionRequest&& req, ResultsType& result, diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + CompletionToken&& token + ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t) { return impl_.async_execute( std::forward(req), @@ -405,14 +399,12 @@ class any_connection template < BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_start_execution( + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken> + auto async_start_execution( ExecutionRequest&& req, ExecutionStateType& st, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + CompletionToken&& token + ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t) { return async_start_execution( std::forward(req), @@ -426,15 +418,13 @@ class any_connection template < BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_start_execution( + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken> + auto async_start_execution( ExecutionRequest&& req, ExecutionStateType& st, diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + CompletionToken&& token + ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t) { return impl_.async_start_execution( std::forward(req), @@ -462,25 +452,18 @@ class any_connection /// \copydoc connection::async_prepare_statement template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, statement)) - async_prepare_statement( - string_view stmt, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + CompletionToken> + auto async_prepare_statement(string_view stmt, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t) { return async_prepare_statement(stmt, impl_.shared_diag(), std::forward(token)); } /// \copydoc async_prepare_statement template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, statement)) - async_prepare_statement( - string_view stmt, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + CompletionToken> + auto async_prepare_statement(string_view stmt, diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t) { return impl_.async_run( detail::prepare_statement_algo_params{&diag, stmt}, @@ -504,26 +487,17 @@ class any_connection } /// \copydoc connection::async_close_statement - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_close_statement( - const statement& stmt, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + template + auto async_close_statement(const statement& stmt, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t) { return async_close_statement(stmt, impl_.shared_diag(), std::forward(token)); } /// \copydoc async_close_statement - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_close_statement( - const statement& stmt, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + template + auto async_close_statement(const statement& stmt, diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t) { return impl_.async_run( impl_.make_params_close_statement(stmt, diag), @@ -549,25 +523,18 @@ class any_connection /// \copydoc connection::async_read_some_rows(execution_state&,CompletionToken&&) template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view)) - async_read_some_rows( - execution_state& st, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + CompletionToken> + auto async_read_some_rows(execution_state& st, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t) { return async_read_some_rows(st, impl_.shared_diag(), std::forward(token)); } /// \copydoc async_read_some_rows(execution_state&,CompletionToken&&) template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view)) - async_read_some_rows( - execution_state& st, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + CompletionToken> + auto async_read_some_rows(execution_state& st, diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t) { return impl_.async_run( impl_.make_params_read_some_rows(st, diag), @@ -688,8 +655,7 @@ class any_connection class... StaticRow, BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, std::size_t)) - async_read_some_rows( + auto async_read_some_rows( static_execution_state& st, span output, CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) @@ -736,8 +702,7 @@ class any_connection class... StaticRow, BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, std::size_t)) - async_read_some_rows( + auto async_read_some_rows( static_execution_state& st, span output, diagnostics& diag, @@ -771,13 +736,9 @@ class any_connection /// \copydoc connection::async_read_resultset_head template < BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_read_resultset_head( - ExecutionStateType& st, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken> + auto async_read_resultset_head(ExecutionStateType& st, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t) { return async_read_resultset_head(st, impl_.shared_diag(), std::forward(token)); } @@ -785,14 +746,9 @@ class any_connection /// \copydoc async_read_resultset_head template < BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_read_resultset_head( - ExecutionStateType& st, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken> + auto async_read_resultset_head(ExecutionStateType& st, diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t) { return impl_.async_run( impl_.make_params_read_resultset_head(st, diag), @@ -813,19 +769,16 @@ class any_connection } /// \copydoc connection::async_ping - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_ping(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + template + auto async_ping(CompletionToken&& token) BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t) { return async_ping(impl_.shared_diag(), std::forward(token)); } /// \copydoc async_ping - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_ping(diagnostics& diag, CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + template + auto async_ping(diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t) { return impl_.async_run(impl_.make_params_ping(diag), std::forward(token)); } @@ -846,22 +799,17 @@ class any_connection } /// \copydoc connection::async_reset_connection - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_reset_connection(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + template + auto async_reset_connection(CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t) { return async_reset_connection(impl_.shared_diag(), std::forward(token)); } /// \copydoc async_reset_connection - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_reset_connection( - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) + template + auto async_reset_connection(diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t) { return impl_.async_run( impl_.make_params_reset_connection(diag), @@ -909,16 +857,16 @@ class any_connection * The handler signature for this operation is `void(boost::mysql::error_code)`. */ template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_close(CompletionToken&& token) + auto async_close(CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t) { return async_close(impl_.shared_diag(), std::forward(token)); } /// \copydoc async_close template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_close(diagnostics& diag, CompletionToken&& token) + auto async_close(diagnostics& diag, CompletionToken&& token) + BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t) { return this->impl_.async_run( this->impl_.make_params_close(diag), diff --git a/include/boost/mysql/detail/config.hpp b/include/boost/mysql/detail/config.hpp index 0992e71e2..04c94d7bc 100644 --- a/include/boost/mysql/detail/config.hpp +++ b/include/boost/mysql/detail/config.hpp @@ -39,6 +39,13 @@ #define BOOST_MYSQL_STATIC_OR_INLINE inline #endif +// Auto return type. Having this as a macro helps the documentation tool. +#ifdef BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#define BOOST_MYSQL_RETURN_TYPE(...) -> __VA_ARGS__ +#else +#define BOOST_MYSQL_RETURN_TYPE(...) +#endif + // clang-format on #endif diff --git a/include/boost/mysql/detail/connection_impl.hpp b/include/boost/mysql/detail/connection_impl.hpp index 6f272f23e..31825d99a 100644 --- a/include/boost/mysql/detail/connection_impl.hpp +++ b/include/boost/mysql/detail/connection_impl.hpp @@ -37,6 +37,7 @@ #include #include #include +#include namespace boost { namespace mysql { @@ -227,8 +228,14 @@ class connection_impl // Generic algorithm template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, completion_signature_t) - async_run(AlgoParams params, CompletionToken&& token) + auto async_run(AlgoParams params, CompletionToken&& token) + -> decltype(asio::async_initiate>( + run_algo_initiation(), + token, + stream_.get(), + st_.get(), + params + )) { return asio::async_initiate>( run_algo_initiation(), @@ -259,13 +266,21 @@ class connection_impl } template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_connect( + auto async_connect( const EndpointType& endpoint, const handshake_params& params, diagnostics& diag, CompletionToken&& token ) + -> decltype(asio::async_initiate( + connect_initiation(), + token, + stream_.get(), + st_.get(), + endpoint, + params, + &diag + )) { return asio::async_initiate( connect_initiation(), @@ -299,8 +314,21 @@ class connection_impl } template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_execute(ExecutionRequest&& req, ResultsType& result, diagnostics& diag, CompletionToken&& token) + auto async_execute( + ExecutionRequest&& req, + ResultsType& result, + diagnostics& diag, + CompletionToken&& token + ) + -> decltype(asio::async_initiate( + initiate_execute(), + token, + stream_.get(), + st_.get(), + std::forward(req), + &access::get_impl(result).get_interface(), + &diag + )) { return asio::async_initiate( initiate_execute(), @@ -332,13 +360,21 @@ class connection_impl } template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_start_execution( + auto async_start_execution( ExecutionRequest&& req, ExecutionStateType& exec_st, diagnostics& diag, CompletionToken&& token ) + -> decltype(asio::async_initiate( + initiate_start_execution(), + token, + stream_.get(), + st_.get(), + std::forward(req), + &access::get_impl(exec_st).get_interface(), + &diag + )) { return asio::async_initiate( initiate_start_execution(), @@ -405,6 +441,65 @@ class connection_impl diagnostics& shared_diag() noexcept; }; +// To use some completion tokens, like deferred, in C++11, the old macros +// BOOST_ASIO_INITFN_AUTO_RESULT_TYPE are no longer enough. +// Helper typedefs to reduce duplication +template +using async_run_t = decltype(std::declval().async_run( + std::declval(), + std::forward(std::declval()) +)); + +template +using async_connect_t = decltype(std::declval().async_connect( + std::declval(), + std::declval(), + std::declval(), + std::forward(std::declval()) +)); + +template +using async_handshake_t = async_run_t; + +template +using async_execute_t = decltype(std::declval().async_execute( + std::declval(), + std::declval(), + std::declval(), + std::forward(std::declval()) +)); + +template +using async_start_execution_t = decltype(std::declval().async_start_execution( + std::declval(), + std::declval(), + std::declval(), + std::forward(std::declval()) +)); +template +using async_read_resultset_head_t = async_run_t; + +template +using async_read_some_rows_dynamic_t = async_run_t; + +template +using async_prepare_statement_t = async_run_t; + +template +using async_close_statement_t = async_run_t; + +template +using async_ping_t = async_run_t; + +template +using async_reset_connection_t = async_run_t; + +template +using async_quit_connection_t = async_run_t; + +template +using async_close_connection_t = async_run_t; + } // namespace detail } // namespace mysql } // namespace boost diff --git a/include/boost/mysql/detail/connection_pool/iddle_connection_list.hpp b/include/boost/mysql/detail/connection_pool/iddle_connection_list.hpp index e4f7c5df7..15894e70d 100644 --- a/include/boost/mysql/detail/connection_pool/iddle_connection_list.hpp +++ b/include/boost/mysql/detail/connection_pool/iddle_connection_list.hpp @@ -39,8 +39,8 @@ class iddle_connection_list connection_node* try_get_one() noexcept { return list_.empty() ? nullptr : &list_.back(); } template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_wait(CompletionToken&& token) + auto async_wait(CompletionToken&& token) + -> decltype(chan_.async_receive(std::forward(token))) { return chan_.async_receive(std::forward(token)); }