You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

292 lines
11 KiB

#ifndef Magnum_AbstractResourceLoader_h
#define Magnum_AbstractResourceLoader_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifdef MAGNUM_BUILD_DEPRECATED
/** @file
* @brief Class @ref Magnum::AbstractResourceLoader
* @m_deprecated_since_latest The @ref Magnum::ResourceManager class is
* obsolete, as it only resulted in additional code verbosity,
* hard-to-track bugs due to less clear resource ownership, and general
* inefficiencies, while not actually solving any real-world problem.
*/
#endif
#include "Magnum/configure.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <string>
#include "Magnum/ResourceManager.h"
/* File deprecation warning printed in ResourceManager.h */
namespace Magnum {
/**
@brief Base for resource loaders
@m_deprecated_since_latest The @ref ResourceManager class is obsolete, as it
only resulted in additional code verbosity, hard-to-track bugs due to
less clear resource ownership, and general inefficiencies, while not
actually solving any real-world problem.
Provides (a)synchronous resource loading for @ref ResourceManager.
14 years ago
@section AbstractResourceLoader-usage Usage and subclassing
14 years ago
Usage is done by subclassing. Subclass instances can be added to
@ref ResourceManager using @ref ResourceManager::setLoader(). After adding the
loader, each call to @ref ResourceManager::get() will call @ref load()
implementation unless the resource is already loaded (or loading is in
progress). Note that resources requested before the loader was added are not
affected by the loader.
Subclassing is done by implementing at least @ref doLoad() function. The
loading can be done synchronously or asynchronously (i.e., in another thread).
The base implementation provides interface to @ref ResourceManager and manages
loading progress (which is then available through functions @ref requestedCount(),
@ref loadedCount() and @ref notFoundCount()). You shouldn't access the
@ref ResourceManager directly when loading the data.
In your @ref doLoad() implementation, after your resources are loaded, call
@ref set() to pass them to @ref ResourceManager or call @ref setNotFound() to
indicate that the resource was not found.
You can also implement @ref doName() to provide meaningful names for resource
keys.
14 years ago
Example implementation for synchronous mesh loader:
@snippet Magnum.cpp AbstractResourceLoader-implementation
14 years ago
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.
@snippet Magnum.cpp AbstractResourceLoader-use
*/
template<class T> class CORRADE_DEPRECATED("the ResourceManager class is obsolete") AbstractResourceLoader {
public:
explicit AbstractResourceLoader(): manager(nullptr), _requestedCount(0), _loadedCount(0), _notFoundCount(0) {}
virtual ~AbstractResourceLoader();
/**
* @brief Count of requested resources
*
* Count of resources requested by calling @ref load().
*/
std::size_t requestedCount() const { return _requestedCount; }
/**
* @brief Count of not found resources
*
* Count of resources requested by calling @ref load(), but not found
* by the loader.
*/
std::size_t notFoundCount() const { return _notFoundCount; }
/**
* @brief Count of loaded resources
*
* Count of resources requested by calling @ref load(), but not found
* by the loader.
*/
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.
*/
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
std::string name(ResourceKey key) const { return doName(key); }
CORRADE_IGNORE_DEPRECATED_POP
/**
* @brief Request resource to be loaded
*
* If the resource isn't yet loaded or loading, state of the resource
* is set to @ref ResourceState::Loading and count of requested
* features is incremented. Depending on implementation the resource
* might be loaded synchronously or asynchronously.
14 years ago
*
* @see @ref ResourceManager::state(), @ref requestedCount(),
* @ref notFoundCount(), @ref loadedCount()
*/
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
void load(ResourceKey key);
CORRADE_IGNORE_DEPRECATED_POP
protected:
/**
* @brief Set loaded resource to resource manager
*
* If @p data is @cpp nullptr @ce and @p state is
* @ref ResourceDataState::NotFound, increments count of not found
* resources. Otherwise, if @p data is not @cpp nullptr @ce, increments
* count of loaded resources. See @ref ResourceManager::set() for
* more information.
*
* Note that resource's state is automatically set to
* @ref ResourceDataState::Loading when it is requested from
* @ref ResourceManager and it's not loaded yet, so it's not needed to
* call this function. For marking a resource as not found you can also
* use the convenience @ref setNotFound() variant.
* @see @ref loadedCount()
*/
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
void set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy);
CORRADE_IGNORE_DEPRECATED_POP
/** @overload */
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
void set(ResourceKey key, Containers::Pointer<T> data, ResourceDataState state, ResourcePolicy policy) {
return set(key, data.release(), state, policy);
}
CORRADE_IGNORE_DEPRECATED_POP
/** @overload */
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
template<class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_same<typename std::decay<U>::type, std::nullptr_t>::value, int>::type = 0
#endif
> void set(ResourceKey key, U&& data, ResourceDataState state, ResourcePolicy policy) {
set(key, new typename std::decay<U>::type(std::forward<U>(data)), state, policy);
}
CORRADE_IGNORE_DEPRECATED_POP
/**
* @brief Set loaded resource to resource manager
*
* Same as above function with state set to @ref ResourceDataState::Final
* and policy to @ref ResourcePolicy::Resident.
*/
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
void set(ResourceKey key, T* data) {
set(key, data, ResourceDataState::Final, ResourcePolicy::Resident);
}
CORRADE_IGNORE_DEPRECATED_POP
/** @overload */
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
void set(ResourceKey key, Containers::Pointer<T> data) {
set(key, data.release());
}
CORRADE_IGNORE_DEPRECATED_POP
/** @overload */
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
template<class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_same<typename std::decay<U>::type, std::nullptr_t>::value, int>::type = 0
#endif
> void set(ResourceKey key, U&& data) {
set(key, new typename std::decay<U>::type(std::forward<U>(data)));
}
CORRADE_IGNORE_DEPRECATED_POP
/**
* @brief Mark resource as not found
*
* A convenience function calling @ref set() with @cpp nullptr @ce
* and @ref ResourceDataState::NotFound.
* @see @ref notFoundCount()
*/
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
void setNotFound(ResourceKey key) {
set(key, nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident);
}
CORRADE_IGNORE_DEPRECATED_POP
#ifndef DOXYGEN_GENERATING_OUTPUT
private:
#else
protected:
#endif
/**
* @brief Implementation for @ref name()
*
* Default implementation returns empty string.
*/
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
virtual std::string doName(ResourceKey key) const;
CORRADE_IGNORE_DEPRECATED_POP
/**
* @brief Implementation for @ref load()
*
* See class documentation for reimplementation guide.
*/
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC 4.8 warns here */
virtual void doLoad(ResourceKey key) = 0;
CORRADE_IGNORE_DEPRECATED_POP
private:
#ifndef DOXYGEN_GENERATING_OUTPUT /* https://bugzilla.gnome.org/show_bug.cgi?id=776986 */
friend Implementation::ResourceManagerData<T>;
#endif
Implementation::ResourceManagerData<T>* manager;
13 years ago
std::size_t _requestedCount,
_loadedCount,
_notFoundCount;
};
CORRADE_IGNORE_DEPRECATED_PUSH
template<class T> AbstractResourceLoader<T>::~AbstractResourceLoader() {
if(manager) manager->_loader = nullptr;
}
template<class T> std::string AbstractResourceLoader<T>::doName(ResourceKey) const { return {}; }
template<class T> void AbstractResourceLoader<T>::load(ResourceKey key) {
++_requestedCount;
manager->set(key, nullptr, ResourceDataState::Loading, ResourcePolicy::Resident);
doLoad(key);
}
template<class T> void AbstractResourceLoader<T>::set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy) {
if(data) ++_loadedCount;
if(!data && state == ResourceDataState::NotFound) ++_notFoundCount;
manager->set(key, data, state, policy);
}
CORRADE_IGNORE_DEPRECATED_POP
}
#else
#error the ResourceManager class is obsolete
#endif
#endif