Browse Source

Class AbstractResourceLoader.

Base for (a)synchronous resource loading automatically trigerred from
ResourceManager.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
2fc010263d
  1. 137
      src/AbstractResourceLoader.h
  2. 1
      src/CMakeLists.txt
  3. 49
      src/ResourceManager.h
  4. 34
      src/Test/ResourceManagerTest.cpp
  5. 1
      src/Test/ResourceManagerTest.h

137
src/AbstractResourceLoader.h

@ -0,0 +1,137 @@
#ifndef Magnum_AbstractResourceLoader_h
#define Magnum_AbstractResourceLoader_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::AbstractResourceLoader
*/
#include "Magnum.h"
#include <string>
#include "ResourceManager.h"
namespace Magnum {
/**
@brief Base for resource loaders
Provides asynchronous resource loading for ResourceManager.
*/
template<class T> class AbstractResourceLoader {
friend class Implementation::ResourceManagerData<T>;
public:
inline AbstractResourceLoader(): manager(nullptr), _requestedCount(0), _loadedCount(0), _notFoundCount(0) {}
inline virtual ~AbstractResourceLoader() {
if(manager) manager->_loader = nullptr;
}
/**
* @brief Count of requested resources
*
* Count of resources requested by calling load().
*/
inline std::size_t requestedCount() const { return _requestedCount; }
/**
* @brief Count of not found resources
*
* Count of resources requested by calling load(), but not found by
* the loader.
*/
inline std::size_t notFountCount() const { return _notFoundCount; }
/**
* @brief Count of loaded resources
*
* Count of resources requested by calling load(), but not found by
* the loader.
*/
inline std::size_t loadedCount() const { return _loadedCount; }
/**
* @brief %Resource name corresponding to given key
*
* If no such resource exists or the resource name is not available,
* returns empty string. Default implementation returns empty string.
*/
virtual std::string name(ResourceKey key) const;
/**
* @brief Request resource to be loaded
*
* If the resource isn't yet loaded or loading, state of the resource
* is set to @ref Resource::ResourceState "ResourceState::Loading" and count of
* requested features is incremented.
*
* The resource might be loaded asynchronously and added to
* ResourceManager when loading is done.
* @see ResourceManager::state(), requestedCount(), notFountCount(),
* loadedCount()
*/
virtual void load(ResourceKey key) = 0;
protected:
/**
* @brief Set loaded resource to resource manager
*
* Also increments count of loaded resources. Parameter @p state
* must be either @ref ResourceManager::ResourceDataState "ResourceDataState::Mutable"
* or @ref ResourceManager::ResourceDataState "ResourceDataState::Final". See
* ResourceManager::set() for more information.
* @see loadedCount()
*/
inline void set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy) {
CORRADE_ASSERT(state == ResourceDataState::Mutable || state == ResourceDataState::Final,
"AbstractResourceLoader::set(): state must be either Mutable or Final", );
++_loadedCount;
manager->set(key, data, state, policy);
}
/**
* @brief Mark resource as not found
*
* Also increments count of not found resources. See
* ResourceManager::setNotFound() for more information.
* @see notFountCount()
*/
inline void setNotFound(ResourceKey key) {
++_notFoundCount;
/** @todo What policy for notfound resources? */
manager->set(key, nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident);
}
private:
Implementation::ResourceManagerData<T>* manager;
std::size_t _requestedCount;
std::size_t _loadedCount;
std::size_t _notFoundCount;
};
template<class T> inline std::string AbstractResourceLoader<T>::name(ResourceKey) const { return {}; }
template<class T> inline void AbstractResourceLoader<T>::load(ResourceKey key) {
++_requestedCount;
/** @todo What policy for loading resources? */
manager->set(key, nullptr, ResourceDataState::Loading, ResourcePolicy::Resident);
}
}
#endif

1
src/CMakeLists.txt

@ -51,6 +51,7 @@ endif()
set(Magnum_HEADERS
AbstractImage.h
AbstractResourceLoader.h
AbstractShaderProgram.h
AbstractTexture.h
Buffer.h

49
src/ResourceManager.h

@ -78,6 +78,8 @@ enum class ResourcePolicy: std::uint8_t {
ReferenceCounted
};
template<class> class AbstractResourceLoader;
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
struct ResourceKeyHash {
@ -88,6 +90,7 @@ namespace Implementation {
template<class T> class ResourceManagerData {
template<class, class> friend class Resource;
friend class AbstractResourceLoader<T>;
ResourceManagerData(const ResourceManagerData<T>&) = delete;
ResourceManagerData(ResourceManagerData<T>&&) = delete;
@ -97,6 +100,11 @@ namespace Implementation {
public:
inline virtual ~ResourceManagerData() {
delete _fallback;
if(_loader) {
_loader->manager = nullptr;
delete _loader;
}
}
inline std::size_t lastChange() const { return _lastChange; }
@ -133,6 +141,10 @@ namespace Implementation {
}
template<class U> inline Resource<T, U> get(ResourceKey key) {
/* Ask loader for the data, if they aren't there yet */
if(_loader && _data.find(key) == _data.end())
_loader->load(key);
return Resource<T, U>(this, key);
}
@ -188,8 +200,20 @@ namespace Implementation {
}
}
inline AbstractResourceLoader<T>* loader() { return _loader; }
inline const AbstractResourceLoader<T>* loader() const { return _loader; }
inline void setLoader(AbstractResourceLoader<T>* loader) {
/* Delete previous loader */
delete _loader;
/* Add new loader */
_loader = loader;
if(_loader) _loader->manager = this;
}
protected:
inline ResourceManagerData(): _fallback(nullptr), _lastChange(0) {}
inline ResourceManagerData(): _fallback(nullptr), _loader(nullptr), _lastChange(0) {}
private:
struct Data {
@ -233,6 +257,7 @@ namespace Implementation {
std::unordered_map<ResourceKey, Data, ResourceKeyHash> _data;
T* _fallback;
AbstractResourceLoader<T>* _loader;
std::size_t _lastChange;
};
}
@ -422,6 +447,26 @@ template<class... Types> class ResourceManager: private Implementation::Resource
freeInternal(std::common_type<Types>()...);
}
/** @brief Loader for given type of resources */
template<class T> inline AbstractResourceLoader<T>* loader() {
return this->Implementation::ResourceManagerData<T>::loader();
}
/** @overload */
template<class T> inline const AbstractResourceLoader<T>* loader() const {
return this->Implementation::ResourceManagerData<T>::loader();
}
/**
* @brief Set loader for given type of resources
*
* The loader will affect only loading of resources requested after
* that.
*/
template<class T> inline void setLoader(AbstractResourceLoader<T>* loader) {
return this->Implementation::ResourceManagerData<T>::setLoader(loader);
}
private:
template<class FirstType, class ...NextTypes> inline void freeInternal(std::common_type<FirstType>, std::common_type<NextTypes>... t) {
free<FirstType>();
@ -441,5 +486,7 @@ template<class ...Types> ResourceManager<Types...>*& ResourceManager<Types...>::
}
/* Make the definition complete */
#include "AbstractResourceLoader.h"
#endif

34
src/Test/ResourceManagerTest.cpp

@ -17,6 +17,7 @@
#include <sstream>
#include "AbstractResourceLoader.h"
#include "ResourceManager.h"
using namespace std;
@ -36,6 +37,18 @@ class Data {
typedef Magnum::ResourceManager<int32_t, Data> ResourceManager;
class IntResourceLoader: public AbstractResourceLoader<std::int32_t> {
public:
void load(ResourceKey key) override {
AbstractResourceLoader::load(key);
}
void load() {
set("hello", new std::int32_t(773), ResourceDataState::Final, ResourcePolicy::Resident);
setNotFound("world");
}
};
size_t Data::count = 0;
ResourceManagerTest::ResourceManagerTest() {
@ -45,7 +58,8 @@ ResourceManagerTest::ResourceManagerTest() {
&ResourceManagerTest::basic,
&ResourceManagerTest::residentPolicy,
&ResourceManagerTest::referenceCountedPolicy,
&ResourceManagerTest::manualPolicy);
&ResourceManagerTest::manualPolicy,
&ResourceManagerTest::loader);
}
void ResourceManagerTest::state() {
@ -205,4 +219,22 @@ void ResourceManagerTest::manualPolicy() {
CORRADE_COMPARE(Data::count, 1);
}
void ResourceManagerTest::loader() {
ResourceManager rm;
IntResourceLoader loader;
rm.setLoader(&loader);
Resource<Data> data = rm.get<Data>("data");
Resource<std::int32_t> hello = rm.get<std::int32_t>("hello");
Resource<std::int32_t> world = rm.get<std::int32_t>("world");
CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
CORRADE_COMPARE(hello.state(), ResourceState::Loading);
CORRADE_COMPARE(world.state(), ResourceState::Loading);
loader.load();
CORRADE_COMPARE(hello.state(), ResourceState::Final);
CORRADE_COMPARE(*hello, 773);
CORRADE_COMPARE(world.state(), ResourceState::NotFound);
}
}}

1
src/Test/ResourceManagerTest.h

@ -30,6 +30,7 @@ class ResourceManagerTest: public Corrade::TestSuite::Tester<ResourceManagerTest
void residentPolicy();
void referenceCountedPolicy();
void manualPolicy();
void loader();
};
}}

Loading…
Cancel
Save