diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-11-18 01:25:50 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-11-18 01:25:50 +0000 |
commit | 89231894c7cd095b811129ca034e31b9017610fb (patch) | |
tree | 8138cd14c79a3a1b43c6bd7a4c29fc0b6f1cc5cd | |
parent | Prevent test failed due to race condition (diff) | |
download | libadhocutil-89231894c7cd095b811129ca034e31b9017610fb.tar.bz2 libadhocutil-89231894c7cd095b811129ca034e31b9017610fb.tar.xz libadhocutil-89231894c7cd095b811129ca034e31b9017610fb.zip |
Implement and test resource testing and replacement on reuse.
-rw-r--r-- | libadhocutil/resourcePool.h | 2 | ||||
-rw-r--r-- | libadhocutil/resourcePool.impl.h | 32 | ||||
-rw-r--r-- | 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 <typename R> void - ResourcePool<R>::destroyResource(R * r) const + ResourcePool<R>::destroyResource(R * r) const throw() { delete r; } @@ -166,20 +166,24 @@ namespace AdHoc { ResourceHandle<R> ResourcePool<R>::getOne() { - UpgradableLock(lock, ulock); - if (available.empty()) { - auto ro = new typename ResourceHandle<R>::Object(createResource(), this); - UpgradeLock(ulock); - inUse.insert({ std::this_thread::get_id(), ro }); - return ro; - } - else { - UpgradeLock(ulock); - auto ro = new typename ResourceHandle<R>::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<R>::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<R>::Object(createResource(), this); + inUse.insert({ std::this_thread::get_id(), ro }); + return ro; } template <typename R> 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); + } +} + |