enhanced connection pool of unique id for each connection
This commit is contained in:
parent
6a4111ba3d
commit
93b868aaaf
|
|
@ -5,6 +5,7 @@
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
@ -12,64 +13,98 @@ namespace matador::sql {
|
||||||
template < class Connection >
|
template < class Connection >
|
||||||
class connection_pool;
|
class connection_pool;
|
||||||
|
|
||||||
|
template < class Connection >
|
||||||
|
using IdConnection = std::pair<size_t, Connection>;
|
||||||
|
|
||||||
template < class Connection >
|
template < class Connection >
|
||||||
class connection_ptr
|
class connection_ptr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
connection_ptr(Connection *c, connection_pool<Connection> &pool)
|
connection_ptr(IdConnection<Connection> *c, connection_pool<Connection> &pool)
|
||||||
: connection_(c), pool_(pool) {}
|
: connection_(c), pool_(pool) {}
|
||||||
~connection_ptr();
|
~connection_ptr();
|
||||||
connection_ptr(const connection_ptr &) = delete;
|
connection_ptr(const connection_ptr &) = delete;
|
||||||
connection_ptr& operator=(const connection_ptr &) = delete;
|
connection_ptr& operator=(const connection_ptr &) = delete;
|
||||||
connection_ptr(connection_ptr &&) noexcept = default;
|
connection_ptr(connection_ptr &&x) noexcept
|
||||||
connection_ptr& operator=(connection_ptr &&) noexcept = default;
|
: 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_; }
|
return *this;
|
||||||
Connection& operator*() { return *connection_; }
|
}
|
||||||
|
|
||||||
|
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; }
|
[[nodiscard]] bool valid() const { return connection_ != nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class connection_pool<Connection>;
|
friend class connection_pool<Connection>;
|
||||||
|
|
||||||
Connection *connection_;
|
IdConnection<Connection> *connection_;
|
||||||
connection_pool<Connection> &pool_;
|
connection_pool<Connection> &pool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template < class Connection >
|
template < class Connection >
|
||||||
class connection_pool
|
class connection_pool
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using connection_pointer = connection_ptr<Connection>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
connection_pool(const std::string &dns, unsigned int count)
|
connection_pool(const std::string &dns, unsigned int count)
|
||||||
: info_(connection_info::parse(dns)) {
|
: info_(connection_info::parse(dns)) {
|
||||||
connection_repo_.reserve(count);
|
connection_repo_.reserve(count);
|
||||||
for (auto i = 0U; i < count; ++i) {
|
for (auto i = 0U; i < count; ++i) {
|
||||||
connection_repo_.emplace_back(info_);
|
connection_repo_.emplace_back(i+1, info_);
|
||||||
idle_connections_.push(&connection_repo_.back());
|
auto &conn = connection_repo_.back();
|
||||||
idle_connections_.back()->open();
|
idle_connections_.emplace(conn.first, &conn);
|
||||||
|
conn.second.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_ptr<Connection> acquire() {
|
connection_ptr<Connection> acquire() {
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
std::unique_lock<std::mutex> lock(mutex_);
|
||||||
if (idle_connections_.empty()) {
|
if (idle_connections_.empty()) {
|
||||||
return {nullptr, *this};
|
return {nullptr, *this};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ptr = idle_connections_.front();
|
|
||||||
idle_connections_.pop();
|
pointer next_connection{nullptr};
|
||||||
inuse_connections_.insert(ptr);
|
for (auto &item : idle_connections_) {
|
||||||
return { ptr, *this };
|
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<Connection> acquire(size_t id) {
|
||||||
|
std::lock_guard<std::mutex> guard(mutex_);
|
||||||
|
return {nullptr, *this};
|
||||||
|
}
|
||||||
|
|
||||||
|
void release(IdConnection<Connection> *c) {
|
||||||
if (c == nullptr) {
|
if (c == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
std::unique_lock<std::mutex> lock(mutex_);
|
||||||
|
if (auto it = inuse_connections_.find(c->first); it != inuse_connections_.end()) {
|
||||||
if (inuse_connections_.erase(c) > 0) {
|
auto node = inuse_connections_.extract(it);
|
||||||
idle_connections_.push(c);
|
idle_connections_.insert(std::move(node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,12 +128,14 @@ public:
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
mutable std::mutex mutex_;
|
mutable std::mutex mutex_;
|
||||||
std::vector<Connection> connection_repo_;
|
std::vector<IdConnection<Connection>> connection_repo_;
|
||||||
using pointer = Connection*;
|
using pointer = IdConnection<Connection>*;
|
||||||
using connections = std::queue<pointer>;
|
using connections = std::queue<pointer>;
|
||||||
|
using connection_map = std::unordered_map<size_t, pointer>;
|
||||||
using connection_set = std::unordered_set<pointer>;
|
using connection_set = std::unordered_set<pointer>;
|
||||||
connections idle_connections_;
|
// connections idle_connections_;
|
||||||
connection_set inuse_connections_;
|
connection_map inuse_connections_;
|
||||||
|
connection_map idle_connections_;
|
||||||
|
|
||||||
const connection_info info_;
|
const connection_info info_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ TEST_CASE("Create connection pool", "[connection pool]") {
|
||||||
|
|
||||||
auto ptr = pool.acquire();
|
auto ptr = pool.acquire();
|
||||||
REQUIRE(ptr.valid());
|
REQUIRE(ptr.valid());
|
||||||
|
REQUIRE(ptr.id() > 0);
|
||||||
REQUIRE(ptr->is_open());
|
REQUIRE(ptr->is_open());
|
||||||
// REQUIRE(!ptr->dns().empty());
|
|
||||||
|
|
||||||
REQUIRE(pool.idle() == 3);
|
REQUIRE(pool.idle() == 3);
|
||||||
REQUIRE(pool.inuse() == 1);
|
REQUIRE(pool.inuse() == 1);
|
||||||
|
|
@ -31,7 +31,6 @@ TEST_CASE("Create connection pool", "[connection pool]") {
|
||||||
auto ptr2 = pool.acquire();
|
auto ptr2 = pool.acquire();
|
||||||
REQUIRE(ptr2.valid());
|
REQUIRE(ptr2.valid());
|
||||||
REQUIRE(ptr2->is_open());
|
REQUIRE(ptr2->is_open());
|
||||||
// REQUIRE(!ptr2->dns().empty());
|
|
||||||
|
|
||||||
REQUIRE(pool.idle() == 3);
|
REQUIRE(pool.idle() == 3);
|
||||||
REQUIRE(pool.inuse() == 1);
|
REQUIRE(pool.inuse() == 1);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue