From 89231894c7cd095b811129ca034e31b9017610fb Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 18 Nov 2015 01:25:50 +0000 Subject: Implement and test resource testing and replacement on reuse. --- libadhocutil/resourcePool.h | 2 +- libadhocutil/resourcePool.impl.h | 32 ++++++++++++++----------- libadhocutil/unittests/testResourcePool.cpp | 37 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/libadhocutil/resourcePool.h b/libadhocutil/resourcePool.h index f3683ae..5ccb516 100644 --- a/libadhocutil/resourcePool.h +++ b/libadhocutil/resourcePool.h @@ -76,7 +76,7 @@ namespace AdHoc { /// Create a new resource instance to add to the pool. virtual Resource * createResource() const = 0; /// Destroy an existing resource (defaults to delete). - virtual void destroyResource(Resource *) const; + virtual void destroyResource(Resource *) const throw(); /// Test a cached resource is still suitable for use (defaults to no-op). virtual void testResource(const Resource *) const; diff --git a/libadhocutil/resourcePool.impl.h b/libadhocutil/resourcePool.impl.h index d4fcfe4..85a6d3d 100644 --- a/libadhocutil/resourcePool.impl.h +++ b/libadhocutil/resourcePool.impl.h @@ -98,7 +98,7 @@ namespace AdHoc { template void - ResourcePool::destroyResource(R * r) const + ResourcePool::destroyResource(R * r) const throw() { delete r; } @@ -166,20 +166,24 @@ namespace AdHoc { ResourceHandle ResourcePool::getOne() { - UpgradableLock(lock, ulock); - if (available.empty()) { - auto ro = new typename ResourceHandle::Object(createResource(), this); - UpgradeLock(ulock); - inUse.insert({ std::this_thread::get_id(), ro }); - return ro; - } - else { - UpgradeLock(ulock); - auto ro = new typename ResourceHandle::Object(available.front(), this); - available.pop_front(); - inUse.insert({ std::this_thread::get_id(), ro }); - return ro; + Lock(lock); + while (!available.empty()) { + auto r = available.front(); + try { + testResource(r); + auto ro = new typename ResourceHandle::Object(r, this); + available.pop_front(); + inUse.insert({ std::this_thread::get_id(), ro }); + return ro; + } + catch (...) { + destroyResource(r); + available.pop_front(); + } } + auto ro = new typename ResourceHandle::Object(createResource(), this); + inUse.insert({ std::this_thread::get_id(), ro }); + return ro; } template diff --git a/libadhocutil/unittests/testResourcePool.cpp b/libadhocutil/unittests/testResourcePool.cpp index 6e62730..349ea00 100644 --- a/libadhocutil/unittests/testResourcePool.cpp +++ b/libadhocutil/unittests/testResourcePool.cpp @@ -245,3 +245,40 @@ BOOST_AUTO_TEST_CASE( threading2 ) BOOST_REQUIRE_EQUAL(1, pool.availableCount()); } +class TTRP : public TRP { + public: + TTRP() : n(0) { } + void testResource(const MockResource *) const override + { + n += 1; + if (n % 2) { + throw std::exception(); + } + } + private: + mutable int n; +}; + +BOOST_AUTO_TEST_CASE( test ) +{ + TTRP pool; + MockResource * rp; + { + auto r = pool.get(); + rp = r.get(); + } + { + auto r = pool.get(); + BOOST_REQUIRE(r.get()); + BOOST_REQUIRE(rp != r.get()); + BOOST_REQUIRE_EQUAL(1, MockResource::count); + rp = r.get(); + } + { + auto r = pool.get(); + BOOST_REQUIRE(r.get()); + BOOST_REQUIRE(rp == r.get()); + BOOST_REQUIRE_EQUAL(1, MockResource::count); + } +} + -- cgit v1.2.3