Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a resource manager that loads and returns resources. Currently I just return shared_ptrs for the resources I create, but I'm thinking about going over to using something like simple handles, whereby you get an ID you use to access the resource. The reasons are more explicit ownership and also less overhead rather than using smart_ptrs.

Are resource handles the most efficient way to access resources, should I stick with shared_ptrs or are there other alternatives?

The reason I am asking is that I was reading this article which made me wonder if I should implement something like that instead.

Thanks

share|improve this question
add comment

2 Answers

std::shared_ptr is expensive, and resources do not need shared ownership. You should use std::unique_ptr.

Create a ResourceManager class.

class ResourceManager
{
    private:
        std::unordered_map<std::string, std::unique_ptr<Texture>> textures;
        std::unordered_map<std::string, std::unique_ptr<Sound>> sounds;

    public:
        Texture& getTexture(const std::string& mId) { return *textures[mId]; }
        Sound& getSound(const std::string& mId) { return *sounds[mId]; }
 }

...

struct Game
{
    ResourceManager& resourceManager;
    Game(ResourceManager& mResourceManager) : resourceManager(mResourceManager) { }
    ...
}

...

int main()
{
    ResourceManager resourceManager;
    // load stuff in the resource manager here

    Game game{resourceManager};
    game.start();
}

The ResourceManager class can be extended with templates and more useful methods easily. You can check my full implementation ħere.

share|improve this answer
    
resources do not need shared ownership - Could you please elaborate on this statement? –  Cypher Jul 18 '13 at 17:21
    
@Cypher even if many game objects use the same resource, they have no need of "owning" it. They can just use a non-owning pointer or a reference, while the ResourceManager takes care of ownership. –  Vittorio Romeo Jul 18 '13 at 18:47
add comment

I disagree with Vittorio about not needing shared ownership of resources and, while I dislike the implementation of shared_ptr, it can be made to work just fine.

You want shared ownership because, of course, multiple game objects might be using the same resource. More importantly, if you have multiple levels and want to minimum level loading, you need some way to compute the union and intersection of resources needed by both.

One way to do this, which does require something more than just a shared_ptr, is to allow "loading" a level without resources and letting it take shared ownership of resources it needs. Then unload the old level, removing its ownership. Then, for any resource that still has ownership active but isn't loaded, load the resource.

For a resource A needed by levels 1 and 2, the reference count goes something like:

load level 1
ref=1
load A
load level 2
ref=2
unload level 1
ref=1

For a resource B used by only level 1, it goes like:

load level 1
ref=1
load B
load level 2
ref=1
unload level 1
ref=0 (removed)

And a resource C used by only level 2, it goes like:

load level 1
ref=0 (implicit, as no resource C exists)
load level 2
ref=1
unload level 1
load C

One method might be to have a layer of indirection. You store shared_ptr to a ResourceHolder. These holders are also in a list of some kind. When loading a level, you create and hold on to these ResourceHolder objects. They contain a unique_ptr to the actual resource (initially nullptr) and the path or other information needed to eventually load the item.

After loading the new level and unloading the old, you can then iterate through the list of live ResourceHolder objects, find any that have a nullptr handle to the actual resource, and then load it. When the shared_ptr to a ResourceHolder hits a ref count of 0 and unloads it, it also naturally frees the resource, and you should ensure that it removes itself from the list of live resources.

You can do much better than shared_ptr but it's a perfectly fine place to start to get up and running. Optimize it into something better later on once you have a working game.

share|improve this answer
    
What are the benefits of shared resource ownership? Even if many objects require the same resource, they can simply store a reference or non-owning pointer to it. –  Vittorio Romeo Jul 18 '13 at 18:48
1  
I explained it in this post with reference count sequence examples. If you don't have shared ownership, you don't know when to unload or reload resources when you transition levels, unless you make the levels themselves owners (which is crappy, because I don't want to have to manually tag which resources each levels needs; I just want to add objects to a level resource and have it all work automatically). –  Sean Middleditch Jul 18 '13 at 20:04
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.