![]() |
|
|||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |