Skip to content

Commit

Permalink
Track number of connections attached to a pool
Browse files Browse the repository at this point in the history
  • Loading branch information
d-frey committed Mar 1, 2024
1 parent 06ceb63 commit 3d60a0c
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 5 deletions.
12 changes: 12 additions & 0 deletions doc/Connection-Pool.md
Original file line number Diff line number Diff line change
Expand Up @@ -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();
};
Expand Down
44 changes: 39 additions & 5 deletions include/tao/pq/internal/pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef TAO_PQ_INTERNAL_POOL_HPP
#define TAO_PQ_INTERNAL_POOL_HPP

#include <atomic>
#include <cassert>
#include <list>
#include <memory>
Expand All @@ -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
{
Expand All @@ -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 );
}
}
Expand Down Expand Up @@ -77,36 +80,67 @@ 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
[[nodiscard]] auto get() -> std::shared_ptr< T >
{
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;
Expand Down

0 comments on commit 3d60a0c

Please sign in to comment.