From 3d60a0c29bc0f57ae3eaea603367b468a55e7b82 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Sat, 2 Mar 2024 00:21:28 +0100 Subject: [PATCH] Track number of connections attached to a pool --- doc/Connection-Pool.md | 12 +++++++++ include/tao/pq/internal/pool.hpp | 44 ++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/doc/Connection-Pool.md b/doc/Connection-Pool.md index 9ecbef7..e54cc23 100644 --- a/doc/Connection-Pool.md +++ b/doc/Connection-Pool.md @@ -80,6 +80,18 @@ namespace tao::pq return connection()->execute( statement, std::forward< As >( as )... ); } + // checks whether the pool contains idle connections + auto empty() const noexcept + -> bool; + + // number of idle connections + auto size() const noexcept + -> std::size_t; + + // number of borrowed connections + auto attached() const noexcept + -> std::size_t; + // cleanup void erase_invalid(); }; diff --git a/include/tao/pq/internal/pool.hpp b/include/tao/pq/internal/pool.hpp index 68c0cbb..246450d 100644 --- a/include/tao/pq/internal/pool.hpp +++ b/include/tao/pq/internal/pool.hpp @@ -5,6 +5,7 @@ #ifndef TAO_PQ_INTERNAL_POOL_HPP #define TAO_PQ_INTERNAL_POOL_HPP +#include #include #include #include @@ -19,7 +20,8 @@ namespace tao::pq::internal { private: std::list< std::shared_ptr< T > > m_items; - std::mutex m_mutex; + mutable std::mutex m_mutex; + std::atomic< std::size_t > m_attached = 0; struct deleter final { @@ -35,6 +37,7 @@ namespace tao::pq::internal { std::unique_ptr< T > up( item ); if( const auto p = m_pool.lock() ) { + --( p->m_attached ); p->push( up ); } } @@ -77,22 +80,33 @@ namespace tao::pq::internal static void attach( const std::shared_ptr< T >& sp, std::weak_ptr< pool >&& p ) noexcept { - deleter* d = std::get_deleter< deleter >( sp ); + const auto d = std::get_deleter< deleter >( sp ); assert( d ); + if( const auto o = d->m_pool.lock() ) { + --( o->m_attached ); + } d->m_pool = std::move( p ); + if( const auto n = d->m_pool.lock() ) { + ++( n->m_attached ); + } } static void detach( const std::shared_ptr< T >& sp ) noexcept { - deleter* d = std::get_deleter< deleter >( sp ); + const auto d = std::get_deleter< deleter >( sp ); assert( d ); + if( const auto o = d->m_pool.lock() ) { + --( o->m_attached ); + } d->m_pool.reset(); } // create a new T which is put into the pool when no longer used [[nodiscard]] auto create() -> std::shared_ptr< T > { - return { v_create().release(), pool::deleter( this->weak_from_this() ) }; + const std::shared_ptr< T > c{ v_create().release(), pool::deleter( this->weak_from_this() ) }; + ++m_attached; + return c; } // get an instance from the pool or create a new one if necessary @@ -100,13 +114,33 @@ namespace tao::pq::internal { while( const auto sp = pull() ) { if( this->v_is_valid( *sp ) ) { - pool::attach( sp, this->weak_from_this() ); + const auto d = std::get_deleter< deleter >( sp ); + assert( d ); + d->m_pool = this->weak_from_this(); + ++m_attached; return sp; } } return create(); } + [[nodiscard]] auto empty() const noexcept -> bool + { + const std::lock_guard lock( m_mutex ); + return m_items.empty(); + } + + [[nodiscard]] auto size() const noexcept -> std::size_t + { + const std::lock_guard lock( m_mutex ); + return m_items.size(); + } + + [[nodiscard]] auto attached() const noexcept -> std::size_t + { + return m_attached; + } + void erase_invalid() { std::list< std::shared_ptr< T > > deferred_delete;