Haven't been active much, programming wise lately, so I decided I'd start at another engine-writing attempt.
After spending most of the last two days pulling my hair out, I think I finally came up with a usable resource manager.
The concept I was going for, was to have only one resource manager (as a singleton) to track Resource objects, which would be the base class for resources. For memory management, I decided to store the resources as reference counting pointers. The resource manager wraps std::map<std::string, CountedPtr<Resource> > for storage and tracking.
I dunno if anything I came up with was necessarily the best way of going about things. I haven't really bothered to write "full" resource manager before. Which is why I'm posting it for you all to comment on . (I won't bother posting headers). The code is also probably full of bugs and other issues - I haven't gotten around to testing yet. Not enough of the other parts of the engine are completed yet.
Resource.cpp:
Code:
#include "pch.h"
#include "Resource.h"
namespace Sakti{
Resource::Resource(string name, string type){
_name = name;
_type = type;
_id = rand(); //TODO: fix
load();
}
Resource::~Resource(){
unload();
}
string Resource::getName(){
return _name;
}
string Resource::getType(){
return _type;
}
void Resource::load(){
loadImp();
}
void Resource::unload(){
unloadImp();
}
}
ResourceManager.cpp:
Code:
#include "pch.h"
#include "ResourceManager.h"
namespace Sakti{
ResourceManager::ResourceManager(){
_initialised = false;
}
ResourceManager::~ResourceManager(){
for(_resMapItr = _resMap.begin(); _resMapItr != _resMap.end(); _resMapItr++){
removeResource(((*_resMapItr).second)->getName());
}
}
ResourceManager& ResourceManager::get(){
return *singleton;
}
ResourceManager* ResourceManager::getPtr(){
return singleton;
}
void ResourceManager::addResource(CountedPtr<Resource> res){
if(_initialised){
if(getResource(res->getName()).get() == NULL){
_resMap.insert(std::pair<string, CountedPtr<Resource> >(res->getName(), res));
}
else{
Utility::logMessage("Error adding resource: resource already exists.");
}
}
else{
MessageManager::get().sendMessage("RECOVERABLE_ERROR");
Utility::logMessage("Error adding resource: resource manager not initialised.");
}
}
void ResourceManager::removeResource(string name){
if(_initialised){
_resMapItr = _resMap.find(name);
if(_resMapItr != _resMap.end()){
_resMap.erase(_resMapItr);
}
else{
Utility::logMessage("Error removing resource: resource not found.");
}
}
else{
MessageManager::get().sendMessage("RECOVERABLE_ERROR");
Utility::logMessage("Error adding resource: not initialised.");
}
}
CountedPtr<Resource> ResourceManager::getResource(string name){
_resMapItr = _resMap.find(name);
if(_resMapItr != _resMap.end()){
return (*_resMapItr).second;
}
else{
return CountedPtr<Resource>();
}
}
void ResourceManager::init(){
if(!_initialised){
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(Platform::getApplicationPath()+"Media/", "FileSystem", "Default", true);
Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Default");
}
_initialised = true;
}
}
CountedPtr.h:
Code:
#ifndef _COUNTED_PTR_H
#define _COUNTED_PTR_H
#include "Sakti.h"
namespace Sakti{
class RefCounter{
public:
RefCounter(){
_count = 0;
}
size_t add(){
_count++;
return _count;
}
size_t remove(){
_count--;
return _count;
}
protected:
size_t _count;
};
template<class T>
class SAPI CountedPtr{
public:
explicit CountedPtr(T* ptr){
_ptr = ptr;
_counter = new RefCounter();
_counter->add();
}
CountedPtr(const CountedPtr& ctdPtr){
_ptr = ctdPtr._ptr;
_counter = ctdPtr._counter;
_counter->add();
}
CountedPtr(){
_ptr = NULL;
}
~CountedPtr(){
if(_counter->remove() == 0){
delete _ptr;
delete _counter;
}
}
size_t getCount(){
return _counter->_count;
}
T* get(){
return _ptr;
}
CountedPtr& operator=(const CountedPtr& ctdPtr){
return *this;
}
bool operator==(const CountedPtr& ctdPtr){
return _ptr == ctdPtr._ptr;
}
bool operator !=(const CountedPtr& ctdPtr){
return _ptr != ctdPtr._ptr;
}
T& operator*(){
return *_ptr;
}
T* operator->(){
return _ptr;
}
protected:
T* _ptr;
RefCounter* _counter;
};
}
#endif