Hi Daniweb,
I've been programming a base class resource manager for a game I'm working on, and so read up on boost's shared_ptr and weak_ptr. I'm done with it and it works and I would really appreciate some feedback on my choice of implementation and design. Am I using the smart pointers in a correct way? Am I overcomplicating things? etc...
Here's the code:
#ifndef RESOURCE_MANAGER_HPP
#define RESOURCE_MANAGER_HPP
#include <map>
#include <string>
#include <iostream>
#include <stdexcept>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>
template<typename T>
class ResourceManager {
// Type definitions
protected:
typedef boost::shared_ptr<T> Resource; // Not to be used by users
public:
typedef boost::weak_ptr<T> ResourcePtr;
typedef std::map<std::string, Resource> ResourceMap;
public:
ResourceManager() {
resources.clear();
}
virtual ~ResourceManager() {
std::cout << "A ResourceManager is about to release " << AllocatedResources() << " resources" << std::endl; // Debug statement
};
ResourcePtr Request(const std::string& key) {
if (resources.find(key) == resources.end()) {
std::cerr << "Error: Requested resource with name " << key << " does not exist\n";
return ResourcePtr(); // "Empty" smart pointer, should throw exception instead in the future though
}
return ResourcePtr(resources[key]);
}
int AllocatedResources() {
return resources.size();
}
protected:
ResourceMap resources;
};
// Runtime exception
class ResourceLoadingException : public std::runtime_error {
ResourceLoadingException(const std::string& message) : std::runtime_error(message) {}
};
#endif
As you can see I am using the shared_ptr for the actual resource, but a weak_ptr as the return value for the Request member function to avoid cyclic references. I really don't expect cyclic references but I thought it might be a good idea to do anyways :) Note also that to use a requested resource, I have to turn the weak_ptr into a shared_ptr and use its dereference operator:
*myResourcePointer.lock()
. Also, derived classes (e.g. an ImageManager) need to implement their own Register/Load member function.