[/
    Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
   
    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]

[section:async Going async]
[nochunk]

Following __Asio__'s convention, all network operations have
asynchronous versions with the same name prefixed by `async_`.
The last parameter to async operations is a __CompletionToken__,
which dictates how the asynchronous operation will be managed
and the function's return type. These `async_` functions are
called async initiating functions.

Every async initiating function has an associated
handler type, which dictates how the asynchronous operation
communicates its result back to the caller. This handler
type always has one of the two following forms:

# `void(error_code)`. Used in operations that do
   not have a proper result, e.g. [refmem connection async_connect].
# `void(error_code, T)`. Used in operations that
   have a result, e.g. [refmem connection async_prepare_statement]
   (in this case, `T` is `statement`).
   
All asynchronous functions are overloaded
to accept an optional [reflink diagnostics] output parameter. It is populated
with any server-provided error information before calling the completion handler.

[heading Single outstanding operation per connection]

As mentioned in [link mysql.overview.async this section], only a single async
operation per connection can be outstanding at a given point in time.
If you need to perform queries in parallel, open more connections to the server.


[heading Completion tokens]

Any completion token you may use with Boost.Asio can also be used
with this library. Here are some of the most common:

* [*Callbacks]. You can pass in a callable (function pointer or
  function object) with the same signature as the handler
  signature specified for the operation. The callable
  will be called when the operation completes. The initiating
  function will return `void`.
  
  [link mysql.examples.async_callbacks This example]
  demonstrates how to use async functions with callbacks.
* [*Futures]. In this case, you pass in the constant
  [asioreflink use_future use_future] as completion token.
  The initiating function will return one of the following:
    * `std::future<void>`, if the completion handler has the
      form given by 1).
    * `std::future<T>`, if the completion handler has the
      form given by 2).
  
  You can wait for the future by calling `future::get`.
  If an error occurs, `future::get` will throw an exception.
  Note that the exception is thrown by Asio itself, and will always
  be of type `boost::system::system_error`, even if diagnostics were
  available.

  [link mysql.examples.async_futures This example]
  demonstrates using futures.
* [*Stackful coroutines]. In this case, you pass in
  a [asioreflink yield_context yield_context]. To obtain one
  of these, you should use [asioreflink spawn spawn] to create
  a new coroutine. The initiating function will return:
    * `void`, if the completion handler has the
      form given by 1).
    * `T`, if the completion handler has the
      form given by 2).
  
  If you use [asioreflink basic_yield_context/operator_lb__rb_
  yield_context::operator\[\]], the operation will set the
  given [reflink error_code] when it fails. Otherwise, the
  function will throw a exception. Note that this exception
  is thrown by Asio itself, and thus will always be of type
  `boost::system::system_error`. To obtain an [reflink error_with_diagnostics]
  we suggest using error codes and the [reflink throw_on_error] function.

  You need to link against __Context__ to use these coroutines.

  [link mysql.examples.async_coroutines This example]
  uses stackful coroutines.
* [*C++20 coroutines]. In this case, you pass in the constant
  [asioreflink use_awaitable use_awaitable] as completion token.
  The initiating function will return:
    * [^[asioreflink awaitable awaitable<void>]],
      if the completion handler has the form given by 1).
    * [^[asioreflink awaitable awaitable<T>]],
      if the completion handler has the form given by 2).
  
  You can then use `co_await` on this return value. If the
  operation fails, `co_await` will throw an exception.
  Note that this exception is thrown by Asio itself, and thus will always be of type
  `boost::system::system_error`. To obtain an [reflink error_with_diagnostics]
  we suggest using the [asioreflink as_tuple as_tuple]
  completion token, which will make `co_await` report failures using error codes, and the
  [reflink throw_on_error] function.
  
  [link mysql.examples.async_coroutinescpp20 This example]
  demonstrates C++20 coroutines.
* Any other type that satisfies the __CompletionToken__ type requirements.
  We have listed the most common ones here, but you can craft your own
  and use it with this library's async operations.


[heading Cancellations and timeouts]

All async operations in this library support
[@boost:/doc/html/boost_asio/overview/core/cancellation.html per-operation cancellation].
All operations support only the `terminal` [asioreflink cancellation_type cancellation_type].
This means that, if an async operation is cancelled, the [reflink connection] object
is left in an unspecified state, after which you should close or destroy the connection.
In particular, it is [*not] safe to retry the cancelled operation.

Supporting cancellation allows you to implement timeouts without explicit
support from the library. [link mysql.examples.timeouts This example]
demonstrates how to implement this pattern.

Note that cancellation happens at the Boost.Asio level, and not at the
MySQL operation level. This means that, when cancelling an operation, the
current network read or write will be cancelled. The operation may have
already reached the server and be executed. As stated above, after an
operation is cancelled, the connection is left in an unspecified state, and
you should close or destroy it.

[endsect]
