Browse Source

Ability to force cleanup of ResourceManager.

Assumes that no resources of given type are referenced. The test case
for this is awful, as I can't think of a way to test which would work
without trying to decrement reference counter on already deleted
resource. Added just-to-be-sure assertion to make it fail early and not
somewhere deep in STL.
pull/277/head
Vladimír Vondruš 13 years ago
parent
commit
c1c4788e88
  1. 33
      src/ResourceManager.h
  2. 33
      src/Test/ResourceManagerTest.cpp

33
src/ResourceManager.h

@ -122,6 +122,8 @@ template<class T> class ResourceManagerData {
void free();
void clear() { _data.clear(); }
AbstractResourceLoader<T>* loader() { return _loader; }
const AbstractResourceLoader<T>* loader() const { return _loader; }
@ -353,6 +355,28 @@ template<class... Types> class ResourceManager: private Implementation::Resource
return this;
}
/**
* @brief Clear all resources of given type
* @return Pointer to self (for method chaining)
*
* Unlike free() this function assumes that no resource is referenced.
*/
template<class T> ResourceManager<Types...>* clear() {
this->Implementation::ResourceManagerData<T>::clear();
return this;
}
/**
* @brief Clear all resources
* @return Pointer to self (for method chaining)
*
* Unlike free() this function assumes that no resource is referenced.
*/
ResourceManager<Types...>* clear() {
clearInternal<Types...>();
return this;
}
/** @brief Loader for given type of resources */
template<class T> AbstractResourceLoader<T>* loader() {
return this->Implementation::ResourceManagerData<T>::loader();
@ -383,6 +407,12 @@ template<class... Types> class ResourceManager: private Implementation::Resource
}
template<class...> void freeInternal() const {}
template<class FirstType, class ...NextTypes> void clearInternal() {
clear<FirstType>();
clearInternal<NextTypes...>();
}
template<class...> void clearInternal() const {}
template<class FirstType, class ...NextTypes> void freeLoaders() {
Implementation::ResourceManagerData<FirstType>::freeLoader();
freeLoaders<NextTypes...>();
@ -513,6 +543,7 @@ template<class T> void ResourceManagerData<T>::freeLoader() {
template<class T> void ResourceManagerData<T>::decrementReferenceCount(ResourceKey key) {
auto it = _data.find(key);
CORRADE_INTERNAL_ASSERT(it != _data.end());
/* Free the resource if it is reference counted */
if(--it->second.referenceCount == 0 && it->second.policy == ResourcePolicy::ReferenceCounted)
@ -541,7 +572,7 @@ template<class T> struct ResourceManagerData<T>::Data {
template<class T> inline ResourceManagerData<T>::Data::~Data() {
CORRADE_ASSERT(referenceCount == 0,
"ResourceManager::~ResourceManager(): destroyed while data are still referenced", );
"ResourceManager: cleared/destroyed while data are still referenced", );
delete data;
}

33
src/Test/ResourceManagerTest.cpp

@ -43,6 +43,8 @@ class ResourceManagerTest: public TestSuite::Tester {
void residentPolicy();
void referenceCountedPolicy();
void manualPolicy();
void clear();
void clearWhileReferenced();
void loader();
};
@ -66,6 +68,8 @@ ResourceManagerTest::ResourceManagerTest() {
&ResourceManagerTest::residentPolicy,
&ResourceManagerTest::referenceCountedPolicy,
&ResourceManagerTest::manualPolicy,
&ResourceManagerTest::clear,
&ResourceManagerTest::clearWhileReferenced,
&ResourceManagerTest::loader});
}
@ -226,6 +230,35 @@ void ResourceManagerTest::manualPolicy() {
CORRADE_COMPARE(Data::count, 1);
}
void ResourceManagerTest::clear() {
ResourceManager rm;
rm.set("blah", new Data);
CORRADE_COMPARE(Data::count, 1);
rm.free();
CORRADE_COMPARE(Data::count, 1);
rm.clear();
CORRADE_COMPARE(Data::count, 0);
}
void ResourceManagerTest::clearWhileReferenced() {
/* Should cover also the destruction case */
std::ostringstream out;
Error::setOutput(&out);
ResourceManager rm;
rm.set("blah", new Int);
/** @todo this will leak, is there any better solution without hitting
assertion in decrementReferenceCount()? */
new Resource<Int>(rm.get<Int>("blah"));
rm.clear();
CORRADE_COMPARE(out.str(), "ResourceManager: cleared/destroyed while data are still referenced\n");
}
void ResourceManagerTest::loader() {
class IntResourceLoader: public AbstractResourceLoader<Int> {
public:

Loading…
Cancel
Save