mercoledì 29 agosto 2007

MemoryManager.cpp

#include "MemoryManager.h"

namespace ManagedMemory
{
using namespace std;

MemoryManagerImpl::MemoryManagerImpl(void *p, size_t heapSize):
_heapSize(heapSize),
_heap(p)
{
_freeBlocks.push_front(MemBlock(_heap, _heapSize));
}

MemoryManagerImpl::~MemoryManagerImpl(void)
{
}

void * MemoryManagerImpl::alloc(size_t amount) throw(MemoryAllocationException)
{
for(list::iterator it = _freeBlocks.begin(); it != _freeBlocks.end(); it++)
{
if(it->_size >= amount)
{
void *memPointer = it->_pointer;
size_t memResidua = it->_size - amount;
_freeBlocks.erase(it);
_usedBlocks.push_back(MemBlock(memPointer, amount));
if(memResidua > 0)
_freeBlocks.push_back(
MemBlock(reinterpret_cast(
reinterpret_cast(memPointer)+amount),
memResidua));
return memPointer;
}
}
return 0;
}

void MemoryManagerImpl::free(void *p) throw(NotOwnedMemoryException, DeallocOnNotAllocatedMemory)
{
if(
( reinterpret_cast(p) <>(_heap)) ||
( reinterpret_cast(p) >= (reinterpret_cast(_heap) + _heapSize))
) throw NotOwnedMemoryException();

for(list::iterator it = _usedBlocks.begin(); it != _usedBlocks.end(); it++)
{
if(it->_pointer == p)
{
_freeBlocks.push_back(*it);
defrag();
_usedBlocks.erase(it);
return;
}
}
throw DeallocOnNotAllocatedMemory();
}

void MemoryManagerImpl::defrag()
{
if(_freeBlocks.size() < 2) return;
_freeBlocks.sort();
list::iterator it1 = _freeBlocks.begin();
list::iterator it2 = _freeBlocks.begin();
it2++;

while(it2 != _freeBlocks.end())
{
if(
(reinterpret_cast(it1->_pointer) +
it1->_size) == (reinterpret_cast(it2->_pointer)))
{
// Unisco e libero
_freeBlocks.push_back(MemBlock(it1->_pointer, it1->_size + it2->_size));
_freeBlocks.erase(it2);
_freeBlocks.erase(it1);

// Ricomincio
if(_freeBlocks.size() < 2) return;
_freeBlocks.sort();
it1 = _freeBlocks.begin();
it2 = _freeBlocks.begin();
it2++;
}
else
{
it1++;
it2++;
}
}
}
};

2 commenti:

Anonimo ha detto...

questa cosa è interessante... Sono un neofita di c++ ma a quanto ho capito questa funzione alloca della memoria e la riserva .. è possibile poi scrivere in questa memoria del codice asm? E allocare, se libero, sempre lo stesso offset?

Miki ha detto...

Il memory manager che propongo qui è un'implementazione molto semplice del concetto (appunto!) di gestore di memoria, compito tipicamente riservato al sistema operativo. Ho utilizzato un gestore di memoria di questo tipo (effettivamente era un sistema decisamente più sofisticato) su un sistema embedded. Dubito che possa essere utile nel mondo dei personal computer, se non per scopo didattico...