1#ifndef NEFORCE_DATABASE_DATABASE_POOL_HPP__
2#define NEFORCE_DATABASE_DATABASE_POOL_HPP__
18NEFORCE_BEGIN_NAMESPACE__
57 struct connection_entry {
61 connection_entry() noexcept = default;
63 explicit connection_entry(idb_connect* c) :
65 idle_at(current_ms()) {}
67 NEFORCE_NODISCARD
milliseconds idle_duration() const noexcept {
return current_ms() - idle_at; }
69 static milliseconds current_ms() noexcept {
return time_cast<milliseconds>(steady_clock::now().since_epoch()); }
73 pool_config pool_cfg_;
74 unique_ptr<idb_factory> factory_;
76 queue<connection_entry> idle_queue_;
77 mutable mutex queue_mtx_;
78 condition_variable cv_;
80 atomic<size_t> total_count_{0};
81 atomic<bool> running_{
false};
83 thread replenish_thread_;
84 thread scanner_thread_;
86 idb_connect* try_create_connect() noexcept;
88 void return_connect(idb_connect* conn);
90 void replenish_task();
94 shared_ptr<T> acquire_impl();
96 template <typename T, typename Rep, typename Period>
97 shared_ptr<T> acquire_impl(const duration<Rep, Period>& timeout);
187 template <typename Rep, typename Period>
189 return acquire_impl<idb_connect>(
timeout);
199 template <
typename Rep,
typename Period>
201 return acquire_impl<idb_tb_connect>(
timeout);
211 template <
typename Rep,
typename Period>
213 return acquire_impl<idb_kv_connect>(
timeout);
235 const bool got = cv_.wait_for(lk, pool_cfg_.acquire_timeout,
236 [
this] { return !idle_queue_.empty() || !running_.load(memory_order_relaxed); });
242 if (!got || idle_queue_.empty()) {
243 const size_t cur = total_count_.load(memory_order_relaxed);
244 if (cur >= pool_cfg_.max_size) {
247 idb_connect* raw = try_create_connect();
248 if (raw ==
nullptr) {
252 total_count_.fetch_add(1, memory_order_relaxed);
253 T* typed =
dynamic_cast<T*
>(raw);
254 if (typed ==
nullptr) {
256 total_count_.fetch_sub(1, memory_order_relaxed);
259 return shared_ptr<T>(typed, [
this](T* p) { this->return_connect(p); });
262 const connection_entry entry = idle_queue_.front();
267 idb_connect* raw = entry.conn;
269 if (!raw->is_valid()) {
270 if (!raw->reconnect(config_)) {
272 total_count_.fetch_sub(1, memory_order_relaxed);
278 T* typed =
dynamic_cast<T*
>(raw);
279 if (typed ==
nullptr) {
280 this->return_connect(raw);
284 return shared_ptr<T>(typed, [
this](T* p) { this->return_connect(p); });
287template <
typename T,
typename Rep,
typename Period>
288shared_ptr<T> database_pool::acquire_impl(
const duration<Rep, Period>& timeout) {
289 unique_lock<mutex> lk(queue_mtx_);
292 cv_.wait_for(lk, timeout, [
this] {
return !idle_queue_.empty() || !running_.load(memory_order_relaxed); });
294 if (!running_.load(memory_order_relaxed)) {
298 if (!got || idle_queue_.empty()) {
299 const size_t cur = total_count_.load(memory_order_relaxed);
300 if (cur >= pool_cfg_.max_size) {
303 idb_connect* raw = try_create_connect();
304 if (raw ==
nullptr) {
308 total_count_.fetch_add(1, memory_order_relaxed);
309 T* typed =
dynamic_cast<T*
>(raw);
310 if (typed ==
nullptr) {
312 total_count_.fetch_sub(1, memory_order_relaxed);
315 return shared_ptr<T>(typed, [
this](T* p) { this->return_connect(p); });
318 const connection_entry entry = idle_queue_.front();
323 idb_connect* raw = entry.conn;
325 if (!raw->is_valid()) {
326 if (!raw->reconnect(config_)) {
328 total_count_.fetch_sub(1, memory_order_relaxed);
334 T* typed =
dynamic_cast<T*
>(raw);
335 if (typed ==
nullptr) {
336 this->return_connect(raw);
340 return shared_ptr<T>(typed, [
this](T* p) { this->return_connect(p); });
346NEFORCE_END_NAMESPACE__
shared_ptr< idb_tb_connect > get_tb_connect_for(const duration< Rep, Period > &timeout)
获取关系型数据库连接(自定义超时)
shared_ptr< idb_connect > get_connect()
获取通用数据库连接
bool is_running() const noexcept
检查连接池是否正在运行
void warm_up(size_t n)
预热连接池
shared_ptr< idb_kv_connect > get_kv_connect_for(const duration< Rep, Period > &timeout)
获取键值存储连接(自定义超时)
size_t idle_count() const noexcept
获取空闲连接数
size_t total_count() const noexcept
获取总连接数
database_pool(db_type type, const db_config &config, const pool_config &pool_config)
构造函数
database_pool(db_type type, const db_config &config)
构造函数
shared_ptr< idb_kv_connect > get_kv_connect()
获取键值存储连接
size_t active_count() const noexcept
获取活跃连接数
shared_ptr< idb_connect > get_connect_for(const duration< Rep, Period > &timeout)
获取通用数据库连接(自定义超时)
shared_ptr< idb_tb_connect > get_tb_connect()
获取关系型数据库连接
duration< int64_t > seconds
秒持续时间
duration< int64_t, milli > milliseconds
毫秒持续时间
constexpr auto memory_order_acquire
获取内存顺序常量
constexpr auto memory_order_relaxed
宽松内存顺序常量
seconds max_idle_time
连接最大空闲时间
milliseconds acquire_timeout
获取连接超时时间