diff --git a/include/sqlpp11/connection.h b/include/sqlpp11/connection.h index 2291c2ea..bb3b8f98 100644 --- a/include/sqlpp11/connection.h +++ b/include/sqlpp11/connection.h @@ -37,7 +37,7 @@ namespace sqlpp }; // Normal (non-pooled) connection - template + template class normal_connection : public ConnectionBase { public: @@ -46,8 +46,15 @@ namespace sqlpp // Constructors normal_connection() = default; - normal_connection(const _config_t& config); - normal_connection(const _config_ptr_t& config); + + normal_connection(const _config_t& config) : normal_connection{std::make_shared<_config_t>(config)} + { + } + + normal_connection(const _config_ptr_t& config) : ConnectionBase{std::make_unique<_handle_t>(config)} + { + } + normal_connection(const normal_connection&) = delete; normal_connection(normal_connection&&) = default; @@ -56,36 +63,21 @@ namespace sqlpp normal_connection& operator=(normal_connection&&) = default; // creates a connection handle and connects to database - void connectUsing(const _config_ptr_t& config) noexcept(false); + void connectUsing(const _config_ptr_t& config) noexcept(false) + { + ConnectionBase::_handle = std::make_unique<_handle_t>(config); + } private: using _handle_t = typename ConnectionBase::_handle_t; }; - template - normal_connection::normal_connection(const _config_t& config) : - normal_connection{std::make_shared<_config_t>(config)} - { - } - - template - normal_connection::normal_connection(const _config_ptr_t& config) : - ConnectionBase{std::make_unique<_handle_t>(config)} - { - } - - template - void normal_connection::connectUsing(const _config_ptr_t& config) noexcept(false) - { - ConnectionBase::_handle = std::make_unique<_handle_t>(config); - } - // Forward declaration - template + template class connection_pool; // Pooled connection - template + template class pooled_connection : public ConnectionBase { friend class connection_pool::pool_core; @@ -99,59 +91,47 @@ namespace sqlpp // Copy/Move constructors pooled_connection(const pooled_connection&) = delete; pooled_connection(pooled_connection&& other) = default; - ~pooled_connection(); + + ~pooled_connection() + { + conn_release(); + } // Assigment operators pooled_connection& operator=(const pooled_connection&) = delete; - pooled_connection& operator=(pooled_connection&& other); + + pooled_connection& operator=(pooled_connection&& other) + { + if (this != &other) + { + conn_release(); + static_cast(*this) = std::move(static_cast(other)); + _pool_core = std::move(other._pool_core); + } + return *this; + } private: _pool_core_ptr_t _pool_core; // Constructors used by the connection pool - pooled_connection(_handle_ptr_t&& handle, _pool_core_ptr_t pool_core); - pooled_connection(const _config_ptr_t& config, _pool_core_ptr_t pool_core); + pooled_connection(_handle_ptr_t&& handle, _pool_core_ptr_t pool_core) + : ConnectionBase{std::move(handle)}, _pool_core{pool_core} + { + } - void conn_release(); + pooled_connection(const _config_ptr_t& config, _pool_core_ptr_t pool_core) + : ConnectionBase{std::make_unique<_handle_t>(config)}, _pool_core{pool_core} + { + } + + void conn_release() + { + if (_pool_core) + { + _pool_core->put(ConnectionBase::_handle); + _pool_core = nullptr; + } + } }; - - template - pooled_connection::~pooled_connection() - { - conn_release(); - } - - template - pooled_connection& pooled_connection::operator=(pooled_connection&& other) - { - if (this != &other) { - conn_release(); - static_cast(*this) = std::move(static_cast(other)); - _pool_core = std::move(other._pool_core); - } - return *this; - } - - template - pooled_connection::pooled_connection(_handle_ptr_t&& handle, _pool_core_ptr_t pool_core) : - ConnectionBase{std::move(handle)}, - _pool_core{pool_core} - { - } - - template - pooled_connection::pooled_connection(const _config_ptr_t& config, _pool_core_ptr_t pool_core) : - ConnectionBase{std::make_unique<_handle_t>(config)}, - _pool_core{pool_core} - { - } - - template - void pooled_connection::conn_release() - { - if (_pool_core) { - _pool_core->put(ConnectionBase::_handle); - _pool_core = nullptr; - } - } } // namespace sqlpp diff --git a/include/sqlpp11/connection_pool.h b/include/sqlpp11/connection_pool.h index 6fb044d5..bccf395e 100644 --- a/include/sqlpp11/connection_pool.h +++ b/include/sqlpp11/connection_pool.h @@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace sqlpp { - template + template class connection_pool { public: @@ -44,18 +44,50 @@ namespace sqlpp class pool_core : public std::enable_shared_from_this { public: - pool_core(const _config_ptr_t& connection_config, std::size_t capacity); + pool_core(const _config_ptr_t& connection_config, std::size_t capacity) + : _connection_config{connection_config}, _handles{capacity} + { + } + pool_core() = delete; - pool_core(const pool_core &) = delete; - pool_core(pool_core &&) = delete; + pool_core(const pool_core&) = delete; + pool_core(pool_core&&) = delete; pool_core& operator=(const pool_core&) = delete; pool_core& operator=(pool_core&&) = delete; - _pooled_connection_t get(); - void put(_handle_ptr_t& handle); + _pooled_connection_t get() + { + std::unique_lock lock{_mutex}; + if (_handles.empty()) + { + lock.unlock(); + return _pooled_connection_t{_connection_config, this->shared_from_this()}; + } + auto handle = std::move(_handles.front()); + _handles.pop_front(); + lock.unlock(); + // If the fetched connection is dead, drop it and create a new one on the fly + return handle->check_connection() ? _pooled_connection_t{std::move(handle), this->shared_from_this()} + : _pooled_connection_t{_connection_config, this->shared_from_this()}; + } + + void put(_handle_ptr_t& handle) + { + std::unique_lock lock{_mutex}; + if (_handles.full()) + { + _handles.set_capacity(_handles.capacity() + 5); + } + _handles.push_back(std::move(handle)); + } + // Returns number of connections available in the pool. Only used in tests. - std::size_t available(); + std::size_t available() + { + std::unique_lock lock{_mutex}; + return _handles.size(); + } private: _config_ptr_t _connection_config; @@ -64,88 +96,39 @@ namespace sqlpp }; connection_pool() = default; - connection_pool(const _config_ptr_t& connection_config, std::size_t capacity); + + connection_pool(const _config_ptr_t& connection_config, std::size_t capacity) + : _core{std::make_shared(connection_config, capacity)} + { + } + connection_pool(const connection_pool&) = delete; connection_pool(connection_pool&&) = default; connection_pool& operator=(const connection_pool&) = delete; connection_pool& operator=(connection_pool&&) = default; - void initialize(const _config_ptr_t& connection_config, std::size_t capacity); - _pooled_connection_t get(); + void initialize(const _config_ptr_t& connection_config, std::size_t capacity) + { + if (_core) + { + throw std::runtime_error{"Connection pool already initialized"}; + } + _core = std::make_shared(connection_config, capacity); + } + + _pooled_connection_t get() + { + return _core->get(); + } + // Returns number of connections available in the pool. Only used in tests. - std::size_t available(); + std::size_t available() + { + return _core->available(); + } private: std::shared_ptr _core; }; - - template - connection_pool::pool_core::pool_core(const _config_ptr_t& connection_config, std::size_t capacity) : - _connection_config{connection_config}, - _handles{capacity} - { - } - - template - typename connection_pool::_pooled_connection_t connection_pool::pool_core::get() - { - std::unique_lock lock{_mutex}; - if (_handles.empty()) { - lock.unlock(); - return _pooled_connection_t{_connection_config, this->shared_from_this()}; - } - auto handle = std::move(_handles.front()); - _handles.pop_front(); - lock.unlock(); - // If the fetched connection is dead, drop it and create a new one on the fly - return - handle->check_connection() ? - _pooled_connection_t{std::move(handle), this->shared_from_this()} : - _pooled_connection_t{_connection_config, this->shared_from_this()}; - } - - template - void connection_pool::pool_core::put(_handle_ptr_t& handle) - { - std::unique_lock lock{_mutex}; - if (_handles.full ()) { - _handles.set_capacity (_handles.capacity () + 5); - } - _handles.push_back(std::move(handle)); - } - - template - std::size_t connection_pool::pool_core::available() - { - std::unique_lock lock{_mutex}; - return _handles.size(); - } - - template - connection_pool::connection_pool(const _config_ptr_t& connection_config, std::size_t capacity) : - _core{std::make_shared(connection_config, capacity)} - { - } - - template - void connection_pool::initialize(const _config_ptr_t& connection_config, std::size_t capacity) - { - if (_core) { - throw std::runtime_error{"Connection pool already initialized"}; - } - _core = std::make_shared(connection_config, capacity); - } - - template - typename connection_pool::_pooled_connection_t connection_pool::get() - { - return _core->get(); - } - - template - std::size_t connection_pool::available() - { - return _core->available(); - } -} // namespace sqlpp +} // namespace sqlpp