Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

Going async

Following Boost.Asio's convetion, 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:

  1. void(error_code). Used in operations that do not have a proper result, e.g. connection::async_connect.
  2. 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:

  • 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 boost::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.

    This example demonstrates using futures.

  • Stackful coroutines. In this case, you pass in a boost::asio::yield_context. To obtain one of these, you should use boost::asio::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 boost::asio::yield_context::operator[], the operation will set the given 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 error_with_diagnostics we suggest using error codes and the throw_on_error function.

    This example uses stackful coroutines.

  • C++20 coroutines. In this case, you pass in the constant boost::asio::use_awaitable as completion token. The initiating function will return:

    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 error_with_diagnostics we suggest using the boost::asio::as_tuple completion token, which will make co_await report failures using error codes, and the throw_on_error function.

    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.

Boost.MySQL also supports default completion tokens. Recall that some stream types may have an associated Executor that has an associated default completion token type (see [asiorelink default_completion_token default_completion_token]). If this is the case, you don't need to specify the CompletionToken parameter in initiating functions, and the default will be used. This example demonstrates using default completion tokens with Boost.MySQL.

All async operations in this library support per-operation cancellation. All operations support only the terminal boost::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 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.


PrevUpHomeNext