Thread: Sorting out a resource manager

  1. #1
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,071

    Sorting out a resource manager

    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
    M.Eng Computer Engineering Candidate
    B.Sc Computer Science

    Robotics and graphics enthusiast.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I eventually went with a templated manager and it seems to be working just fine.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Resource manager
    By beene in forum Game Programming
    Replies: 3
    Last Post: 03-04-2008, 09:50 PM
  2. Resource manager tree
    By VirtualAce in forum Game Programming
    Replies: 23
    Last Post: 09-07-2007, 10:27 PM
  3. Is this a good resource manager?
    By VirtualAce in forum Game Programming
    Replies: 7
    Last Post: 07-13-2007, 11:24 PM
  4. Generic Resource Manager, 90% done! Boost enabled!
    By Shamino in forum C++ Programming
    Replies: 2
    Last Post: 02-20-2006, 07:37 PM
  5. Templated Generic Resource Manager, WIP..
    By Shamino in forum C++ Programming
    Replies: 13
    Last Post: 02-19-2006, 06:29 PM