108 lines
2.6 KiB
C++
108 lines
2.6 KiB
C++
#ifndef QUERY_CONNECTION_POOL_HPP
|
|
#define QUERY_CONNECTION_POOL_HPP
|
|
|
|
#include <utility>
|
|
#include <queue>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <unordered_set>
|
|
|
|
namespace matador::sql {
|
|
|
|
template < class Connection >
|
|
class connection_pool;
|
|
|
|
template < class Connection >
|
|
class connection_ptr
|
|
{
|
|
public:
|
|
connection_ptr(Connection *c, connection_pool<Connection> &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* operator->() { return connection_; }
|
|
Connection& operator*() { return *connection_; }
|
|
|
|
[[nodiscard]] bool valid() const { return connection_ != nullptr; }
|
|
|
|
private:
|
|
friend class connection_pool<Connection>;
|
|
|
|
Connection *connection_;
|
|
connection_pool<Connection> &pool_;
|
|
};
|
|
|
|
template < class Connection >
|
|
class connection_pool
|
|
{
|
|
public:
|
|
connection_pool(const std::string &db, unsigned int count) {
|
|
connection_repo_.reserve(count);
|
|
for (auto i = 0U; i < count; ++i) {
|
|
connection_repo_.emplace_back(db + std::to_string(i+1));
|
|
idle_connections_.push(&connection_repo_.back());
|
|
idle_connections_.back()->open();
|
|
}
|
|
}
|
|
|
|
connection_ptr<Connection> acquire() {
|
|
std::lock_guard<std::mutex> guard(mutex_);
|
|
if (idle_connections_.empty()) {
|
|
return {nullptr, *this};
|
|
}
|
|
|
|
auto ptr = idle_connections_.front();
|
|
idle_connections_.pop();
|
|
inuse_connections_.insert(ptr);
|
|
return { ptr, *this };
|
|
}
|
|
|
|
void release(Connection *c) {
|
|
if (c == nullptr) {
|
|
return;
|
|
}
|
|
std::lock_guard<std::mutex> guard(mutex_);
|
|
|
|
if (inuse_connections_.erase(c) > 0) {
|
|
idle_connections_.push(c);
|
|
}
|
|
}
|
|
|
|
void release(connection_ptr<Connection> &c) {
|
|
release(c.connection_);
|
|
c.connection_ = nullptr;
|
|
}
|
|
|
|
std::size_t size() const { return connection_repo_.size(); }
|
|
std::size_t idle() const {
|
|
std::lock_guard<std::mutex> guard(mutex_);
|
|
return idle_connections_.size();
|
|
}
|
|
std::size_t inuse() const {
|
|
std::lock_guard<std::mutex> guard(mutex_);
|
|
return inuse_connections_.size();
|
|
}
|
|
|
|
private:
|
|
mutable std::mutex mutex_;
|
|
std::vector<Connection> connection_repo_;
|
|
using pointer = Connection*;
|
|
using connections = std::queue<pointer>;
|
|
using connection_set = std::unordered_set<pointer>;
|
|
connections idle_connections_;
|
|
connection_set inuse_connections_;
|
|
};
|
|
|
|
template<class Connection>
|
|
connection_ptr<Connection>::~connection_ptr() {
|
|
pool_.release(connection_);
|
|
}
|
|
|
|
}
|
|
|
|
#endif //QUERY_CONNECTION_POOL_HPP
|