söndag 21 december 2008

Boosted resource manager

This entry has been slightly delayed because I was yet again pissed of by how poorly webstuff works. This time it was the <'s and >'s in my code that gave me a headache. Thus I put off posting this for a few days until I got my rational mind back. The solution was actually quite simple, I just had to use sed.

Anyway time to get on topic. For some reason I felt compelled to add a resource manager to a project I'm working on. I already had one ready to be used, but I felt it was too simple. It didn't have any features other than keeping track of what resources had already been loaded so you avoid duplicates.

So I wanted to add a little to it. First of all I felt the need to use boost::shared_ptr since that is quite a bit safer than the raw pointers it was using. This was not entirely trivial since the resource manager manages more than one type of resource. I could not store different types of shared pointers in the same resource map. Therefore I turned to the boost::any type which can store anything. I must say it solved my problem quite nicely.

Secondly I felt it might be a good idea to add a Drop function so you can tell the resource manager to drop your resource if you don't want it to stay loaded when it's not used anymore.

Thirdly I wanted to add threading so you can load big/slow/web/complex resources and still be able to provide your user with program responsiveness or at least some animated eye candy. However, this part is not done yet, I am in the finishing stages of coding it but I thought I'd give it a whole new post because I don't want to clutter the simplicity of the threadless resource manager.

Well that's all I want to say about it for now. Enjoy the code!

#ifndef resource_manager_h
#define resource_manager_h

#include <map>
#include <string>
#include <typeinfo>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/any.hpp>

typedef std::map<std::string, boost::any> Resource_map;

/* Class: Resource_manager
* Managing resources.
* */
class Resource_manager
{
public:
/* Function: Load
* Loads a resource, or returns it if it has already been loaded.
*
* Parameters:
* filename - File to load
*
* Returns:
* Shared pointer to loaded resource.
* */
template <typename T> boost::shared_ptr<T> Load(std::string filename)
{
typedef boost::shared_ptr<T> TSP;
std::string resname = filename + "*" + typeid(T).name();
Resource_map::iterator i = resources.find(resname);

if(i != resources.end()) {
try
{
TSP tsp = boost::any_cast<TSP>(i->second);
return tsp;
}
catch(boost::bad_any_cast e)
{
}
}

TSP resource = TSP(new T);
if(!resource->Load(filename)) {
std::cout << "Resource failed to load: " << filename << std::endl;
resource.reset();
return resource;
}
resources[resname] = resource;
return resource;
}

/* Function: Drop
* Drops a resource from the manager.
* This will not affect any shared pointers that are still pointing to it.
*
* Parameters:
* r - Shared pointer to the resource to drop.
* */
template <typename T> void Drop(boost::shared_ptr<T> r)
{
typedef boost::shared_ptr<T> TSP;
for(Resource_map::iterator i = resources.begin(); i != resources.end(); ++i)
{
try
{
TSP tsp = boost::any_cast<TSP>(i->second);
if(tsp == r)
{
resources.erase(i);
return;
}
}
catch(boost::bad_any_cast e)
{
}
}
}
private:
Resource_map resources;
};

#endif

Inga kommentarer: