Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:43:02

0001 //
0002 // Copyright (c) 2019-2025 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_WITH_DIAGNOSTICS_HPP
0009 #define BOOST_MYSQL_WITH_DIAGNOSTICS_HPP
0010 
0011 #include <boost/mysql/detail/access.hpp>
0012 
0013 #include <type_traits>
0014 #include <utility>
0015 
0016 namespace boost {
0017 namespace mysql {
0018 
0019 /**
0020  * \brief A completion token adapter used to include server diagnostics in exceptions.
0021  * \details
0022  * When passed to an async initiating function, transforms its handler signature from `void(error_code, T...)`
0023  * to `void(std::exception_ptr, T...)`.
0024  * Uses knowledge of Boost.MySQL internals to grab any \ref diagnostics
0025  * that the operation may produce to create a `std::exception_ptr` pointing to an \ref error_with_diagnostics
0026  * object. On success, the generated `std::exception_ptr` will be `nullptr`.
0027  *
0028  * Using `with_diagnostics` to wrap tokens that throw exceptions (like `deferred` + `co_await` or
0029  * `yield_context`) enhances the thrown exceptions with diagnostics information, matching the ones thrown by
0030  * sync functions. If you don't use this token, Asio will use `system_error` exceptions, containing less info.
0031  *
0032  * This token can only be used with operations involving Boost.MySQL, as it relies on its internals.
0033  *
0034  * Like `asio::as_tuple`, this class wraps another completion token. For instance,
0035  * `with_diagnostics(asio::deferred)` will generate a deferred operation with an adapted
0036  * signature, which will throw `error_with_diagnostics` when `co_await`'ed.
0037  *
0038  * If this token is applied to a function with a handler signature that
0039  * does not match `void(error_code, T...)`, the token acts as a pass-through:
0040  * it does not modify the signature, and calls the underlying token's initiation directly.
0041  * This has the following implications:
0042  *
0043  *   - `asio::as_tuple(with_diagnostics(X))` is equivalent to `asio::as_tuple(X)`.
0044  *   - `asio::redirect_error(with_diagnostics(X))` is equivalent to `asio::redirect_error(X)`.
0045  *   - Tokens like `asio::as_tuple` and `asio::redirect_error` can be used as partial tokens
0046  *     when `with_diagnostics` is the default completion token, as is the case for \ref any_connection.
0047  */
0048 template <class CompletionToken>
0049 class with_diagnostics_t
0050 {
0051     CompletionToken impl_;
0052 
0053 #ifndef BOOST_MYSQL_DOXYGEN
0054     friend struct detail::access;
0055 #endif
0056 
0057 public:
0058     /**
0059      * \brief Default constructor.
0060      * \details
0061      * Only valid if `CompletionToken` is default-constructible.
0062      *
0063      * \par Exception safety
0064      * Strong guarantee. Any exceptions thrown by default-constructing
0065      * `CompletionToken` are propagated.
0066      */
0067     constexpr with_diagnostics_t() : impl_{} {}
0068 
0069     /**
0070      * \brief Constructor.
0071      * \details
0072      * The passed `token` should be convertible to `CompletionToken`.
0073      *
0074      * \par Exception safety
0075      * Strong guarantee. Any exceptions thrown by constructing `CompletionToken` are propagated.
0076      */
0077     template <class T>
0078     constexpr explicit with_diagnostics_t(T&& token) : impl_(std::forward<T>(token))
0079     {
0080     }
0081 };
0082 
0083 /**
0084  * \brief Creates a \ref with_diagnostics_t from a completion token.
0085  * \details
0086  * The passed token is decay-copied into the \ref with_diagnostics_t object.
0087  *
0088  * \par Exception safety
0089  * Strong guarantee. Any exceptions thrown by constructing `CompletionToken` are propagated.
0090  */
0091 template <class CompletionToken>
0092 constexpr with_diagnostics_t<typename std::decay<CompletionToken>::type> with_diagnostics(
0093     CompletionToken&& token
0094 )
0095 {
0096     return with_diagnostics_t<typename std::decay<CompletionToken>::type>(std::forward<CompletionToken>(token)
0097     );
0098 }
0099 
0100 }  // namespace mysql
0101 }  // namespace boost
0102 
0103 #include <boost/mysql/impl/with_diagnostics.hpp>
0104 
0105 #endif