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); +	} +} + | 
