File indexing completed on 2025-01-18 09:42:39
0001
0002
0003
0004
0005
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
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;
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
0794 }
0795 }
0796
0797 #ifdef BOOST_MYSQL_HEADER_ONLY
0798 #include <boost/mysql/impl/network_algorithms.ipp>
0799 #endif
0800
0801 #endif