Original Post
Hi i''ve got some problems here.
I have been redesigning my memory/resource manager after reading about different tequniques people where using in thier engines (sliding slot and buddy systems)
now as far as I know my resource managers are working as they havn''t really been changed but they now include various memory manager classes as member variables, 1 for ram, 1 for hard disk and 1 for vram if nessessary.
I think my mem manager has the right ideas going there is just a few implementation details that are wrong, I am basing some of this off of superpigs enginuity articles and I admit I have hardly any knowledge of STL and so all that stuff may be a bit mixed up, slow or there may just be a better way for me to have done these functions.
I also havn''t done any pointer arithmetic for ages and so there''s parts of the code that don''t compile because of this.
I also think I may be using the smart pointer and memory managed object classes from the enginuity articles a bit wrong.
Anyway here is the source code for the memory manager so far (if anyone has difficulty reading it, just post telling me what parts you don''t understand):
template <class T>
class E_MemBlock : public E_MMObject
{
public:
T *m_StartLocation;
unsigned int m_BlockSize; //amount of memory the block has, e.g. 128k etc
void SetData(T *ptr, unsigned long size)
{
memcpy(m_StartLocation, ptr, size);
}
protected:
unsigned long Size(){return sizeof(*this);}
};
template <class T>
class E_MemoryManager
{
//=====================================================================
//variables
//=====================================================================
protected:
std::list<E_SmartPointer<E_MemBlock<T> > > m_FreeBlocks;
std::list<E_SmartPointer<E_MemBlock<T> > > m_UsedBlocks;
public:
//=====================================================================
//functions
//=====================================================================
//----------------------------------------------------------------------
//the function takes the data type being pointed to (char, int etc)
//memory is a ptr to the memory that should be managed, size is the
//total size of the memory.
//this function then creates a memory block from this data and then stores
//it in the free blocks list. it then splits the block into 2. it then
//recursively splits the 1st block until a block with the lowest
//memory size is created.
//the function returns false if this can''t be done and true on success
//----------------------------------------------------------------------
bool Create(T *memory, unsigned int size)
{
//create a free block with the parameters passed in
//this is used as the main memory for this manager
E_MemBlock<T> block;
block.m_BlockSize = size;
block.m_StartLocation = memory;
//store original block in the free list
m_FreeBlocks.insert(m_FreeBlocks.begin(), █);
//recursively split the block into smaller sizes
for(; block.m_BlockSize == size / 5;)
{
if(!SplitBlock(block))
break;
}
return true;
}
//----------------------------------------------------------------------
//This takes a ptr to a block to be split, the source block should
//return as half the size as it''s original self, the remainder of the
//source block is stored in destBlock.
//the function returns false if the block could not be split and true on
//success
//----------------------------------------------------------------------
bool SplitBlock(E_MemBlock<T> block)
{
//find half size of original block
unsigned int halfSize = block.m_BlockSize / 2;
//create new block with ptr at half way through originals memory and size
//as half the original
E_MemBlock<T> newBlock;
newBlock.m_BlockSize = halfSize;
newBlock.m_StartLocation = block.m_StartLocation + halfSize;
//set the original block to have half the size
block.m_BlockSize = halfSize;
//store the new block on the free list
m_FreeBlocks.insert(m_FreeBlocks.begin(), &newBlock);
return true;
}
//----------------------------------------------------------------------
//This function takes the size of the required block and trys to find 2 or
//more blocks free in contiguous memory that it can merge to create a
//block of the desired size, if it can''t NULL is returned
//----------------------------------------------------------------------
E_MemBlock<T> MergeBlock(unsigned int size)
{
//sort free blocks so that the memory is as linear as possible
m_FreeBlocks.sort();
//find 2 or more adjacent blocks that are linear in memory and that are
//large enough in total to create a block as large as size
std::list<E_SmartPointer<E_MemBlock<T> > >::iterator it;
//loop through the free list
for(it = m_FreeBlocks.begin(); it != m_FreeBlocks.end(); it++)
{
//store the start block
E_SmartPointer<E_MemBlock<T> > &startBlock = (*it);
//store the total size of the blocks
unsigned int totalSize = startBlock->m_BlockSize;
//store the number of blocks that are going to be merged
unsigned int numOfBlocks = 0;
bool linear = true;
//loop through all the blocks after the start block until we reach a block
//that is not contiguous in memory from the other ones
for(it++; linear == true; it++)
{
//get the next block
E_SmartPointer<E_MemBlock<T> > &nextBlock = (*it);
//check if memory is linear
if(startBlock->m_StartLocation + totalSize != nextBlock->m_StartLocation)
linear = false;
numOfBlocks += 1;
//update the total size of all the contiguous blocks
totalSize += nextBlock->m_BlockSize;
//merge the blocks if enough memory is found
if(totalSize >= size)
{
startBlock->m_BlockSize = totalSize;
//remove and delete all blocks that were merged
for(it = *startBlock+1; it < *startBlock + numOfBlocks;) // dont know what i need to do here
{
E_MemBlock<T> *block = (*it);
it++;
m_FreeBlocks.remove(block);
block = NULL;
}
//return the newley merged block
return startBlock;
}
}
}
return NULL;
}
//----------------------------------------------------------------------
//This function returns a free block that matches the size, if one can''t
//be found it trys merging blocks together and splitting larger blocks,
//if it still can''t find a block then it returns a block with size null
//, else it returns the block and puts it on the used list
//----------------------------------------------------------------------
E_MemBlock<T> GetFreeBlock(unsigned int size)
{
//search the list for a block that matches size
//if one is found return it
std::list<E_SmartPointer<E_MemBlock<T> > >::iterator it;
//loop through the free list
for(it = m_FreeBlocks.begin(); it != m_FreeBlocks.end(); it++)
{
E_SmartPointer<E_MemBlock<T> > █ = (*it);
if(block->m_BlockSize == size)
{
m_FreeBlocks.remove(block);
m_UsedBlocks.insert(m_UsedBlocks.begin(), block);
return *block;
}
}
//else
//try merging blocks
E_MemBlock<T> mergedBlock;
mergedBlock.m_BlockSize = 0;
mergedBlock = MergeBlock(size);
if(mergedBlock.m_BlockSize != 0)
{
m_FreeBlocks.remove(&mergedBlock);
m_UsedBlocks.insert(m_UsedBlocks.begin(), &mergedBlock);
return mergedBlock;
}
//else try spliting larger blocks
for(it = m_FreeBlocks.begin(); it != m_FreeBlocks.end(); it++)
{
E_SmartPointer<E_MemBlock<T> > █ = (*it);
if(block->m_BlockSize >= size)
{
do
{
SplitBlock(*block);
if(block->m_BlockSize == size)
{
//return the free block and put it on the used list
m_FreeBlocks.remove(block);
m_UsedBlocks.insert(m_UsedBlocks.begin(), block);
return *block;
}
}while(block->m_BlockSize >= size);
}
}
return mergedBlock; //wanted to return NULL so that memory wasn''t wasted
//now it looks like the caller will need to delete this
}
//----------------------------------------------------------------------
//this function releses it''s memory and is put on the free blocks list
//----------------------------------------------------------------------
bool ReleaseBlock(E_MemBlock<T> block)
{
//put the block on the free list
return true;
}
If anyone cares to go through the code and point out what''s wrong with it (everythng ;-) ) or give tips on better ways to do some of the code (like speeding it up or makeing it easier to read etc) I''d be greatful.
Cheers!