...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Following Boost.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. connection::async_connect
.
void(error_code,
T)
.
Used in operations that have a result, e.g. connection::async_prepare_statement
(in this case, T
is statement
).
All asynchronous functions are overloaded to accept an optional diagnostics
output parameter. It is populated with any server-provided error information
before calling the completion handler.
As mentioned in 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.
Any completion token you may use with Boost.Asio can also be used with this library. Here are some of the most common:
C++20 coroutines, using asio::co_spawn
and asio::deferred
.
Passing deferred
to an
initiation function returns an object that can be co_await
'ed.
You can combine deferred with with_diagnostics
to get better error reporting.
See the async tutorial for details.
Stackful coroutines, which you can use
to get coroutine-like functionality in C++11. Access this functionality
using asio::spawn
and asio::yield_context
,
possibly in conjunction with with_diagnostics.
You need to link against Boost.Context
to use these coroutines.
See this example for details.
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
.
This example demonstrates how to use async functions with callbacks.
Futures. In this case, you pass in the
constant asio::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.
with_diagnostics
is a completion token adapter that you can use with async operations when using
exceptions. with_diagnostics
makes your operations throw error_with_diagnostics
,
like sync functions do. For example:
[async_with_diagnostics_cpp20] [async_with_diagnostics_cpp11]
with_diagnostics
only makes
sense when using exceptions. When using error codes, you can keep using asio::as_tuple
and asio::redirect_error
normally.
All async operations in this library support per-operation
cancellation. All operations support only the terminal
asio::cancellation_type
.
This means that, if an async operation is cancelled, the 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. This tutorial covers the subject in depth.
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.