Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:39

0001 //
0002 // Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_HPP
0009 #define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_HPP
0010 
0011 #include <boost/mysql/diagnostics.hpp>
0012 #include <boost/mysql/error_code.hpp>
0013 #include <boost/mysql/execution_state.hpp>
0014 #include <boost/mysql/field_view.hpp>
0015 #include <boost/mysql/handshake_params.hpp>
0016 #include <boost/mysql/rows_view.hpp>
0017 #include <boost/mysql/statement.hpp>
0018 #include <boost/mysql/string_view.hpp>
0019 
0020 #include <boost/mysql/detail/access.hpp>
0021 #include <boost/mysql/detail/any_execution_request.hpp>
0022 #include <boost/mysql/detail/channel_ptr.hpp>
0023 #include <boost/mysql/detail/config.hpp>
0024 #include <boost/mysql/detail/execution_processor/execution_processor.hpp>
0025 #include <boost/mysql/detail/typing/get_type_index.hpp>
0026 
0027 #include <boost/asio/any_completion_handler.hpp>
0028 #include <boost/mp11/integer_sequence.hpp>
0029 
0030 #include <array>
0031 #include <cstddef>
0032 
0033 namespace boost {
0034 namespace mysql {
0035 
0036 template <class... StaticRow>
0037 class static_execution_state;
0038 
0039 namespace detail {
0040 
0041 class channel;
0042 
0043 template <class T>
0044 using any_handler = asio::any_completion_handler<void(error_code, T)>;
0045 
0046 using any_void_handler = asio::any_completion_handler<void(error_code)>;
0047 
0048 // execution helpers
0049 template <class... T, std::size_t... I>
0050 std::array<field_view, sizeof...(T)> tuple_to_array_impl(const std::tuple<T...>& t, mp11::index_sequence<I...>) noexcept
0051 {
0052     return std::array<field_view, sizeof...(T)>{{to_field(std::get<I>(t))...}};
0053 }
0054 
0055 template <class... T>
0056 std::array<field_view, sizeof...(T)> tuple_to_array(const std::tuple<T...>& t) noexcept
0057 {
0058     return tuple_to_array_impl(t, mp11::make_index_sequence<sizeof...(T)>());
0059 }
0060 
0061 struct query_request_getter
0062 {
0063     any_execution_request value;
0064     any_execution_request get() const noexcept { return value; }
0065 };
0066 inline query_request_getter make_request_getter(string_view q, channel&) noexcept
0067 {
0068     return query_request_getter{q};
0069 }
0070 
0071 struct stmt_it_request_getter
0072 {
0073     statement stmt;
0074     span<const field_view> params;  // Points into channel shared_fields()
0075 
0076     any_execution_request get() const noexcept { return any_execution_request(stmt, params); }
0077 };
0078 
0079 template <class FieldViewFwdIterator>
0080 inline stmt_it_request_getter make_request_getter(
0081     const bound_statement_iterator_range<FieldViewFwdIterator>& req,
0082     channel& chan
0083 )
0084 {
0085     auto& impl = access::get_impl(req);
0086     auto& shared_fields = get_shared_fields(chan);
0087     shared_fields.assign(impl.first, impl.last);
0088     return {impl.stmt, shared_fields};
0089 }
0090 
0091 template <std::size_t N>
0092 struct stmt_tuple_request_getter
0093 {
0094     statement stmt;
0095     std::array<field_view, N> params;
0096 
0097     any_execution_request get() const noexcept { return any_execution_request(stmt, params); }
0098 };
0099 template <class WritableFieldTuple>
0100 stmt_tuple_request_getter<std::tuple_size<WritableFieldTuple>::value>
0101 make_request_getter(const bound_statement_tuple<WritableFieldTuple>& req, channel&)
0102 {
0103     auto& impl = access::get_impl(req);
0104     return {impl.stmt, tuple_to_array(impl.params)};
0105 }
0106 
0107 //
0108 // connect
0109 //
0110 BOOST_MYSQL_DECL
0111 void connect_erased(
0112     channel& chan,
0113     const void* endpoint,
0114     const handshake_params& params,
0115     error_code& err,
0116     diagnostics& diag
0117 );
0118 
0119 BOOST_MYSQL_DECL
0120 void async_connect_erased(
0121     channel& chan,
0122     const void* endpoint,
0123     const handshake_params& params,
0124     diagnostics& diag,
0125     any_void_handler handler
0126 );
0127 
0128 // Handles casting from the generic EndpointType we've got in the interface to the concrete endpoint type
0129 template <class Stream>
0130 void connect_interface(
0131     channel& chan,
0132     const typename Stream::lowest_layer_type::endpoint_type& ep,
0133     const handshake_params& params,
0134     error_code& err,
0135     diagnostics& diag
0136 )
0137 {
0138     connect_erased(chan, &ep, params, err, diag);
0139 }
0140 
0141 template <class Stream>
0142 struct connect_initiation
0143 {
0144     template <class Handler>
0145     void operator()(
0146         Handler&& handler,
0147         channel* chan,
0148         const typename Stream::lowest_layer_type::endpoint_type& endpoint,
0149         handshake_params params,
0150         diagnostics* diag
0151     )
0152     {
0153         async_connect_erased(*chan, &endpoint, params, *diag, std::forward<Handler>(handler));
0154     }
0155 };
0156 
0157 template <class Stream, class CompletionToken>
0158 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0159 async_connect_interface(
0160     channel& chan,
0161     const typename Stream::lowest_layer_type::endpoint_type& endpoint,
0162     const handshake_params& params,
0163     diagnostics& diag,
0164     CompletionToken&& token
0165 )
0166 {
0167     return asio::async_initiate<CompletionToken, void(error_code)>(
0168         connect_initiation<Stream>(),
0169         token,
0170         &chan,
0171         endpoint,
0172         params,
0173         &diag
0174     );
0175 }
0176 
0177 //
0178 // handshake
0179 //
0180 BOOST_MYSQL_DECL
0181 void handshake_erased(channel& channel, const handshake_params& params, error_code& err, diagnostics& diag);
0182 
0183 BOOST_MYSQL_DECL
0184 void async_handshake_erased(
0185     channel& chan,
0186     const handshake_params& params,
0187     diagnostics& diag,
0188     any_void_handler
0189 );
0190 
0191 inline void handshake_interface(
0192     channel& channel,
0193     const handshake_params& params,
0194     error_code& err,
0195     diagnostics& diag
0196 )
0197 {
0198     handshake_erased(channel, params, err, diag);
0199 }
0200 
0201 struct handshake_initiation
0202 {
0203     template <class Handler>
0204     void operator()(Handler&& handler, channel* chan, handshake_params params, diagnostics* diag)
0205     {
0206         async_handshake_erased(*chan, params, *diag, std::forward<Handler>(handler));
0207     }
0208 };
0209 
0210 template <class CompletionToken>
0211 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0212 async_handshake_interface(
0213     channel& chan,
0214     const handshake_params& params,
0215     diagnostics& diag,
0216     CompletionToken&& token
0217 )
0218 {
0219     return asio::async_initiate<CompletionToken, void(error_code)>(
0220         handshake_initiation(),
0221         token,
0222         &chan,
0223         params,
0224         &diag
0225     );
0226 }
0227 
0228 //
0229 // execute
0230 //
0231 BOOST_MYSQL_DECL
0232 void execute_erased(
0233     channel& channel,
0234     const any_execution_request& req,
0235     execution_processor& output,
0236     error_code& err,
0237     diagnostics& diag
0238 );
0239 
0240 BOOST_MYSQL_DECL void async_execute_erased(
0241     channel& chan,
0242     const any_execution_request& req,
0243     execution_processor& output,
0244     diagnostics& diag,
0245     any_void_handler handler
0246 );
0247 
0248 struct initiate_execute
0249 {
0250     template <class Handler, class ExecutionRequest>
0251     void operator()(
0252         Handler&& handler,
0253         channel& chan,
0254         const ExecutionRequest& req,
0255         execution_processor& proc,
0256         diagnostics& diag
0257     )
0258     {
0259         auto getter = make_request_getter(req, chan);
0260         async_execute_erased(chan, getter.get(), proc, diag, std::forward<Handler>(handler));
0261     }
0262 };
0263 
0264 template <class ExecutionRequest, class ResultsType>
0265 void execute_interface(
0266     channel& channel,
0267     const ExecutionRequest& req,
0268     ResultsType& result,
0269     error_code& err,
0270     diagnostics& diag
0271 )
0272 {
0273     auto getter = make_request_getter(req, channel);
0274     execute_erased(channel, getter.get(), access::get_impl(result).get_interface(), err, diag);
0275 }
0276 
0277 template <class ExecutionRequest, class ResultsType, class CompletionToken>
0278 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0279 async_execute_interface(
0280     channel& chan,
0281     ExecutionRequest&& req,
0282     ResultsType& result,
0283     diagnostics& diag,
0284     CompletionToken&& token
0285 )
0286 {
0287     return asio::async_initiate<CompletionToken, void(error_code)>(
0288         initiate_execute(),
0289         token,
0290         std::ref(chan),
0291         std::forward<ExecutionRequest>(req),
0292         std::ref(access::get_impl(result).get_interface()),
0293         std::ref(diag)
0294     );
0295 }
0296 
0297 //
0298 // start_execution
0299 //
0300 BOOST_MYSQL_DECL
0301 void start_execution_erased(
0302     channel& channel,
0303     const any_execution_request& req,
0304     execution_processor& proc,
0305     error_code& err,
0306     diagnostics& diag
0307 );
0308 
0309 BOOST_MYSQL_DECL
0310 void async_start_execution_erased(
0311     channel& channel,
0312     const any_execution_request& req,
0313     execution_processor& proc,
0314     diagnostics& diag,
0315     any_void_handler handler
0316 );
0317 
0318 struct initiate_start_execution
0319 {
0320     template <class Handler, class ExecutionRequest>
0321     void operator()(
0322         Handler&& handler,
0323         channel& chan,
0324         const ExecutionRequest& req,
0325         execution_processor& proc,
0326         diagnostics& diag
0327     )
0328     {
0329         auto getter = make_request_getter(req, chan);
0330         async_start_execution_erased(chan, getter.get(), proc, diag, std::forward<Handler>(handler));
0331     }
0332 };
0333 
0334 template <class ExecutionRequest, class ExecutionStateType>
0335 void start_execution_interface(
0336     channel& channel,
0337     const ExecutionRequest& req,
0338     ExecutionStateType& st,
0339     error_code& err,
0340     diagnostics& diag
0341 )
0342 {
0343     auto getter = make_request_getter(req, channel);
0344     start_execution_erased(channel, getter.get(), access::get_impl(st).get_interface(), err, diag);
0345 }
0346 
0347 template <class ExecutionRequest, class ExecutionStateType, class CompletionToken>
0348 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0349 async_start_execution_interface(
0350     channel& chan,
0351     ExecutionRequest&& req,
0352     ExecutionStateType& st,
0353     diagnostics& diag,
0354     CompletionToken&& token
0355 )
0356 {
0357     return asio::async_initiate<CompletionToken, void(error_code)>(
0358         initiate_start_execution(),
0359         token,
0360         std::ref(chan),
0361         std::forward<ExecutionRequest>(req),
0362         std::ref(access::get_impl(st).get_interface()),
0363         std::ref(diag)
0364     );
0365 }
0366 
0367 //
0368 // prepare_statement
0369 //
0370 BOOST_MYSQL_DECL
0371 statement prepare_statement_erased(channel& chan, string_view stmt, error_code& err, diagnostics& diag);
0372 
0373 BOOST_MYSQL_DECL void async_prepare_statement_erased(
0374     channel& chan,
0375     string_view stmt,
0376     diagnostics& diag,
0377     any_handler<statement> handler
0378 );
0379 
0380 struct prepare_statement_initiation
0381 {
0382     template <class Handler>
0383     void operator()(Handler&& handler, channel* chan, string_view stmt_sql, diagnostics* diag)
0384     {
0385         async_prepare_statement_erased(*chan, stmt_sql, *diag, std::forward<Handler>(handler));
0386     }
0387 };
0388 
0389 inline statement prepare_statement_interface(
0390     channel& chan,
0391     string_view stmt,
0392     error_code& err,
0393     diagnostics& diag
0394 )
0395 {
0396     return prepare_statement_erased(chan, stmt, err, diag);
0397 }
0398 
0399 template <class CompletionToken>
0400 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code, boost::mysql::statement))
0401 async_prepare_statement_interface(channel& chan, string_view stmt, diagnostics& diag, CompletionToken&& token)
0402 {
0403     return asio::async_initiate<CompletionToken, void(error_code, statement)>(
0404         prepare_statement_initiation(),
0405         token,
0406         &chan,
0407         stmt,
0408         &diag
0409     );
0410 }
0411 
0412 //
0413 // close_statement
0414 //
0415 BOOST_MYSQL_DECL
0416 void close_statement_erased(channel& chan, const statement& stmt, error_code& err, diagnostics& diag);
0417 
0418 BOOST_MYSQL_DECL
0419 void async_close_statement_erased(
0420     channel& chan,
0421     const statement& stmt,
0422     diagnostics& diag,
0423     any_void_handler handler
0424 );
0425 
0426 struct close_statement_initiation
0427 {
0428     template <class Handler>
0429     void operator()(Handler&& handler, channel* chan, statement stmt, diagnostics* diag)
0430     {
0431         async_close_statement_erased(*chan, stmt, *diag, std::forward<Handler>(handler));
0432     }
0433 };
0434 
0435 inline void close_statement_interface(
0436     channel& chan,
0437     const statement& stmt,
0438     error_code& err,
0439     diagnostics& diag
0440 )
0441 {
0442     close_statement_erased(chan, stmt, err, diag);
0443 }
0444 
0445 template <class CompletionToken>
0446 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0447 async_close_statement_interface(
0448     channel& chan,
0449     const statement& stmt,
0450     diagnostics& diag,
0451     CompletionToken&& token
0452 )
0453 {
0454     return asio::async_initiate<CompletionToken, void(error_code)>(
0455         close_statement_initiation(),
0456         token,
0457         &chan,
0458         stmt,
0459         &diag
0460     );
0461 }
0462 
0463 //
0464 // read_some_rows (dynamic)
0465 //
0466 BOOST_MYSQL_DECL
0467 rows_view read_some_rows_dynamic_erased(
0468     channel& chan,
0469     execution_state_impl& st,
0470     error_code& err,
0471     diagnostics& diag
0472 );
0473 
0474 BOOST_MYSQL_DECL void async_read_some_rows_dynamic_erased(
0475     channel& chan,
0476     execution_state_impl& st,
0477     diagnostics& diag,
0478     any_handler<rows_view> handler
0479 );
0480 
0481 struct read_some_rows_dynamic_initiation
0482 {
0483     template <class Handler>
0484     void operator()(Handler&& handler, channel* chan, execution_state_impl* st, diagnostics* diag)
0485     {
0486         async_read_some_rows_dynamic_erased(*chan, *st, *diag, std::forward<Handler>(handler));
0487     }
0488 };
0489 
0490 inline rows_view read_some_rows_dynamic_interface(
0491     channel& chan,
0492     execution_state& st,
0493     error_code& err,
0494     diagnostics& diag
0495 )
0496 {
0497     return read_some_rows_dynamic_erased(chan, access::get_impl(st), err, diag);
0498 }
0499 
0500 template <class CompletionToken>
0501 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view))
0502 async_read_some_rows_dynamic_interface(
0503     channel& chan,
0504     execution_state& st,
0505     diagnostics& diag,
0506     CompletionToken&& token
0507 )
0508 {
0509     return asio::async_initiate<CompletionToken, void(error_code, rows_view)>(
0510         read_some_rows_dynamic_initiation(),
0511         token,
0512         &chan,
0513         &access::get_impl(st).get_interface(),
0514         &diag
0515     );
0516 }
0517 
0518 //
0519 // read_some_rows (static)
0520 //
0521 BOOST_MYSQL_DECL
0522 std::size_t read_some_rows_static_erased(
0523     channel& chan,
0524     execution_processor& proc,
0525     const output_ref& output,
0526     error_code& err,
0527     diagnostics& diag
0528 );
0529 
0530 BOOST_MYSQL_DECL
0531 void async_read_some_rows_erased(
0532     channel& chan,
0533     execution_processor& proc,
0534     const output_ref& output,
0535     diagnostics& diag,
0536     any_handler<std::size_t> handler
0537 );
0538 
0539 template <class SpanRowType, class... RowType>
0540 std::size_t read_some_rows_static_interface(
0541     channel& chan,
0542     static_execution_state<RowType...>& st,
0543     span<SpanRowType> output,
0544     error_code& err,
0545     diagnostics& diag
0546 )
0547 {
0548     constexpr std::size_t index = get_type_index<SpanRowType, RowType...>();
0549     static_assert(index != index_not_found, "SpanRowType must be one of the types returned by the query");
0550 
0551     return read_some_rows_static_erased(
0552         chan,
0553         access::get_impl(st).get_interface(),
0554         output_ref(output, index),
0555         err,
0556         diag
0557     );
0558 }
0559 
0560 struct read_some_rows_static_initiation
0561 {
0562     template <class Handler>
0563     void operator()(
0564         Handler&& handler,
0565         channel* chan,
0566         execution_processor* proc,
0567         const output_ref& output,
0568         diagnostics* diag
0569     )
0570     {
0571         async_read_some_rows_erased(*chan, *proc, output, *diag, std::forward<Handler>(handler));
0572     }
0573 };
0574 
0575 template <
0576     class SpanRowType,
0577     class... RowType,
0578     BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) CompletionToken>
0579 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view))
0580 async_read_some_rows_static_interface(
0581     channel& chan,
0582     static_execution_state<RowType...>& st,
0583     span<SpanRowType> output,
0584     diagnostics& diag,
0585     CompletionToken&& token
0586 )
0587 {
0588     constexpr std::size_t index = get_type_index<SpanRowType, RowType...>();
0589     static_assert(index != index_not_found, "SpanRowType must be one of the types returned by the query");
0590 
0591     return asio::async_initiate<CompletionToken, void(error_code, std::size_t)>(
0592         read_some_rows_static_initiation(),
0593         token,
0594         &chan,
0595         &access::get_impl(st).get_interface(),
0596         output_ref(output, index),
0597         &diag
0598     );
0599 }
0600 
0601 //
0602 // read_resultset_head
0603 //
0604 BOOST_MYSQL_DECL
0605 void read_resultset_head_erased(
0606     channel& channel,
0607     execution_processor& proc,
0608     error_code& err,
0609     diagnostics& diag
0610 );
0611 
0612 BOOST_MYSQL_DECL
0613 void async_read_resultset_head_erased(
0614     channel& chan,
0615     execution_processor& proc,
0616     diagnostics& diag,
0617     any_void_handler handler
0618 );
0619 
0620 template <class ExecutionStateType>
0621 void read_resultset_head_interface(
0622     channel& channel,
0623     ExecutionStateType& st,
0624     error_code& err,
0625     diagnostics& diag
0626 )
0627 {
0628     read_resultset_head_erased(channel, access::get_impl(st).get_interface(), err, diag);
0629 }
0630 
0631 struct read_resultset_head_initiation
0632 {
0633     template <class Handler>
0634     void operator()(Handler&& handler, channel* chan, execution_processor* proc, diagnostics* diag)
0635     {
0636         async_read_resultset_head_erased(*chan, *proc, *diag, std::forward<Handler>(handler));
0637     }
0638 };
0639 
0640 template <class CompletionToken, class ExecutionStateType>
0641 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0642 async_read_resultset_head_interface(
0643     channel& chan,
0644     ExecutionStateType& st,
0645     diagnostics& diag,
0646     CompletionToken&& token
0647 )
0648 {
0649     return asio::async_initiate<CompletionToken, void(error_code)>(
0650         read_resultset_head_initiation(),
0651         token,
0652         &chan,
0653         &access::get_impl(st).get_interface(),
0654         &diag
0655     );
0656 }
0657 
0658 //
0659 // ping
0660 //
0661 BOOST_MYSQL_DECL
0662 void ping_erased(channel& chan, error_code& code, diagnostics& diag);
0663 
0664 BOOST_MYSQL_DECL
0665 void async_ping_erased(channel& chan, diagnostics& diag, any_void_handler handler);
0666 
0667 struct ping_initiation
0668 {
0669     template <class Handler>
0670     void operator()(Handler&& handler, channel* chan, diagnostics* diag)
0671     {
0672         async_ping_erased(*chan, *diag, std::forward<Handler>(handler));
0673     }
0674 };
0675 
0676 inline void ping_interface(channel& chan, error_code& code, diagnostics& diag)
0677 {
0678     ping_erased(chan, code, diag);
0679 }
0680 
0681 template <class CompletionToken>
0682 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0683 async_ping_interface(channel& chan, diagnostics& diag, CompletionToken&& token)
0684 {
0685     return asio::async_initiate<CompletionToken, void(error_code)>(ping_initiation(), token, &chan, &diag);
0686 }
0687 
0688 //
0689 // reset_connection
0690 //
0691 BOOST_MYSQL_DECL
0692 void reset_connection_erased(channel& chan, error_code& code, diagnostics& diag);
0693 
0694 BOOST_MYSQL_DECL
0695 void async_reset_connection_erased(channel& chan, diagnostics& diag, any_void_handler handler);
0696 
0697 struct reset_connection_initiation
0698 {
0699     template <class Handler>
0700     void operator()(Handler&& handler, channel* chan, diagnostics* diag)
0701     {
0702         async_reset_connection_erased(*chan, *diag, std::forward<Handler>(handler));
0703     }
0704 };
0705 
0706 inline void reset_connection_interface(channel& chan, error_code& code, diagnostics& diag)
0707 {
0708     reset_connection_erased(chan, code, diag);
0709 }
0710 
0711 template <class CompletionToken>
0712 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0713 async_reset_connection_interface(channel& chan, diagnostics& diag, CompletionToken&& token)
0714 {
0715     return asio::async_initiate<CompletionToken, void(error_code)>(
0716         reset_connection_initiation(),
0717         token,
0718         &chan,
0719         &diag
0720     );
0721 }
0722 
0723 //
0724 // close connection
0725 //
0726 BOOST_MYSQL_DECL
0727 void close_connection_erased(channel& chan, error_code& code, diagnostics& diag);
0728 
0729 BOOST_MYSQL_DECL
0730 void async_close_connection_erased(channel& chan, diagnostics& diag, any_void_handler handler);
0731 
0732 struct close_connection_initiation
0733 {
0734     template <class Handler>
0735     void operator()(Handler&& handler, channel* chan, diagnostics* diag)
0736     {
0737         async_close_connection_erased(*chan, *diag, std::forward<Handler>(handler));
0738     }
0739 };
0740 
0741 inline void close_connection_interface(channel& chan, error_code& code, diagnostics& diag)
0742 {
0743     close_connection_erased(chan, code, diag);
0744 }
0745 
0746 template <class CompletionToken>
0747 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0748 async_close_connection_interface(channel& chan, diagnostics& diag, CompletionToken&& token)
0749 {
0750     return asio::async_initiate<CompletionToken, void(error_code)>(
0751         close_connection_initiation(),
0752         token,
0753         &chan,
0754         &diag
0755     );
0756 }
0757 
0758 //
0759 // quit connection
0760 //
0761 BOOST_MYSQL_DECL
0762 void quit_connection_erased(channel& chan, error_code& err, diagnostics& diag);
0763 
0764 BOOST_MYSQL_DECL
0765 void async_quit_connection_erased(channel& chan, diagnostics& diag, any_void_handler handler);
0766 
0767 struct quit_connection_initiation
0768 {
0769     template <class Handler>
0770     void operator()(Handler&& handler, channel* chan, diagnostics* diag)
0771     {
0772         async_quit_connection_erased(*chan, *diag, std::forward<Handler>(handler));
0773     }
0774 };
0775 
0776 inline void quit_connection_interface(channel& chan, error_code& err, diagnostics& diag)
0777 {
0778     quit_connection_erased(chan, err, diag);
0779 }
0780 
0781 template <class CompletionToken>
0782 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
0783 async_quit_connection_interface(channel& chan, diagnostics& diag, CompletionToken&& token)
0784 {
0785     return asio::async_initiate<CompletionToken, void(error_code)>(
0786         quit_connection_initiation(),
0787         token,
0788         &chan,
0789         &diag
0790     );
0791 }
0792 
0793 }  // namespace detail
0794 }  // namespace mysql
0795 }  // namespace boost
0796 
0797 #ifdef BOOST_MYSQL_HEADER_ONLY
0798 #include <boost/mysql/impl/network_algorithms.ipp>
0799 #endif
0800 
0801 #endif