From 93b868aaafecdee525098a760dcf385a6c2ba3e2 Mon Sep 17 00:00:00 2001 From: Sascha Kuehl Date: Mon, 27 Nov 2023 17:26:14 +0100 Subject: [PATCH] enhanced connection pool of unique id for each connection --- include/matador/sql/connection_pool.hpp | 83 ++++++++++++++++++------- test/ConnectionPoolTest.cpp | 3 +- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/include/matador/sql/connection_pool.hpp b/include/matador/sql/connection_pool.hpp index e3f9c95..3e7b6f4 100644 --- a/include/matador/sql/connection_pool.hpp +++ b/include/matador/sql/connection_pool.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace matador::sql { @@ -12,64 +13,98 @@ namespace matador::sql { template < class Connection > class connection_pool; +template < class Connection > +using IdConnection = std::pair; + template < class Connection > class connection_ptr { public: - connection_ptr(Connection *c, connection_pool &pool) + connection_ptr(IdConnection *c, connection_pool &pool) : connection_(c), pool_(pool) {} ~connection_ptr(); connection_ptr(const connection_ptr &) = delete; connection_ptr& operator=(const connection_ptr &) = delete; - connection_ptr(connection_ptr &&) noexcept = default; - connection_ptr& operator=(connection_ptr &&) noexcept = default; + connection_ptr(connection_ptr &&x) noexcept + : connection_(x.connection_) + , pool_(x.pool_) + { + x.connection_ = nullptr; + } + connection_ptr& operator=(connection_ptr &&x) noexcept + { + if (this == &x) { + return *this; + } + connection_ = x.connection_; + pool_ = x.pool_; + x.connection_ = nullptr; - Connection* operator->() { return connection_; } - Connection& operator*() { return *connection_; } + return *this; + } + + Connection* operator->() { return &connection_->second; } + Connection& operator*() { return connection_->second; } + + [[nodiscard]] size_t id() const { return connection_->first; } [[nodiscard]] bool valid() const { return connection_ != nullptr; } private: friend class connection_pool; - Connection *connection_; + IdConnection *connection_; connection_pool &pool_; }; template < class Connection > class connection_pool { +public: + using connection_pointer = connection_ptr; + public: connection_pool(const std::string &dns, unsigned int count) : info_(connection_info::parse(dns)) { connection_repo_.reserve(count); for (auto i = 0U; i < count; ++i) { - connection_repo_.emplace_back(info_); - idle_connections_.push(&connection_repo_.back()); - idle_connections_.back()->open(); + connection_repo_.emplace_back(i+1, info_); + auto &conn = connection_repo_.back(); + idle_connections_.emplace(conn.first, &conn); + conn.second.open(); } } connection_ptr acquire() { - std::lock_guard guard(mutex_); + std::unique_lock lock(mutex_); if (idle_connections_.empty()) { return {nullptr, *this}; } - auto ptr = idle_connections_.front(); - idle_connections_.pop(); - inuse_connections_.insert(ptr); - return { ptr, *this }; + + pointer next_connection{nullptr}; + for (auto &item : idle_connections_) { + next_connection = item.second; + auto node = idle_connections_.extract(item.first); + inuse_connections_.insert(std::move(node)); + break; + } + return {next_connection, *this}; } - void release(Connection *c) { + connection_ptr acquire(size_t id) { + std::lock_guard guard(mutex_); + return {nullptr, *this}; + } + + void release(IdConnection *c) { if (c == nullptr) { return; } - std::lock_guard guard(mutex_); - - if (inuse_connections_.erase(c) > 0) { - idle_connections_.push(c); + std::unique_lock lock(mutex_); + if (auto it = inuse_connections_.find(c->first); it != inuse_connections_.end()) { + auto node = inuse_connections_.extract(it); + idle_connections_.insert(std::move(node)); } } @@ -93,12 +128,14 @@ public: } private: mutable std::mutex mutex_; - std::vector connection_repo_; - using pointer = Connection*; + std::vector> connection_repo_; + using pointer = IdConnection*; using connections = std::queue; + using connection_map = std::unordered_map; using connection_set = std::unordered_set; - connections idle_connections_; - connection_set inuse_connections_; +// connections idle_connections_; + connection_map inuse_connections_; + connection_map idle_connections_; const connection_info info_; }; diff --git a/test/ConnectionPoolTest.cpp b/test/ConnectionPoolTest.cpp index 6aa600e..88b0f34 100644 --- a/test/ConnectionPoolTest.cpp +++ b/test/ConnectionPoolTest.cpp @@ -16,8 +16,8 @@ TEST_CASE("Create connection pool", "[connection pool]") { auto ptr = pool.acquire(); REQUIRE(ptr.valid()); + REQUIRE(ptr.id() > 0); REQUIRE(ptr->is_open()); -// REQUIRE(!ptr->dns().empty()); REQUIRE(pool.idle() == 3); REQUIRE(pool.inuse() == 1); @@ -31,7 +31,6 @@ TEST_CASE("Create connection pool", "[connection pool]") { auto ptr2 = pool.acquire(); REQUIRE(ptr2.valid()); REQUIRE(ptr2->is_open()); -// REQUIRE(!ptr2->dns().empty()); REQUIRE(pool.idle() == 3); REQUIRE(pool.inuse() == 1);