Sign in to follow this  

Resource manager question

This topic is 3490 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I normally do things the inefficient way and break things up, but I'm interested in doing one of them resource factory approaches on a resource manager, to handle 2d textures, 3d models, and audio - now my questions is, does anyone have a good template shell, of one would look like, the coding part isn't a problem, but I don't want to blindly just hope I can correctly put it together. One of the things I want to be able to do is just, be able to access all my resources regardless of type, and just OnLostDevice & OnResetDevice, which I can do with a data structure, list/vector, or whatever it may be -- I just need to know of a general template on how it may look. /shrug Thanks. Hopefully, this makes sense - I'm posting on 2 hours of sleep.

Share this post


Link to post
Share on other sites
I'm in the middle of designing one right now, but its far from finished. I too, would like to look at any templates people post so that I may learn about them, and correct my design if need be.

EDIT: my manager works like this:

1. My resource manager class has several functions, of which are: add(ResourceObj *), remove (ResourceObj *), onDeviceLost(), and onDeviceRestored();
2. This class uses a singleton pattern.
3. I have a ResourceObj class. It is abstract but it has a constructor and destructor and two other functions: invalidate() and restore();
4. The constructor of this class adds itself to the resource manager upon creation: resourceManager::getInstance()->add(this);
5. The destructor removes itself from the resource manager much like the constructor.

Here is some code:

class ResourceManager
{
vector<ResourceObj *> objList;
public:
ResourceManager *getInstance(); //Singleton Pattern
bool add(ResourceObj *);
bool remove(ResourceObj *);
void onDeviceList();
void onDeviceRestored();
};






class ResourceObj
{
public:
ResourceObj();
virtual ~ResourceObj();

void invalidate() = 0;
void restore() = 0;
};





Implementation:

bool ResourceManager::add(ResourceObj *obj)
{
// Add this object to the list
objList.push_back(obj);
}

bool ResourceManager::remove(ResourceObj *obj)
{
// Remove object from the list
objList.erase(obj);
}

bool ResourceManager::onDeviceLost()
{
// Invalidate all objects
for (int i = 0; i < objList.size(); i++)
objList[i]->invalidate();
}

bool ResourceManager::onDeviceRestored()
{
// Restore all objects
for (int i = 0; i < objList.size(); i++)
objList[i]->restore();
}





ResourceObj::ResourceObj()
{
// Auto-add myself
ResourceManager::getInstance()->add(this);
}

ResourceObj::~ResourceObj()
{
ResourceManager::getInstance()->remove(this);
}




Once you have this basic pattern down, you can easily tell the manager that the device is lost, or regained. The manager will do the rest.

Once you get the basics down, you can easily derive from ResourceObj. This is not bound to any specific API because it does not implement the restore and invalidate functions, rather thats left to any specific derivations of this class.

I'll give a free lolly pop to anyone that guesses all the patterns used in this example :P.

Share this post


Link to post
Share on other sites
Why dont you take your best stab at the template yourself. Then show us and we'll critique it?

You'll want to use reference counting and some kind of smart pointer to your resources. This will allow for async resource creation.

My resource looks kind of like this

class Resource : public RefCounted
{
public:
virtual ResourceStatus InitialLoad( InitialLoadParams& params ) = 0;
virtual ResourceStatus ContinueLoad( ContinueLoadParams& params ) = 0;

const ResourceStatus GetStatus() const;
const InitialLoadParams& GetInitialParams() const;
int CompareResources( const Resource& other ) const;
};

Share this post


Link to post
Share on other sites
A resource pool is not a place for a singleton. What if you wanted to load resources for the next level as you were nearing the end of the current one? Why limit things to just one instance, eventually down the road you will realize how dumb it was but how nearly impossible to undo it is. There have been enough discussions by much smarter people then I on why the singleton is completely wrong so search the forums and enjoy the ride! If you need just one, make just one (specify this in the documentation). If you need a global, make it a global (or research far better ways of doing this, the OO way or whatever).

@OP: Just hit up google there are hundreds of examples of templated factories out there. It's nothing special for game development, its just a factory.

And like bzroom said, just write it up and post it, we'll look it over for you.

@bzroom: Why not use boost smart pointers? Or weak pointers. They're automatically reference counted and highly debugged already (instead of reinventing the wheel and having a more then likely bugger one)?

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike2343
@bzroom: Why not use boost smart pointers? Or weak pointers. They're automatically reference counted and highly debugged already (instead of reinventing the wheel and having a more then likely bugger one)?



Because reInventing the wheel is fuun!

I agree that if you just change your ResourceManager to ResourcePool and make it non singleton it would be a wise move.

I never thought of having resources pooled by zone or level. Usually I just assume that the entire game will reuse at least some content. But to drop a whole level of the entire spectrum of content would be sweet. I think i'm going to make a resource pool and add one to each of my "Scenes" so it can be dropped as a whole and preserve the other scenes resources.

To give you a bit more info about my system. I use template specialization to create a mapping between resource type and an enumeration. I use this enumeration to index a map of different resources.

Example:

//ResourceTypes.h - Client Defined

enum ResourceTypes
{
RESOURCE_TEXTURE = 0,
RESOURCE_MODEL,
//ADD ADDITIONAL RESOURCE TYPES HERE
RESOURCE_TYPE_COUNT
};

//specialization
template < typename T > struct ToResourceType;
template <> struct ToResourceType<Renderer::Texture>
{
static const ResourceType Enum = RESOURCE_TEXTURE;
static const char *SubFolder() { return "Textures\\"; }
};
template <> struct ToResourceType<Renderer::Model>
{
static const ResourceType Enum = RESOURCE_MODEL;
static const char *SubFolder() { return "Models\\"; }
};

//ghetto hacking
//called on resource manager intialization
static ResourceListBase *CreateResourceList( ResourceTypes type )
{
switch(type)
{
case RESOURCE_TEXTURE:
return new ResourceList<Renderer::Texture>;
case RESOURCE_MODEL:
return new ResourceList<Renderer::Model>;
}
};





//ResourceManager.h


#include "ResourceTypes.h"

class ResourceManager
{
public:
ResourceManager() { SetupLists(); }
~ResourceManager() { DestroyLists(); }

template<class T>
ResourceHandle<T> GetResource(const std::string &filename, ...)
{
ResourceList<T> *list = dynamic_cast<ResourceList<T>*>(m_Resources[ToResourceType<T>::Enum]);

//invalid list
if (!list)
return ResourceHandle<T>();

std::string path = m_Path + ToResourceType<T>::SubFolder() + filename;

CreateResourceParams createParams(path, ...);

return list->GetResource(createParams);
}

private:
void SetupLists()
{
for( int i = 0; i < RESOURCE_TYPE_COUNT; ++i)
m_Resources[i] = CreateResourceList((ResourceTypes)i);
}
void DestroyLists();

ResourceListBase *m_Resources[RESOURCE_TYPE_COUNT]
};






[Edited by - bzroom on May 26, 2008 11:04:55 PM]

Share this post


Link to post
Share on other sites
@bzroom: Not sure if you're coming back to this thread again but if you do. You could also pole other resource pools (older ones) for existing data instead of reloading it off the slow HDD again. I have it so one pool can do a full copy to another pool to save cycles and load times. Just an idea :)

Share this post


Link to post
Share on other sites
A little while ago I had some thoughts on this and wrote them down in my journal.

I admit, I never got around to implimenting them but there might be a few ideas worth considering; mostly I'm happy with the 'weak pointer' method of doing things, where your resource pool doesn't hold a strong pointer to the object but a weak one so that you automatically clean up the resource once the thing using them goes out of scope.

Of course, there are pros and cons to strong vs weak.

anyways, my ponderings start here with "Resource Manager Design Part 1".

I should probably revist this subject at some point...

edit:
Turns out this carries on into July as well, where we get into a bit more meat around the subject.. so yeah, don't just stop on the couple of entries in June if you do read it

Share this post


Link to post
Share on other sites

This topic is 3490 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this