#ifndef QUERY_CONNECTION_POOL_HPP #define QUERY_CONNECTION_POOL_HPP #include #include #include #include #include namespace matador::sql { template < class Connection > class connection_pool; template < class Connection > class connection_ptr { public: connection_ptr(Connection *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* operator->() { return connection_; } Connection& operator*() { return *connection_; } [[nodiscard]] bool valid() const { return connection_ != nullptr; } private: friend class connection_pool; Connection *connection_; connection_pool &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 acquire() { std::lock_guard 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 guard(mutex_); if (inuse_connections_.erase(c) > 0) { idle_connections_.push(c); } } void release(connection_ptr &c) { release(c.connection_); c.connection_ = nullptr; } std::size_t size() const { return connection_repo_.size(); } std::size_t idle() const { std::lock_guard guard(mutex_); return idle_connections_.size(); } std::size_t inuse() const { std::lock_guard guard(mutex_); return inuse_connections_.size(); } private: mutable std::mutex mutex_; std::vector connection_repo_; using pointer = Connection*; using connections = std::queue; using connection_set = std::unordered_set; connections idle_connections_; connection_set inuse_connections_; }; template connection_ptr::~connection_ptr() { pool_.release(connection_); } } #endif //QUERY_CONNECTION_POOL_HPP