I3MUP1+-+Exercise+13+-+Dynamic+Memory+Allocation

=Exercise 13 - Fixed Size Buffer Pattern=

Exercise 1:
Vi dannede os et overblik over de klasserne i systemet ved først at lave et klassediagram som kan ses herunder:



Vi lavede herefter et overordnet sekvensdaigarm af de forløbet hvor en klasse anmoder om 100 bytes hukommelse af HeapManager, og hukommelsen bliver returneret til anmoderen.

Vi følte at efter disse to diagrammer var lavet havde vi fået et overblik over hvad hver klasse havde ansvar for.

Exercise 2 - Design and Implement MemPool
MemPool skal ikke bruge noget hukommelse i heapen, og derfor ville det ikke give mening at benytte new og delete.
 * Why do MemPool not use new and delete?**

Herunder ses headeren for MemPool. vi tilføjede tre private data members, da vi skal benytte nElements og size i diverse funktioner. Vi tilføjede også en BufferDescriptor array.

code format="cpp" //===================================== // CLASS : MemPool // DESCR. : Contols a chunk of raw memory that is logically divided into a number of buffers //===================================== class MemPool { public: MemPool(size_t nElements, size_t size); ~MemPool;

void* allocate; bool free(void*); bool anyFree; void* info; size_t getElementSize;

private: void* rawMem_; BufferDescriptor* bDescriptor_;

size_t nElements_; size_t size_; } code Herunder ses implementeringen af klassen MemPool:

code format="cpp" //============================================================= // METHOD : Explicit constructor // DESCR. : Inizialize variables and starts CruiseControllerThread //============================================================= MemPool::MemPool(size_t nElements, size_t size) : nElements_(nElements), size_(size) {   //Allocates a raw chunk of memory (large enough to hold nElements with size size) rawMem_ = malloc(nElements * size);

//Allocates an array of nElements BufferDescriptor-objects bDescriptor_ = (BufferDescriptor*)malloc(nElements);

//Makes i'th BufferDesciptor's ptr point to the address of the i'th element in the raw memory chunk. for(int i = 0; i < (int)nElements_; i++) {       if(i > 0) bDescriptor_[i].ptr_ = rawMem_ + (size * i); else bDescriptor_[i].ptr_ = rawMem_;

//Sets all BufferDescriptor isFree-attribute to true bDescriptor_[i].isFree_ = true; }

}

MemPool::~MemPool {   free(rawMem_); }

//============================================================= // METHOD : allocate // DESCR. : Returns an ptr to the first unused ptr //============================================================= void* MemPool::allocate {   // Checks if there is any free buffers if(anyFree) {       for(int i = 0; i < (int)nElements_; i++) {           if(bDescriptor_[i].isFree_ == true) {               bDescriptor_[i].isFree_ = false; return bDescriptor_[i].ptr_; }       }    } }

//============================================================= // METHOD : free // DESCR. : Return true if ptr has been found in bDescriptor_, otherwise false //============================================================= bool MemPool::free(void* ptr) {   for(int i = 0; i < (int)nElements_; i++) {       // Check if the given ptr (in the parameter) belongs in this bDescriptor. if(bDescriptor_[i].ptr_ == true) {           bDescriptor_[i].isFree = true; return true; }   }    return false; }

//============================================================= // METHOD : anyFree // DESCR. : Returns if there is any free BufferDescriptors //============================================================= bool MemPool::anyFree {   for(int i = 0; i < (int)nElements_; i++) {       if(bDescriptor_[i].isFree_ == true) return true; }   return false; }

//============================================================= // METHOD : info // DESCR. : Prints info about the MemPool object //============================================================= void* MemPool::info {   std::cout << "MemPool with " << nElements_ << " number of elements, each with the size " << size_ << std::endl; std::cout << "It contains : ";

for(int i = 0; i < (int)nElements_; i++) {       std::cout << "Element #" << i << " (" << bDescriptor_[i].isFree ? "EMPTY" : "USED") << ")" << std::endl;    } }

//============================================================= // METHOD : info // DESCR. : Returns element size //============================================================= size_t MemPool::getElementSize {   return size_; } code

**Exercise 3 - Design and Implement HeapManager**
Implementeringen af HeapManager kan ses herunder. HeapManager er et singleton objekt, som kan benyttes af diverse klasser til at allokere hukommelse. HeapManager tager imod en størrelse som ønskes på heapen, og finder herefter en blok der passer anmodningen. HeapManager klassen tager kampen op imod heap fragmentation. Det skal dog siges at Heap Fragmentation ikke kan løses, men HeapManager-klassen giver en metode til at modvirke det.

code format="cpp" //===================================== // CLASS : HeapManager // DESCR. : Contols a chunk of raw memory that is logically divided into a number of buffers //===================================== class HeapManager { public: static HeapManager& getInstance ~HeapManager;

void* allocate(size_t memSize); bool free(void* p); void* info;

protected: HeapManager(size_t nPools, size_t nElements, size_t smallestPool);

private: static HeapManager instance_; void* rawMem_;

size_t nPools_; MemPool *pools_; } code Implementeringen kan ses herunder:

code format="cpp" //============================================================= // METHOD : Explicit Constructor // DESCR. : //============================================================= HeapManager::HeapManager(size_t nPools, size_t nElements, size_t smallestPool) : nPools_(nPools) {	// Allocates nPools MemPool-objects. // Constructors will not be called pools_ = (MemPool*)malloc(sizeof(MemPool) * nPools);

void* ptr; size_t tmpSizeOfPool = smallestPool;

for(int i = 0; i < nPools; i++) {		ptr = malloc(sizeof(MemPool));

// Constructor gets called! rawMem[i] = new (ptr) MemPool(nElements, tmpSizeOfPool); tmpSizeOfPool *= 2; } }

//============================================================= // METHOD : getInstance // DESCR. : Returns an instance of HeapManager //============================================================= static HeapManager& HeapManager::getInstance {	return HeapManager::instance_; }

//============================================================= // METHOD : Destructor // DESCR. : //============================================================= HeapManager::~HeapManager {	free(pools_); }

//============================================================= // METHOD : allocate // DESCR. : Returns an ptr to the first unused ptr in the smallest possible MemPool Object //============================================================= void* HeapManager::allocate(size_t memSize) {	// Go through MemPools Array for(int i = 0; i < nPools; i++) {		// Only call allocate in the MemPool class if it is free, // and the size is bigger or equal of the size requested if((pools_[i].getSize => memSize) && (pools_[i].anyFree)		{			return pools_[i].allocate;		}	}	std::cout << "HeapManager::allocate failed" << std::endl; }

//============================================================= // METHOD : free // DESCR. : Return true if ptr has been found in bDescriptor_, otherwise false //============================================================= bool HeapManager::free(void* p) { for(int i = 0; i < nPools; i++) {		if(pools_[i].free(p) == true) return true; }	return false; }

//============================================================= // METHOD : info // DESCR. : Prints info about the HeapManager object //============================================================= void* HeapManager::info {	for(int i = 0; i < nPools; i++) {		std::cout << "Pool: " << (i+1) << ":\n"; std::cout << "Pool address: " << pools_[i].info << "\n"; std::cout << "Element size: " << pools_[i].getElementSize << "\n"; } } code

Exercise 4 - Overloading the global operator new and delete
Ud fra opgavebeskrivelsen overloades new og delete-operatorene. Overloadingen ligger i klassen HeapManager, da man ikke kan benytte de overloadede operatorer uden HeapManager klassen. Implementeringen ses herunder:

code format="cpp" void* operator new(size_t n) { return HeapManager::getInstance.allocate(n); }

void* operator new[](size_t n) { return HeapManager::getInstance.allocate(n); }

void operator delete(void* p) { HeapManager::getInstance.free(p); }

void operator delete[](void* p) { HeapManager::getInstance.free(p); } code