/*! \file object_manager.h * this manager will ceep track of the objects in the world This is specially designed to: - Give an interface to the world data - separate the world data from the world build,update,draw process - recycle deleted objects: specific for Projectils since there is a lot of world entity creation/deletion (and this needs a lot of time) - control the garbage collector TO ADD SUPPORT FOR A CLASS do the following steps: 1. include the hader file : #include "class_id.h" 2. add the class to the type enum classID {}; in class_id.h 3. define a function void mCache( ClassName ) in class ObjectManager */ #ifndef _OBJECT_MANAGER_H #define _OBJECT_MANAGER_H #include "base_object.h" #include "class_id.h" template class tList; class GarbageCollector; /** * Creates a FastFactory to a Loadable FastFactory. */ //#define CREATE_FAST_FACTORY(CLASS_NAME, CLASS_ID) \ //tFastFactory* global_##CLASS_NAME##_FastFactory = new tFastFactory(#CLASS_NAME, CLASS_ID) //! A struct, that holds Lists of Objects of a certain type. template struct FastObjectMember { T* objectPointer; FastObjectMember* next; }; //! The FastFactory is a fast loadable object creator, and Dynamic List of dead object handler. /** * FastFactory is needed to glue all the tFastFactory's together. * Furthermore one can retrieve the corresponding tFastFactory over * tFastFactory* = FastFacroty::getFastFactory(ID); */ class FastFactory : public BaseObject { public: virtual ~FastFactory (); // functions to push and pop elements of this class BaseObject* resurect(ClassID classID); void kill(ClassID classID, BaseObject* object); // retrival functions for fast Ineraction //FastFactory* getFastFactory(ClassID classID); /** @returns the first FastFactory */ static FastFactory* getFirst() { return FastFactory::first; }; protected: /** sets the Next factory in the list @param nextFactory the next factory */ inline void setNext( FastFactory* nextFastFactory) { this->next = nextFastFactory; }; /** @returns the next FastFactory */ FastFactory* getNext() const { return this->next; }; virtual BaseObject* fabricate(ClassID classID) = NULL; private: FastFactory (ClassID classID, const char* fastFactoryName = NULL); static void registerFastFactory(FastFactory* fastFactory); static FastFactory* searchFastFactory(ClassID classID, const char* fastFactoryName = NULL); protected: ClassID storedClassID; //!< The classID of the specified class. unsigned int storedDeadObjects; //!< How many dead objects are stored in this class private: static FastFactory* first; //!< A pointer to the first FastFactory. FastFactory* next; //!< pointer to the next FastFactory. }; /** * a FastFactory that is able to load any kind of Object from a ClassID * (this is a Functor) */ template class tFastFactory : public FastFactory { public: static FastFactory* getFastFactory(ClassID classID, const char* fastFactoryName = NULL); void prepare(unsigned int count); T* resurect(); void kill(T* object); private: tFastFactory(ClassID classID, const char* fastFactoryName); T* fabricate(); private: FastObjectMember* deadList; //!< A List of all stored dead Objects of this class. FastObjectMember* unusedContainers; //!< This is a List of unused containers, that will be reused by kill. }; /** * construnts a FastFactory with * @param fastFactoryName the name of the FastFactory * @param fastFactory the ID of the class */ template tFastFactory::tFastFactory(ClassID classID, const char* fastFactoryName) : FastFactory(classID, fastFactoryName) { PRINTF(5)("Class: %s loadable as a FastFactory\n", this->getName()); this->deadList = NULL; this->unusedContainers = NULL; } template FastFactory* tFastFactory::getFastFactory(ClassID classID, const char* fastFactoryName) { tFastFactory* tmpFac = NULL; if (FastFactory::getFirst() != NULL) tmpFac = FastFactory::getFirst()->searchFastFactory(classID, fastFactoryName); if (tmpFac != NULL) return tmpFac; else return new tFastFactory; } template T* tFastFactory::fabricate() { FastObjectMember* tmpFirstDead = this->deadList; tmpFirstDead->objectPointer = new T(); tmpFirstDead->next = this->deadList; ++this->storedDeadObjects; this->deadList = tmpFirstDead; return this->deadList; } template void tFastFactory::prepare(unsigned int count) { if (this->storedDeadObjects + this->storedLivingObjects >= count) { PRINTF(3)("not creating new Objects for class %s, because the requested count already exists\n", this->getClassName()); } for (int i = this->storedDeadObjects + this->storedLivingObjects; i < count; i++) { this->fabricate(); } } template T* tFastFactory::resurect() { if (unlikely(this->deadList == NULL)) { PRINTF(2)("The deadList of Class %s is empty, this may be either because it has not been filled yet, or the cache is to small.\n" \ "Fabricating a new %s", this->getName(), this->getName()); return this->fabricate(); } else { FastObjectMember* tmpC = deadList; this->deadList = this->deadList->next; tmpC->next = this->unusedContainers; this->unusedContainers->tmpC; return tmpC; } } template void tFastFactory::kill(T* object) { FastObjectMember* tmpC; if (unlikely(this->unusedContainers == NULL)) { tmpC = new FastObjectMember; } else { tmpC = this->unusedContainers; this->unusedContainers = this->unusedContainers->next; } tmpC->next = this->deadList; tmpC->objectPointer = object; } //////////////////// // OBJECT MANAGER // //////////////////// //! the object manager itself class ObjectManager : public BaseObject { public: virtual ~ObjectManager(); /** @returns a Pointer to the only object of this Class */ inline static ObjectManager* getInstance() { if (!singletonRef) singletonRef = new ObjectManager(); return singletonRef; }; void registerClass(ClassID classID); BaseObject* resurect(); void kill(BaseObject* object); void debug() const; private: ObjectManager(); private: static ObjectManager* singletonRef; //!< The singleton reference to the only reference of this class }; #endif /* _OBJECT_MANAGER_H */