ContigousMemory / memories / FauxMemory.imp.h
FauxMemory.imp.h
Raw
#ifndef FAUXMEMORY_IMP_H
#define FAUXMEMORY_IMP_H
#include "FauxMemory.h"
#include <string>

  /**************
  * 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<MemBlock*>* FauxMemory::getAllBlocks(){
    return &allBlocks;
  }
  vector<string>* 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<float>(largest_free) / static_cast<float>((*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<MemBlock*> 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