Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/mysql/connection_pool.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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_CONNECTION_POOL_HPP
0009 #define BOOST_MYSQL_CONNECTION_POOL_HPP
0010 
0011 #include <boost/mysql/any_connection.hpp>
0012 #include <boost/mysql/diagnostics.hpp>
0013 #include <boost/mysql/error_code.hpp>
0014 #include <boost/mysql/pool_params.hpp>
0015 #include <boost/mysql/with_diagnostics.hpp>
0016 
0017 #include <boost/mysql/detail/access.hpp>
0018 #include <boost/mysql/detail/config.hpp>
0019 #include <boost/mysql/detail/connection_pool_fwd.hpp>
0020 #include <boost/mysql/detail/initiation_base.hpp>
0021 
0022 #include <boost/asio/any_completion_handler.hpp>
0023 #include <boost/asio/any_io_executor.hpp>
0024 #include <boost/asio/async_result.hpp>
0025 
0026 #include <chrono>
0027 #include <memory>
0028 #include <utility>
0029 
0030 namespace boost {
0031 namespace mysql {
0032 
0033 /**
0034  * \brief A proxy to a connection owned by a pool that returns it to the pool when destroyed.
0035  * \details
0036  * A `pooled_connection` behaves like to a `std::unique_ptr`: it has exclusive ownership of an
0037  * \ref any_connection created by the pool. When destroyed, it returns the connection to the pool.
0038  * A `pooled_connection` may own nothing. We say such a connection is invalid (`this->valid() == false`).
0039  *
0040  * This class is movable but not copyable.
0041  *
0042  * \par Object lifetimes
0043  * While `*this` is alive, the \ref connection_pool internal data will be kept alive
0044  * automatically. It's safe to destroy the `connection_pool` object before `*this`.
0045  *
0046  * \par Thread safety
0047  * This object and the \ref any_connection object it may point to are **not thread safe**,
0048  * even if the connection pool used to obtain them was constructed with
0049  * \ref pool_params::thread_safe set to true.
0050  *
0051  * Functions that return the underlying connection to the pool
0052  * cause a mutation on the pool state object. Calling such functions
0053  * on objects obtained from the same pool
0054  * is thread-safe only if the pool was constructed with \ref pool_params::thread_safe set to true.
0055  *
0056  * In other words, individual connections can't be shared between threads. Pools can
0057  * be shared only if they're constructed with \ref pool_params::thread_safe set to true.
0058  *
0059  * - Distinct objects: safe if the \ref connection_pool that was used to obtain the objects
0060  *   was created with \ref pool_params::thread_safe set to true. Otherwise, unsafe.
0061  * - Shared objects: always unsafe.
0062  */
0063 class pooled_connection
0064 {
0065 #ifndef BOOST_MYSQL_DOXYGEN
0066     friend struct detail::access;
0067     friend class detail::basic_pool_impl<any_connection, std::chrono::steady_clock, pooled_connection>;
0068 #endif
0069 
0070     struct impl_t
0071     {
0072         detail::connection_node* node;
0073         std::shared_ptr<detail::pool_impl> pool;
0074     } impl_{};
0075 
0076     pooled_connection(detail::connection_node& node, std::shared_ptr<detail::pool_impl> pool_impl) noexcept
0077         : impl_{&node, std::move(pool_impl)}
0078     {
0079         BOOST_ASSERT(impl_.pool);
0080     }
0081 
0082 public:
0083     /**
0084      * \brief Constructs an invalid pooled connection.
0085      * \details
0086      * The resulting object is invalid (`this->valid() == false`).
0087      *
0088      * \par Exception safety
0089      * No-throw guarantee.
0090      */
0091     pooled_connection() noexcept = default;
0092 
0093     /**
0094      * \brief Move constructor.
0095      * \details
0096      * Transfers connection ownership from `other` to `*this`.
0097      *
0098      * After this function returns, if `other.valid() == true`, `this->valid() == true`.
0099      * In any case, `other` will become invalid (`other.valid() == false`).
0100      *
0101      * \par Exception safety
0102      * No-throw guarantee.
0103      */
0104     pooled_connection(pooled_connection&& other) noexcept : impl_(std::move(other.impl_)) {}
0105 
0106     /**
0107      * \brief Move assignment.
0108      * \details
0109      * If `this->valid()`, returns the connection owned by `*this` to the pool and marks
0110      * it as pending reset (as if the destructor was called).
0111      * It then transfers connection ownership from `other` to `*this`.
0112      *
0113      * After this function returns, if `other.valid() == true`, `this->valid() == true`.
0114      * In any case, `other` will become invalid (`other.valid() == false`).
0115      *
0116      * \par Thread-safety
0117      * May cause a mutation on the connection pool that `this` points to.
0118      * Thread-safe for a shared pool only if it was constructed with
0119      * \ref pool_params::thread_safe set to true.
0120      *
0121      * \par Exception safety
0122      * No-throw guarantee.
0123      */
0124     pooled_connection& operator=(pooled_connection&& other) noexcept
0125     {
0126         if (valid())
0127         {
0128             detail::return_connection(*impl_.pool, *impl_.node, true);
0129         }
0130         impl_ = std::move(other.impl_);
0131         return *this;
0132     }
0133 
0134 #ifndef BOOST_MYSQL_DOXYGEN
0135     pooled_connection(const pooled_connection&) = delete;
0136     pooled_connection& operator=(const pooled_connection&) = delete;
0137 #endif
0138 
0139     /**
0140      * \brief Destructor.
0141      * \details
0142      * If `this->valid() == true`, returns the owned connection to the pool
0143      * and marks it as pending reset. If your connection doesn't need to be reset
0144      * (e.g. because you didn't mutate session state), use \ref return_without_reset.
0145      *
0146      * \par Thread-safety
0147      * May cause a mutation on the connection pool that `this` points to.
0148      * Thread-safe for a shared pool only if it was constructed with
0149      * \ref pool_params::thread_safe set to true.
0150      */
0151     ~pooled_connection()
0152     {
0153         if (valid())
0154             detail::return_connection(*impl_.pool, *impl_.node, true);
0155     }
0156 
0157     /**
0158      * \brief Returns whether the object owns a connection or not.
0159      * \par Exception safety
0160      * No-throw guarantee.
0161      */
0162     bool valid() const noexcept { return impl_.pool.get() != nullptr; }
0163 
0164     /**
0165      * \brief Retrieves the connection owned by this object.
0166      * \par Preconditions
0167      * The object should own a connection (`this->valid() == true`).
0168      *
0169      * \par Object lifetimes
0170      * The returned reference is valid as long as `*this` or an object
0171      * move-constructed or move-assigned from `*this` is alive.
0172      *
0173      * \par Exception safety
0174      * No-throw guarantee.
0175      */
0176     any_connection& get() noexcept { return detail::get_connection(*impl_.node); }
0177 
0178     /// \copydoc get
0179     const any_connection& get() const noexcept { return detail::get_connection(*impl_.node); }
0180 
0181     /// \copydoc get
0182     any_connection* operator->() noexcept { return &get(); }
0183 
0184     /// \copydoc get
0185     const any_connection* operator->() const noexcept { return &get(); }
0186 
0187     /**
0188      * \brief Returns the owned connection to the pool and marks it as not requiring reset.
0189      * \details
0190      * Returns a connection to the pool and marks it as idle. This will
0191      * skip the \ref any_connection::async_reset_connection call to wipe session state.
0192      * \n
0193      * This can provide a performance gain, but must be used with care. Failing to wipe
0194      * session state can lead to resource leaks (prepared statements not being released),
0195      * incorrect results and vulnerabilities (different logical operations interacting due
0196      * to leftover state).
0197      * \n
0198      * Please read the documentation on \ref any_connection::async_reset_connection before
0199      * calling this function. If in doubt, don't use it, and leave the destructor return
0200      * the connection to the pool for you.
0201      * \n
0202      * When this function returns, `*this` will own nothing (`this->valid() == false`).
0203      *
0204      * \par Preconditions
0205      * `this->valid() == true`
0206      *
0207      * \par Exception safety
0208      * No-throw guarantee.
0209      *
0210      * \par Thread-safety
0211      * Causes a mutation on the connection pool that `this` points to.
0212      * Thread-safe for a shared pool only if it was constructed with
0213      * \ref pool_params::thread_safe set to true.
0214      */
0215     void return_without_reset() noexcept
0216     {
0217         BOOST_ASSERT(valid());
0218         detail::return_connection(*impl_.pool, *impl_.node, false);
0219         impl_ = impl_t{};
0220     }
0221 };
0222 
0223 /**
0224  * \brief A pool of connections of variable size.
0225  * \details
0226  * A connection pool creates and manages \ref any_connection objects.
0227  * Using a pool allows to reuse sessions, avoiding part of the overhead associated
0228  * to session establishment. It also features built-in error handling and reconnection.
0229  * See the discussion and examples for more details on when to use this class.
0230  *
0231  * Connections are retrieved by \ref async_get_connection, which yields a
0232  * \ref pooled_connection object. They are returned to the pool when the
0233  * `pooled_connection` is destroyed, or by calling \ref pooled_connection::return_without_reset.
0234  *
0235  * A pool needs to be run before it can return any connection. Use \ref async_run for this.
0236  * Pools can only be run once.
0237  *
0238  * Connections are created, connected and managed internally by the pool, following
0239  * a well-defined state model. Please refer to the discussion for details.
0240  *
0241  * Due to oddities in Boost.Asio's universal async model, this class only
0242  * exposes async functions. You can use `asio::use_future` to transform them
0243  * into sync functions (please read the discussion for details).
0244  *
0245  * This is a move-only type.
0246  *
0247  * \par Default completion tokens
0248  * The default completion token for all async operations in this class is
0249  * `with_diagnostics(asio::deferred)`, which allows you to use `co_await`
0250  * and have the expected exceptions thrown on error.
0251  *
0252  * \par Thread-safety
0253  * Pools are composed of an internal state object, plus a handle to such state.
0254  * Each component has different thread-safety rules.
0255  *
0256  * Regarding **internal state**, connection pools are **not thread-safe by default**,
0257  * but can be made safe by constructing them with
0258  * \ref pool_params::thread_safe set to `true`.
0259  * Internal state is also mutated by some functions outside `connection_pool`, like
0260  * returning connections.
0261  *
0262  * The following actions imply a pool state mutation, and are protected by a strand
0263  * when thread-safety is enabled:
0264  *
0265  * - Calling \ref connection_pool::async_run.
0266  * - Calling \ref connection_pool::async_get_connection.
0267  * - Cancelling \ref async_get_connection by emitting a cancellation signal.
0268  * - Returning a connection by destroying a \ref pooled_connection or
0269  *   calling \ref pooled_connection::return_without_reset.
0270  * - Cancelling the pool by calling \ref connection_pool::cancel,
0271  *   emitting a cancellation signal for \ref async_run, or destroying the
0272  *   `connection_pool` object.
0273  *
0274  * The **handle to the pool state** is **never thread-safe**, even for
0275  * pools with thread-safety enabled. Functions like assignments
0276  * modify the handle, and cause race conditions if called
0277  * concurrently with other functions. Other objects,
0278  * like \ref pooled_connection, have their own state handle,
0279  * and thus interact only with the pool state.
0280  *
0281  * If configured to be thread-safe, the protection applies only to the pool's state.
0282  * In particular, be careful when using `asio::cancel_after` and similar tokens.
0283  * Please read
0284  * <a href="../connection_pool.html#mysql.connection_pool.thread_safe">this page</a> for more info.
0285  *
0286  * In summary:
0287  *
0288  * - Distinct objects: safe. \n
0289  * - Shared objects: unsafe. Setting \ref pool_params::thread_safe
0290  *   to `true` makes some functions safe.
0291  *
0292  * \par Object lifetimes
0293  * Connection pool objects create an internal state object that is referenced
0294  * by other objects and operations (like \ref pooled_connection). This object
0295  * will be kept alive using shared ownership semantics even after the `connection_pool`
0296  * object is destroyed. This results in intuitive lifetime rules.
0297  */
0298 class connection_pool
0299 {
0300     std::shared_ptr<detail::pool_impl> impl_;
0301 
0302 #ifndef BOOST_MYSQL_DOXYGEN
0303     friend struct detail::access;
0304 #endif
0305 
0306     struct initiate_run : detail::initiation_base
0307     {
0308         using detail::initiation_base::initiation_base;
0309 
0310         // Having diagnostics* here makes async_run compatible with with_diagnostics
0311         template <class Handler>
0312         void operator()(Handler&& h, diagnostics*, std::shared_ptr<detail::pool_impl> self)
0313         {
0314             async_run_erased(std::move(self), std::forward<Handler>(h));
0315         }
0316     };
0317 
0318     BOOST_MYSQL_DECL
0319     static void async_run_erased(
0320         std::shared_ptr<detail::pool_impl> pool,
0321         asio::any_completion_handler<void(error_code)> handler
0322     );
0323 
0324     struct initiate_get_connection : detail::initiation_base
0325     {
0326         using detail::initiation_base::initiation_base;
0327 
0328         template <class Handler>
0329         void operator()(Handler&& h, diagnostics* diag, std::shared_ptr<detail::pool_impl> self)
0330         {
0331             async_get_connection_erased(std::move(self), diag, std::forward<Handler>(h));
0332         }
0333     };
0334 
0335     BOOST_MYSQL_DECL
0336     static void async_get_connection_erased(
0337         std::shared_ptr<detail::pool_impl> pool,
0338         diagnostics* diag,
0339         asio::any_completion_handler<void(error_code, pooled_connection)> handler
0340     );
0341 
0342     template <class CompletionToken>
0343     auto async_get_connection_impl(diagnostics* diag, CompletionToken&& token)
0344         -> decltype(asio::async_initiate<CompletionToken, void(error_code, pooled_connection)>(
0345             std::declval<initiate_get_connection>(),
0346             token,
0347             diag,
0348             impl_
0349         ))
0350     {
0351         BOOST_ASSERT(valid());
0352         return asio::async_initiate<CompletionToken, void(error_code, pooled_connection)>(
0353             initiate_get_connection{get_executor()},
0354             token,
0355             diag,
0356             impl_
0357         );
0358     }
0359 
0360     BOOST_MYSQL_DECL
0361     connection_pool(asio::any_io_executor ex, pool_params&& params, int);
0362 
0363 public:
0364     /**
0365      * \brief Constructs a connection pool.
0366      * \details
0367      *
0368      * The pool is created in a "not-running" state. Call \ref async_run to transition to the
0369      * "running" state.
0370      *
0371      * The constructed pool is always valid (`this->valid() == true`).
0372      *
0373      * \par Executor
0374      * The passed executor becomes the pool executor, available through \ref get_executor.
0375      * `ex` is used as follows:
0376      *
0377      *   - If `params.thread_safe == true`, `ex` is used to build a strand. The strand is used
0378      *     to build internal I/O objects, like timers.
0379      *   - If `params.thread_safe == false`, `ex` is used directly to build internal I/O objects.
0380      *   - If `params.connection_executor` is empty, `ex` is used to build individual connections,
0381      *     regardless of the chosen thread-safety mode. Otherwise, `params.connection_executor`
0382      *     is used.
0383      *
0384      * \par Exception safety
0385      * Strong guarantee. Exceptions may be thrown by memory allocations.
0386      * \throws std::invalid_argument If `params` contains values that violate the rules described in \ref
0387      *         pool_params.
0388      */
0389     connection_pool(asio::any_io_executor ex, pool_params params)
0390         : connection_pool(std::move(ex), std::move(params), 0)
0391     {
0392     }
0393 
0394     /**
0395      * \brief Constructs a connection pool.
0396      * \details
0397      * Equivalent to `connection_pool(ctx.get_executor(), params)`.
0398      *
0399      * This function participates in overload resolution only if `ExecutionContext`
0400      * satisfies the `ExecutionContext` requirements imposed by Boost.Asio.
0401      *
0402      * \par Exception safety
0403      * Strong guarantee. Exceptions may be thrown by memory allocations.
0404      * \throws std::invalid_argument If `params` contains values that violate the rules described in \ref
0405      *         pool_params.
0406      */
0407     template <
0408         class ExecutionContext
0409 #ifndef BOOST_MYSQL_DOXYGEN
0410         ,
0411         class = typename std::enable_if<std::is_convertible<
0412             decltype(std::declval<ExecutionContext&>().get_executor()),
0413             asio::any_io_executor>::value>::type
0414 #endif
0415         >
0416     connection_pool(ExecutionContext& ctx, pool_params params)
0417         : connection_pool(ctx.get_executor(), std::move(params), 0)
0418     {
0419     }
0420 
0421 #ifndef BOOST_MYSQL_DOXYGEN
0422     connection_pool(const connection_pool&) = delete;
0423     connection_pool& operator=(const connection_pool&) = delete;
0424 #endif
0425 
0426     /**
0427      * \brief Move-constructor.
0428      * \details
0429      * Constructs a connection pool by taking ownership of `other`.
0430      *
0431      * After this function returns, if `other.valid() == true`, `this->valid() == true`.
0432      * In any case, `other` will become invalid (`other.valid() == false`).
0433      *
0434      * Moving a connection pool with outstanding async operations
0435      * is safe.
0436      *
0437      * \par Exception safety
0438      * No-throw guarantee.
0439      *
0440      * \par Thread-safety
0441      * Mutates `other`'s internal state handle. Does not access the pool state.
0442      * This function **can never be called concurrently with other functions
0443      * that read the internal state handle**, even for pools created
0444      * with \ref pool_params::thread_safe set to true.
0445      *
0446      * The internal pool state is not accessed, so this function can be called
0447      * concurrently with functions that only access the pool's internal state,
0448      * like returning connections.
0449      */
0450     connection_pool(connection_pool&& other) = default;
0451 
0452     /**
0453      * \brief Move assignment.
0454      * \details
0455      * Assigns `other` to `*this`, transferring ownership.
0456      *
0457      * After this function returns, if `other.valid() == true`, `this->valid() == true`.
0458      * In any case, `other` will become invalid (`other.valid() == false`).
0459      *
0460      * Moving a connection pool with outstanding async operations
0461      * is safe.
0462      *
0463      * \par Exception safety
0464      * No-throw guarantee.
0465      *
0466      * \par Thread-safety
0467      * Mutates `*this` and `other`'s internal state handle. Does not access the pool state.
0468      * This function **can never be called concurrently with other functions
0469      * that read the internal state handle**, even for pools created
0470      * with \ref pool_params::thread_safe set to true.
0471      *
0472      * The internal pool state is not accessed, so this function can be called
0473      * concurrently with functions that only access the pool's internal state,
0474      * like returning connections.
0475      */
0476     connection_pool& operator=(connection_pool&& other) = default;
0477 
0478     /**
0479      * \brief Destructor.
0480      * \details
0481      * Cancels all outstanding async operations on `*this`, as per \ref cancel.
0482      *
0483      * \par Thread-safety
0484      * Mutates the internal state handle. Mutates the pool state.
0485      * This function **can never be called concurrently with other functions
0486      * that read the internal state handle**, even for pools created
0487      * with \ref pool_params::thread_safe set to true.
0488      *
0489      * The internal pool state is modified as per \ref cancel.
0490      * If thread-safety is enabled, it's safe to call the destructor concurrently
0491      * with functions that only access the pool's internal state,
0492      * like returning connections.
0493      */
0494     ~connection_pool()
0495     {
0496         if (valid())
0497             cancel();
0498     }
0499 
0500     /**
0501      * \brief Returns whether the object is in a moved-from state.
0502      * \details
0503      * This function returns always `true` except for pools that have been
0504      * moved-from. Moved-from objects don't represent valid pools. They can only
0505      * be assigned to or destroyed.
0506      *
0507      * \par Exception safety
0508      * No-throw guarantee.
0509      *
0510      * \par Thread-safety
0511      * Reads the internal state handle. Does not access the pool state.
0512      * Can be called concurrently with any other function that reads the state handle,
0513      * like \ref async_run or \ref async_get_connection.
0514      * It can't be called concurrently with functions modifying the handle, like assignments,
0515      * even if \ref pool_params::thread_safe is set to true.
0516      */
0517     bool valid() const noexcept { return impl_.get() != nullptr; }
0518 
0519     /// The executor type associated to this object.
0520     using executor_type = asio::any_io_executor;
0521 
0522     /**
0523      * \brief Retrieves the executor associated to this object.
0524      * \details
0525      * Returns the executor used to construct the pool as first argument.
0526      * This is the case even when using \ref pool_params::thread_safe -
0527      * the internal strand created in this case is never exposed.
0528      *
0529      * \par Exception safety
0530      * No-throw guarantee.
0531      *
0532      * \par Thread-safety
0533      * Reads the internal state handle. Reads the pool state.
0534      * If the pool was built with thread-safety enabled, it can be called
0535      * concurrently with other functions that don't modify the state handle.
0536      */
0537     BOOST_MYSQL_DECL
0538     executor_type get_executor() noexcept;
0539 
0540     /**
0541      * \brief Runs the pool task in charge of managing connections.
0542      * \details
0543      * This function creates and connects new connections, and resets and pings
0544      * already created ones. You need to call this function for \ref async_get_connection
0545      * to succeed.
0546      *
0547      * The async operation will run indefinitely, until the pool is cancelled
0548      * (by calling \ref cancel or using per-operation cancellation on the `async_run` operation).
0549      * The operation completes once all internal connection operations
0550      * (including connects, pings and resets) complete.
0551      *
0552      * It is safe to call this function after calling \ref cancel.
0553      *
0554      * \par Preconditions
0555      * This function can be called at most once for a single pool.
0556      * Formally, `async_run` hasn't been called before on `*this` or any object
0557      * used to move-construct or move-assign `*this`.
0558      *
0559      * Additionally, `this->valid() == true`.
0560      *
0561      * \par Object lifetimes
0562      * While the operation is outstanding, the pool's internal data will be kept alive.
0563      * It is safe to destroy `*this` while the operation is outstanding.
0564      *
0565      * \par Handler signature
0566      * The handler signature for this operation is `void(boost::mysql::error_code)`
0567      *
0568      * \par Executor
0569      *
0570      * The final handler is executed using `token`'s associated executor,
0571      * or `this->get_executor()` if the token doesn't have an associated
0572      * executor. The final handler is called as if it was submitted using `asio::post`,
0573      * and is never be called inline from within this function.
0574      *
0575      * If the pool was constructed with thread-safety enabled, intermediate
0576      * completion handlers are executed using an internal strand that wraps `this->get_executor()`.
0577      * Otherwise, intermediate handlers are executed using `this->get_executor()`.
0578      * In any case, the token's associated executor is only used for the final handler.
0579      *
0580      * \par Per-operation cancellation
0581      * This operation supports per-operation cancellation. Cancelling `async_run`
0582      * is equivalent to calling \ref connection_pool::cancel.
0583      * The following `asio::cancellation_type_t` values are supported:
0584      *
0585      *   - `asio::cancellation_type_t::terminal`
0586      *   - `asio::cancellation_type_t::partial`
0587      *
0588      * Note that `asio::cancellation_type_t::total` is not supported because invoking
0589      * `async_run` always has observable side effects.
0590      *
0591      * \par Errors
0592      * This function always complete successfully. The handler signature ensures
0593      * maximum compatibility with Boost.Asio infrastructure.
0594      *
0595      * \par Thread-safety
0596      * Reads the internal state handle. Mutates the pool state.
0597      * If the pool was built with thread-safety enabled, it can be called
0598      * concurrently with other functions that don't modify the state handle.
0599      */
0600     template <
0601         BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
0602             CompletionToken = with_diagnostics_t<asio::deferred_t>>
0603     auto async_run(CompletionToken&& token = {})
0604         BOOST_MYSQL_RETURN_TYPE(decltype(asio::async_initiate<CompletionToken, void(error_code)>(
0605             std::declval<initiate_run>(),
0606             token,
0607             static_cast<diagnostics*>(nullptr),
0608             impl_
0609         )))
0610     {
0611         BOOST_ASSERT(valid());
0612         return asio::async_initiate<CompletionToken, void(error_code)>(
0613             initiate_run{get_executor()},
0614             token,
0615             static_cast<diagnostics*>(nullptr),
0616             impl_
0617         );
0618     }
0619 
0620     /**
0621      * \brief Retrieves a connection from the pool.
0622      * \details
0623      * Retrieves an idle connection from the pool to be used.
0624      *
0625      * If this function completes successfully (empty error code), the return \ref pooled_connection
0626      * will have `valid() == true` and will be usable. If it completes with a non-empty error code,
0627      * it will have `valid() == false`.
0628      *
0629      * If a connection is idle when the operation is started, it will complete immediately
0630      * with that connection. Otherwise, it will wait for a connection to become idle
0631      * (possibly creating one in the process, if pool configuration allows it), until
0632      * the operation is cancelled (by emitting a cancellation signal) or the pool
0633      * is cancelled (by calling \ref connection_pool::cancel).
0634      * If the pool is not running, the operation fails immediately.
0635      *
0636      * If the operation is cancelled, and the overload with \ref diagnostics was used,
0637      * the output diagnostics will contain the most recent error generated by
0638      * the connections attempting to connect (via \ref any_connection::async_connect), if any.
0639      * In cases where \ref async_get_connection doesn't complete because connections are unable
0640      * to connect, this feature can help figuring out where the problem is.
0641      *
0642      * \par Preconditions
0643      * `this->valid() == true` \n
0644      *
0645      * \par Object lifetimes
0646      * While the operation is outstanding, the pool's internal data will be kept alive.
0647      * It is safe to destroy `*this` while the operation is outstanding.
0648      *
0649      * \par Handler signature
0650      * The handler signature for this operation is
0651      * `void(boost::mysql::error_code, boost::mysql::pooled_connection)`
0652      *
0653      * \par Executor
0654      *
0655      * If the final handler has an associated immediate executor, and the operation
0656      * completes immediately, the final handler is dispatched to it.
0657      * Otherwise, the final handler is called as if it was submitted using `asio::post`,
0658      * and is never be called inline from within this function.
0659      * Immediate completions can only happen when thread-safety is not enabled.
0660      *
0661      * The final handler is executed using `token`'s associated executor,
0662      * or `this->get_executor()` if the token doesn't have an associated
0663      * executor.
0664      *
0665      * If the pool was constructed with thread-safety enabled, intermediate
0666      * completion handlers are executed using an internal strand that wraps `this->get_executor()`.
0667      * Otherwise, intermediate handlers are executed using
0668      * `token`'s associated executor if it has one, or `this->get_executor()` if it hasn't.
0669      *
0670      * **Caution**: be careful when using thread-safety and `asio::cancel_after`, as it
0671      * can result in inadvertent race conditions. Please refer to
0672      * <a href="../../../connection_pool.html#mysql.connection_pool.thread_safe">this
0673      * page</a> for more info.
0674      *
0675      * \par Per-operation cancellation
0676      * This operation supports per-operation cancellation.
0677      * Cancelling `async_get_connection` has no observable side effects.
0678      * The following `asio::cancellation_type_t` values are supported:
0679      *
0680      *   - `asio::cancellation_type_t::terminal`
0681      *   - `asio::cancellation_type_t::partial`
0682      *   - `asio::cancellation_type_t::total`
0683      *
0684      * \par Errors
0685      *   - \ref client_errc::no_connection_available, if the `async_get_connection`
0686      *     operation is cancelled before a connection becomes available.
0687      *   - \ref client_errc::pool_not_running, if the `async_get_connection`
0688      *     operation is cancelled before async_run is called.
0689      *   - \ref client_errc::pool_cancelled, if the pool is cancelled before
0690      *     the operation completes, or `async_get_connection` is called
0691      *     on a pool that has been cancelled.
0692      *
0693      * \par Thread-safety
0694      * Reads the internal state handle. Mutates the pool state.
0695      * If the pool was built with thread-safety enabled, it can be called
0696      * concurrently with other functions that don't modify the state handle.
0697      */
0698     template <
0699         BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::pooled_connection))
0700             CompletionToken = with_diagnostics_t<asio::deferred_t>>
0701     auto async_get_connection(CompletionToken&& token = {}) BOOST_MYSQL_RETURN_TYPE(
0702         decltype(async_get_connection_impl(nullptr, std::forward<CompletionToken>(token)))
0703     )
0704     {
0705         return async_get_connection_impl(nullptr, std::forward<CompletionToken>(token));
0706     }
0707 
0708     /// \copydoc async_get_connection
0709     template <
0710         BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::pooled_connection))
0711             CompletionToken = with_diagnostics_t<asio::deferred_t>>
0712     auto async_get_connection(diagnostics& diag, CompletionToken&& token = {}) BOOST_MYSQL_RETURN_TYPE(
0713         decltype(async_get_connection_impl(nullptr, std::forward<CompletionToken>(token)))
0714     )
0715     {
0716         return async_get_connection_impl(&diag, std::forward<CompletionToken>(token));
0717     }
0718 
0719     /**
0720      * \brief Stops any current outstanding operation and marks the pool as cancelled.
0721      * \details
0722      * This function has the following effects:
0723      *
0724      * \li Stops the currently outstanding \ref async_run operation, if any, which will complete
0725      *     with a success error code.
0726      * \li Cancels any outstanding \ref async_get_connection operations.
0727      * \li Marks the pool as cancelled. Successive `async_get_connection` calls will
0728      *     fail immediately.
0729      *
0730      * This function will return immediately, without waiting for the cancelled operations to complete.
0731      *
0732      * You may call this function any number of times. Successive calls will have no effect.
0733      *
0734      * \par Preconditions
0735      * `this->valid() == true`
0736      *
0737      * \par Exception safety
0738      * Basic guarantee. Memory allocations and acquiring mutexes may throw.
0739      *
0740      * \par Thread-safety
0741      * Reads the internal state handle. Mutates the pool state.
0742      * If the pool was built with thread-safety enabled, it can be called
0743      * concurrently with other functions that don't modify the state handle.
0744      */
0745     BOOST_MYSQL_DECL
0746     void cancel();
0747 };
0748 
0749 }  // namespace mysql
0750 }  // namespace boost
0751 
0752 #ifdef BOOST_MYSQL_HEADER_ONLY
0753 #include <boost/mysql/impl/connection_pool.ipp>
0754 #endif
0755 
0756 #endif