Browse Source

Deleting all resource loaders before unloading any resource data.

Previously was done per type (i.e. for each type delete loader and then
the data), wasn't usable when the loader stored different resource type
(which is the only case where it is useful).
pull/277/head
Vladimír Vondruš 13 years ago
parent
commit
8bce5114da
  1. 7
      src/AbstractResourceLoader.h
  2. 24
      src/ResourceManager.h
  3. 54
      src/Test/ResourceManagerTest.cpp

7
src/AbstractResourceLoader.h

@ -78,7 +78,12 @@ class MeshResourceLoader: public AbstractResourceLoader<Mesh> {
};
@endcode
You can then add it to resource manager instance like this:
You can then add it to resource manager instance like this. Note that the
manager automatically deletes the all loaders on destruction before unloading
all resources. It allows you to use resources in the loader itself without
having to delete the loader explicitly to ensure proper resource unloading. In
the following code, however, the loader destroys itself (and removes itself
from the manager) before the manager is destroyed.
@code
MyResourceManager manager;
MeshResourceLoader loader;

24
src/ResourceManager.h

@ -125,6 +125,8 @@ template<class T> class ResourceManagerData {
AbstractResourceLoader<T>* loader() { return _loader; }
const AbstractResourceLoader<T>* loader() const { return _loader; }
void freeLoader();
void setLoader(AbstractResourceLoader<T>* loader);
protected:
@ -367,6 +369,8 @@ template<class... Types> class ResourceManager: private Implementation::Resource
* @return Pointer to self (for method chaining)
*
* See AbstractResourceLoader documentation for more information.
* @attention The loader is deleted on destruction before unloading
* all resources.
*/
template<class T> ResourceManager<Types...>* setLoader(AbstractResourceLoader<T>* loader) {
this->Implementation::ResourceManagerData<T>::setLoader(loader);
@ -380,6 +384,12 @@ template<class... Types> class ResourceManager: private Implementation::Resource
}
template<class...> void freeInternal() const {}
template<class FirstType, class ...NextTypes> void freeLoaders() {
Implementation::ResourceManagerData<FirstType>::freeLoader();
freeLoaders<NextTypes...>();
}
template<class...> void freeLoaders() const {}
static ResourceManager<Types...>*& internalInstance();
};
@ -393,12 +403,8 @@ template<class ...Types> ResourceManager<Types...>*& ResourceManager<Types...>::
namespace Implementation {
template<class T> ResourceManagerData<T>::~ResourceManagerData() {
/* Loaders are already deleted via freeLoaders() from ResourceManager */
delete _fallback;
if(_loader) {
_loader->manager = nullptr;
delete _loader;
}
}
template<class T> std::size_t ResourceManagerData<T>::referenceCount(const ResourceKey key) const {
@ -499,6 +505,13 @@ template<class T> void ResourceManagerData<T>::setLoader(AbstractResourceLoader<
if((_loader = loader)) _loader->manager = this;
}
template<class T> void ResourceManagerData<T>::freeLoader() {
if(!_loader) return;
_loader->manager = nullptr;
delete _loader;
}
template<class T> void ResourceManagerData<T>::decrementReferenceCount(ResourceKey key) {
auto it = _data.find(key);
@ -546,6 +559,7 @@ template<class ...Types> ResourceManager<Types...>::ResourceManager() {
}
template<class ...Types> ResourceManager<Types...>::~ResourceManager() {
freeLoaders<Types...>();
CORRADE_INTERNAL_ASSERT(internalInstance() == this);
internalInstance() = nullptr;
}

54
src/Test/ResourceManagerTest.cpp

@ -229,6 +229,7 @@ void ResourceManagerTest::manualPolicy() {
void ResourceManagerTest::loader() {
class IntResourceLoader: public AbstractResourceLoader<Int> {
public:
IntResourceLoader(): resource(ResourceManager::instance()->get<Data>("data")) {}
void load() {
set("hello", new Int(773), ResourceDataState::Final, ResourcePolicy::Resident);
@ -242,32 +243,45 @@ void ResourceManagerTest::loader() {
if(key == ResourceKey("hello")) return "hello";
return "";
}
/* To verify that the loader is destroyed before unloading
_all types of_ resources */
Resource<Data> resource;
};
auto rm = new ResourceManager;
auto loader = new IntResourceLoader;
rm->setLoader(loader);
Resource<Data> data = rm->get<Data>("data");
Resource<Int> hello = rm->get<Int>("hello");
Resource<Int> world = rm->get<Int>("world");
CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
CORRADE_COMPARE(hello.state(), ResourceState::Loading);
CORRADE_COMPARE(world.state(), ResourceState::Loading);
CORRADE_COMPARE(loader->requestedCount(), 2);
CORRADE_COMPARE(loader->loadedCount(), 0);
CORRADE_COMPARE(loader->notFoundCount(), 0);
CORRADE_COMPARE(loader->name(ResourceKey("hello")), "hello");
loader->load();
CORRADE_COMPARE(hello.state(), ResourceState::Final);
CORRADE_COMPARE(*hello, 773);
CORRADE_COMPARE(world.state(), ResourceState::NotFound);
CORRADE_COMPARE(loader->requestedCount(), 2);
CORRADE_COMPARE(loader->loadedCount(), 1);
CORRADE_COMPARE(loader->notFoundCount(), 1);
{
Resource<Data> data = rm->get<Data>("data");
Resource<Int> hello = rm->get<Int>("hello");
Resource<Int> world = rm->get<Int>("world");
CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
CORRADE_COMPARE(hello.state(), ResourceState::Loading);
CORRADE_COMPARE(world.state(), ResourceState::Loading);
CORRADE_COMPARE(loader->requestedCount(), 2);
CORRADE_COMPARE(loader->loadedCount(), 0);
CORRADE_COMPARE(loader->notFoundCount(), 0);
CORRADE_COMPARE(loader->name(ResourceKey("hello")), "hello");
loader->load();
CORRADE_COMPARE(hello.state(), ResourceState::Final);
CORRADE_COMPARE(*hello, 773);
CORRADE_COMPARE(world.state(), ResourceState::NotFound);
CORRADE_COMPARE(loader->requestedCount(), 2);
CORRADE_COMPARE(loader->loadedCount(), 1);
CORRADE_COMPARE(loader->notFoundCount(), 1);
/* Verify that the loader is deleted at proper time */
rm->set("data", new Data);
CORRADE_COMPARE(Data::count, 1);
}
delete rm;
CORRADE_COMPARE(Data::count, 0);
}
}}

Loading…
Cancel
Save