diff --git a/include/crucible/pool.h b/include/crucible/pool.h index ccb634b..7377169 100644 --- a/include/crucible/pool.h +++ b/include/crucible/pool.h @@ -37,28 +37,26 @@ namespace crucible { void clear(); private: - using ListType = list; - struct ListRep { - ListType m_list; + struct PoolRep { + list m_list; mutex m_mutex; - bool m_destroyed = false; Checker m_checkin; - ListRep(Checker checkin); + PoolRep(Checker checkin); }; struct Handle { - shared_ptr m_list_rep; + weak_ptr m_list_rep; Ptr m_ret_ptr; - Handle(shared_ptr list_rep, Ptr ret_ptr); + Handle(shared_ptr list_rep, Ptr ret_ptr); ~Handle(); }; Generator m_fn; Checker m_checkout; - shared_ptr m_list_rep; + shared_ptr m_list_rep; }; template - Pool::ListRep::ListRep(Checker checkin) : + Pool::PoolRep::PoolRep(Checker checkin) : m_checkin(checkin) { } @@ -67,20 +65,20 @@ namespace crucible { Pool::Pool(Generator f, Checker checkin, Checker checkout) : m_fn(f), m_checkout(checkout), - m_list_rep(make_shared(checkin)) + m_list_rep(make_shared(checkin)) { } template Pool::~Pool() { - unique_lock lock(m_list_rep->m_mutex); - m_list_rep->m_destroyed = true; - m_list_rep->m_list.clear(); + auto list_rep = m_list_rep; + unique_lock lock(list_rep->m_mutex); + m_list_rep.reset(); } template - Pool::Handle::Handle(shared_ptr list_rep, Ptr ret_ptr) : + Pool::Handle::Handle(shared_ptr list_rep, Ptr ret_ptr) : m_list_rep(list_rep), m_ret_ptr(ret_ptr) { @@ -89,25 +87,25 @@ namespace crucible { template Pool::Handle::~Handle() { - unique_lock lock(m_list_rep->m_mutex); - // Checkin prepares the object for storage and reuse. // Neither of those will happen if there is no Pool. // If the Pool was destroyed, just let m_ret_ptr expire. - if (!m_list_rep->m_destroyed) { - - // If a checkin function is defined, call it - auto checkin = m_list_rep->m_checkin; - if (checkin) { - lock.unlock(); - checkin(m_ret_ptr); - lock.lock(); - } - - // Place object back in pool - m_list_rep->m_list.push_front(m_ret_ptr); - + auto list_rep = m_list_rep.lock(); + if (!list_rep) { + return; } + + unique_lock lock(list_rep->m_mutex); + // If a checkin function is defined, call it + auto checkin = list_rep->m_checkin; + if (checkin) { + lock.unlock(); + checkin(m_ret_ptr); + lock.lock(); + } + + // Place object back in pool + list_rep->m_list.push_front(m_ret_ptr); } template @@ -132,7 +130,7 @@ namespace crucible { lock.unlock(); } - // rv now points to a new T object that is not in the list. + // rv now points to a T object that is not in the list. THROW_CHECK0(runtime_error, rv); // Construct a shared_ptr for Handle which will refcount the Handle objects