#ifndef FAUXMEMORY_IMP_H #define FAUXMEMORY_IMP_H #include "FauxMemory.h" #include /************** * Constructor * ***************/ FauxMemory::FauxMemory(int max_size){ // Initialise empty Memory HoleBlock* init_hole = new HoleBlock(max_size); init_hole->setStart(0); init_hole->setEnd(max_size - 1); allBlocks.push_back(init_hole); // Initialise vars setLimit(max_size - 1); setFree(max_size); last_bid = -1; } /********** * Setters * ***********/ void FauxMemory::setLimit(int maxSize){ limit_register = maxSize; } void FauxMemory::setFree(int maxSize){ free = maxSize; } void FauxMemory::setBid(int new_bid){ last_bid = new_bid; } /********** * Getters * ***********/ vector* FauxMemory::getAllBlocks(){ return &allBlocks; } vector* FauxMemory::getAllErrors(){ return &allErrors; } string FauxMemory::getStrategy(){ return strategy; } int* FauxMemory::getBid(){ return &last_bid; } int* FauxMemory::getLimit(){ return &limit_register; } int* FauxMemory::getFree(){ return &free; } int FauxMemory::getTotalSize(){ return limit_register; } /********************** * Increment Bid by 1. * ***********************/ void FauxMemory::incrementBid(){ this->last_bid++; } /********************************************************** * This method stores and allocation error when it occurs. * ***********************************************************/ void FauxMemory::addAllocError(int inst_num){ // Instruction type string inst_type = "A"; // Find biggest free block int max_space = 0; for(auto block : (*this->getAllBlocks())){ if(block->getId() == -1) { if(block->getSize() > max_space){ max_space = block->getSize(); }; }; }; // Generate and store error. string error = inst_type + ";" + to_string(inst_num) + ";" + to_string(max_space); this->allErrors.push_back(error); } /********************************************************** * This method stores a deallocation error when it occurs. * ***********************************************************/ void FauxMemory::addDallocError(int inst_num, int block_id){ string inst_type = "D"; int reason_failed = 0; if(block_id <= (*this->getBid())){ reason_failed = 1; }; string error = inst_type + ";" + to_string(inst_num) + ";" + to_string(reason_failed); this->allErrors.push_back(error); } /****************************************************************** * This is the method to calculate the fragmentation of the memory * *******************************************************************/ float FauxMemory::fragmentation(){ // Find the size of the largest free block int largest_free = 0; for(auto block : this->allBlocks){ if(block->getId() == -1){ if(block->getSize() > largest_free){ largest_free = block->getSize(); }; }; }; // Calculate fragmentation if(largest_free == 0){ return 0; }else{ return (1 - (static_cast(largest_free) / static_cast((*this->getFree())))); } } /************************************************************** * This is the method to deallocate a block based on their id. * ***************************************************************/ bool FauxMemory::deallocMem(int id){ // Makre sure there are programs loaded into memory // Must contain at least one block in memory. if((*this->getAllBlocks()).size() < 1){ return false; }; // Declare a new hole block HoleBlock* new_hole = new HoleBlock(0); // Sequentailly check all blocks to find the correct one. // Declare a pointer for readability. for(int i =0; i < (*this->getAllBlocks()).size(); i++){ // Pointer to current Program block MemBlock* currBlock = (*this->getAllBlocks())[i]; // Check if this is the right block if(currBlock->getId() == id){ // Declare neighbours used for freeing memory MemBlock* low_neighbour; MemBlock* high_neighbour; // Merge neighbouring hole blocks to form a bigger hole block. // Check index to see if this is an "edge" case. bool low = (i > 0); bool high = (i < (this->getAllBlocks()->size() - 1)); // Merge low neighbour if(low){ low_neighbour = (*this->getAllBlocks())[i-1]; if(low_neighbour->getId() == -1){ new_hole->setStart(low_neighbour->getStart()); this->getAllBlocks()->erase(this->getAllBlocks()->begin() + (i-1)); delete low_neighbour; i -= 1; } else { new_hole->setStart(currBlock->getStart()); }; } else { new_hole->setStart(currBlock->getStart()); }; // Merge high neighbour if(high){ high_neighbour = (*this->getAllBlocks())[i+1]; if(high_neighbour->getId() == -1){ new_hole->setEnd(high_neighbour->getEnd()); this->getAllBlocks()->erase(this->getAllBlocks()->begin() + (i+1)); delete high_neighbour; } else { new_hole->setEnd(currBlock->getEnd()); }; } else { new_hole->setEnd(currBlock->getEnd()); }; // Resize the new free memory block new_hole->resize(); this->setFree((*this->getFree()) + currBlock->getSize()); // Replace program block with a hole block. (*this->getAllBlocks())[i] = new_hole; delete currBlock; return true; }; }; // All blocks checked - invalid Id return false; } /******************************************* * This is the method to compact the memory.* ********************************************/ bool FauxMemory::compactMem(){ vector new_memory; int new_start = 0; // Push program blocks to the top of the memory (move addresses) for(auto block : this->allBlocks){ if (block->getId() >= 0){ // Update block block->setStart(new_start); block->setEnd(new_start + (block->getSize() - 1)); new_memory.push_back(block); // Update address for the next iteration. new_start = block->getEnd() + 1; } else { // Deletes hole blocks. delete block; } }; // "Fill up" the remaining memory with free space in the form of a new hole block. HoleBlock* new_hole = new HoleBlock(0); new_hole->setStart(new_memory.back()->getEnd() + 1); new_hole->setEnd((*this->getLimit())); new_hole->resize(); new_memory.push_back(new_hole); // Update memory. this->allBlocks = new_memory; // Confirm compaction return true; } #endif