Resource Manager Ideas

closed account (N36fSL3A)
The title says it all.

I'm just looking for an easy to use Resource Manager/Ideas, very simple and reusable.
closed account (3qX21hU5)
Here is a resource manager I have that holds all the heavyweight resources like textures. It was made for sfml but I am sure it wouldn't be to hard to convert to SDL (I assume that is what you are using).


ResourceHolder.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* 
* Resource Manager
*
* This is used to hold the heavyweight resources like sf::Textures, sf::Fonts and sf::SoundBuffers.
* It is generic so you can create one for each type of resource using the same class.
*/

#ifndef RESOURCE_HOLDER_H
#define RESOURCE_HOLDER_H

#include <map>
#include <memory>
#include <string>
#include <cassert>
#include <stdexcept>

template <typename Resource, typename Identifier>
class ResourceHolder
{
    public:
        void                load(Identifier id, const std::string& filename);

        template <typename Parameter>
        void                load (Identifier id, const std::string& filename, const Parameter& secondParam);

        Resource&           get(Identifier id);
        const Resource&     get(Identifier id) const;

        void                insertResource(Identifier id, std::unique_ptr<Resource> resource);

    private:
        std::map<Identifier, std::unique_ptr<Resource>> resourceMap;
};

#include "ResourceHolder.inl"

#endif // !RESOURCE_HOLDER_H 


ResourceHolder.inl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
template <typename Resource, typename Identifier>
void ResourceHolder<Resource, Identifier>::load(Identifier id, const std::string& filename)
{
    std::unique_ptr<Resource> resource(new Resource());
    if (!resource->loadFromFile(filename))
        throw std::runtime_error("ResourceHolder::load - Failed to load " + filename);

    auto inserted = resourceMap.insert(std::make_pair(id, std::move(resource)));
    assert(inserted.second);
}

template <typename Resource, typename Identifier>
template <typename Parameter>
void ResourceHolder<Resource, Identifier>::load(Identifier id, const std::string& filename,
                                                const Parameter& secondParam)
{
    std::unique_ptr<Resource> resource(new Resource());
    if (!resource->loadFromFile(filename, secondParam))
        throw std::runtime_error("ResourceHolder::load - Failed to load " + filename);

    auto inserted = resourceMap.insert(std::make_pair(id, std::move(resource)));
    assert(inserted.second);
}

template <typename Resource, typename Identifier>
Resource& ResourceHolder<Resource, Identifier>::get(Identifier id)
{
    auto foundResource = resourceMap.find(id);
    assert(foundResource != resourceMap.end());

    return *foundResource->second;
}

template <typename Resource, typename Identifier>
const Resource& ResourceHolder<Resource, Identifier>::get(Identifier id) const
{
    auto foundResource = resourceMap.find(id);
    assert(foundResource != resourceMap.end());

    return *foundResource->second;
}

template <typename Resource, typename Identifier>
void ResourceHolder<Resource, Identifier>::insertResource(Identifier id, std::unique_ptr<Resource> resource)
{
    auto inserted = resourceMap.insert(std::make_pair(id, std::move(resource)));
    assert(inserted.second);
}


Just missing a way to unload resources and that is about it (At least as far as I can tell).

The identifier can be anything you want I personally like using enums with it but that is just me.

Anyways maybe that will give ya some ideas. Generally a resource manager isn't that hard really it basically just provides a central place for you to keep your heavyweight resources and provides a way to manage them (IE load them when you need them and unload them when you don't).

Another one that I really liked that cire pointed out to me what how Thor handled it http://www.bromeon.ch/libraries/thor/v2.0/tutorial-resources.html
Last edited on
My resource managers are typically "load on demand" and use the filename as the the ID rather than having to track a separate ID value and pre-load items.

xerzi also came up with a neat 'descriptor' idea which allows you to specialize the loading process for various types without having to create an entirely separate manager class.

Example


Specialized descriptor:
1
2
3
4
5
6
7
8
9
10
11
12
13
    template <typename T>
    class ResourceDescriptor
    {
        static_assert( !std::is_same<T,T>::value, "Default resource descriptor used!" );
    };

    ///////////////////////////////////////////////////////////////
    class Texture2D;
    template <> class ResourceDescriptor<Texture2D>
    {
    public:
        std::shared_ptr<Texture2D>  load(std::string name) const;
    };


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    template <typename T>
    class ResourceManager
    {
    public:
        typedef std::shared_ptr<T>      res_t;

        static res_t get(const std::string& name)
        {
            static const ResourceDescriptor<T>      desc;

            auto i = resources.insert( std::make_pair( name, res_t(nullptr) ) );
            if(i.second)
            {
                i.first->second = desc.load(name);
            }

            return i.first->second;
        }

        static void clearAll()
        {
            resources.clear();
        }

    private:
        static std::map< std::string, std::shared_ptr<T> >      resources;
    };
    
    template<typename T>    std::map< std::string, std::shared_ptr<T> > SharedResourceManager<T>::resources;
closed account (N36fSL3A)
What exactly is nullptr?
closed account (3qX21hU5)
What exactly is nullptr?


nullptr is a pointer literal of type std::nullptr_t. Basically it is used to initialize your pointer to have no value. It was provided in C++11 to replace initializing pointers with a 0 (What NULL is) because that provided some problems.

The name alone should explain it all. It is "null" for a "pointer" ;p
closed account (N36fSL3A)
So what is wrong with setting a pointer to NULL?

I never had any problems with it.
closed account (3qX21hU5)
NULL isn't type safe for one.

The main problem with using NULL for a null pointer literal is that it can cause ambiguity, it is weakly typed and there edge case bugs that can arise from it. You most likely won't see any of them bugs in normal programming but that is no reason not to use nullptr

Not using it is like saying "I won't use bool's because 0's and 1's work just fine" ;p

Here is a article on it that can help explain it better http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/nullptr
Last edited on
Topic archived. No new replies allowed.