#ifndef ___MEM_MANAGER_H_INCLUDED___ #define ___MEM_MANAGER_H_INCLUDED___ #pragma warning(disable:4786) #include <vector> #include <queue> #include <set> #include "sync_simple.h" using namespace std; /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------- CLASS ---------------------------------------------------------- // A priority queue that allows pre-setting capacity of the container. template<class T> class mpriority_queue : public priority_queue<T, vector<T>, less<typename vector<T>::value_type> > { public: void reserve(size_type _N) { c.reserve(_N); }; size_type capacity() const { return c.capacity(); }; }; /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------- CLASS ---------------------------------------------------------- // A template class allowing re-using of the memory blocks. template<class T> class QueuedBlocks { private: QMutex m_qMutex; set< T* > m_quBlocks; vector< T* > m_allBlocks; public: QueuedBlocks(int nInitSize = 1): m_qMutex(), m_quBlocks(), m_allBlocks() { int i; int nSize = (nInitSize <= 0)?1:nInitSize; // allocate and push the blocks to the queue for (i = 0; i < nSize; i++) { T *t = new T(); if (t != NULL) { t->Clear(); m_quBlocks.insert( t ); m_allBlocks.push_back( t ); } } }; // get a free block from the queue, if one cannot be found // then NULL is returned T* GetFromQueue() { T* t = NULL; m_qMutex.Lock(); if (!m_quBlocks.empty()) { set<T*>::iterator itPos = m_quBlocks.begin(); t = *itPos; m_quBlocks.erase( t ); } m_qMutex.Unlock(); return t; }; // get a free block from the queue, if one cannot be found // then a new one is created T* Get() { T* t = GetFromQueue(); if (t == NULL) { t = new T(); if (t != NULL) { t->Clear(); m_qMutex.Lock(); m_allBlocks.push_back( t ); m_qMutex.Unlock(); } } return t; }; // Release the used block, place it // back to the queue. For performance reason, // we assume that the block was previously taken // from the queue. void Release(T* t) { if (t != NULL) { t->Clear(); m_qMutex.Lock(); m_quBlocks.insert( t ); m_qMutex.Unlock(); } }; // Return all the blocks ever allocated. vector<T*> *GetBlocks() { return &m_allBlocks; }; ~QueuedBlocks() { m_qMutex.Lock(); m_quBlocks.clear(); vector<T*>::iterator itPos = m_allBlocks.begin(); for (; itPos < m_allBlocks.end(); itPos++) { T* t = *itPos; t->Clear(); delete t; } m_allBlocks.clear(); m_qMutex.Unlock(); }; }; /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------- CLASS ---------------------------------------------------------- // A template class used for providing free blocks as well // as releasing unnecessary ones. Uses "QueuedBlocks" which // allows reusing of the blocks. template<class T> class StaticBlocks { private: static QueuedBlocks<T> *blocks; public: static void Init(int nSize = 1) { if (blocks == NULL) blocks = new QueuedBlocks<T>(nSize); }; static void Clear() { if (blocks != NULL) { delete blocks; blocks = NULL; } } static T *Get() { if (blocks == NULL) return NULL; return blocks->Get(); }; static void Release(T *b) { if (blocks != NULL) blocks->Release(b); }; }; #endif