Initial commit

This commit is contained in:
jslightham
2023-05-21 23:28:11 -04:00
commit 0360e7dfcc
31 changed files with 2068 additions and 0 deletions

156
P2/ChainingHashTable.cpp Normal file
View File

@@ -0,0 +1,156 @@
#include <iostream>
#include "ChainingHashTable.h"
#include "Process.h"
ChainingHashTable::ChainingHashTable(int size)
{
processList = new std::vector<Process *>[size];
maxCount = size;
count = 0;
}
ChainingHashTable::~ChainingHashTable()
{
for (int i = 0; i < maxCount; i++)
{
for (int j = 0; j < processList[i].size(); j++)
{
delete processList[i][j];
}
}
delete[] processList;
}
/// @brief Insert a process into the hash table
/// @param p the process to insert
/// @return true if insertion was successful, false otherwise
bool ChainingHashTable::Insert(Process *p)
{
if (count >= maxCount)
{
return false;
}
int hashedIndex = p->getPid() % maxCount;
int indexSize = processList[hashedIndex].size();
if (indexSize == 0)
{
processList[hashedIndex].emplace_back(p);
count++;
return true;
}
// attempt to insert in the middle of the vector
for (int i = 0; i < indexSize; i++)
{
if (processList[hashedIndex][i]->getPid() == p->getPid())
{
return false;
}
// store in descending order (9, 8, 7,...)
if (processList[hashedIndex][i]->getPid() < p->getPid())
{
processList[hashedIndex].insert(processList[hashedIndex].begin() + i, p);
count++;
return true;
}
}
// insert at the end of the vector if we have to
processList[hashedIndex].emplace_back(p);
return true;
}
/// @brief Search the hash table for the PID
/// @param PID the PID to search the hash table for
/// @return the index if in the hash table, or -1 otherwise
int ChainingHashTable::Search(unsigned int PID)
{
int hashedIndex = PID % maxCount;
int indexSize = processList[hashedIndex].size();
for (int i = 0; i < indexSize; i++)
{
if (processList[hashedIndex][i]->getPid() == PID)
{
return hashedIndex;
}
}
return -1;
}
/// @brief Get a pointer to the process with PID
/// @param PID the PID to look for
/// @return a pointer to the process, or nullptr if the process does not exist
Process *ChainingHashTable::Get(unsigned int PID)
{
int hashedIndex = PID % maxCount;
int indexSize = processList[hashedIndex].size();
for (int i = 0; i < indexSize; i++)
{
if (processList[hashedIndex][i]->getPid() == PID)
{
return processList[hashedIndex][i];
}
}
return nullptr;
}
/// @brief Remove a process from the hash table with a given PID
/// @param PID the PID of the process to remove
/// @return true if the process was removed, false otherwise
bool ChainingHashTable::Remove(unsigned int PID)
{
int hashedIndex = PID % maxCount;
int indexSize = processList[hashedIndex].size();
for (int i = 0; i < indexSize; i++)
{
if (processList[hashedIndex][i]->getPid() == PID)
{
delete processList[hashedIndex][i];
processList[hashedIndex].erase(processList[hashedIndex].begin() + i);
count--;
return true;
}
}
return false;
}
/// @brief Print out the value of the chain at index m
/// @param m the index to print the chain of
void ChainingHashTable::Print(unsigned int m)
{
if (m >= maxCount)
{
std::cout << "chain is empty" << std::endl;
return;
}
int indexSize = processList[m].size();
for (int i = 0; i < indexSize; i++)
{
if (i != 0)
std::cout << " ";
std::cout << processList[m][i]->getPid();
}
if (indexSize < 1)
{
std::cout << "chain is empty";
}
std::cout << std::endl;
}

23
P2/ChainingHashTable.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef CHAININGHASHTABLE_H
#define CHAININGHASHTABLE_H
#include <vector>
#include "Process.h"
#include "HashTable.h"
class ChainingHashTable : public HashTable
{
public:
bool Insert(Process *p);
int Search(unsigned int PID);
Process *Get(unsigned int PID);
bool Remove(unsigned int PID);
void Print(unsigned int m);
ChainingHashTable(int size);
~ChainingHashTable();
private:
std::vector<Process *> *processList;
};
#endif

177
P2/DoubleHashTable.cpp Normal file
View File

@@ -0,0 +1,177 @@
#include <iostream>
#include <cmath>
#include "DoubleHashTable.h"
#include "Process.h"
DoubleHashTable::DoubleHashTable(int size)
{
processList = new Process *[size];
maxCount = size;
count = 0;
for (int i = 0; i < size; i++)
{
processList[i] = nullptr;
}
}
DoubleHashTable::~DoubleHashTable()
{
for (int i = 0; i < maxCount; i++)
{
if (processList[i] != nullptr)
delete processList[i];
}
delete[] processList;
}
/// @brief Insert a process into the hash table
/// @param p pointer to the process to insert
/// @return true if successful, false otherwise
bool DoubleHashTable::Insert(Process *p)
{
if (count >= maxCount)
{
return false;
}
// Continually hash until we have reached a nullpointer, -1, or the end
int emptyIndex = -1;
for (int i = 0; i < maxCount; i++)
{
unsigned int hashedIndex = HashIndex(p->getPid(), i);
// If we have reached a nullptr, and have not seen any empty slots before
if (processList[hashedIndex] == nullptr && emptyIndex == -1)
{
// Replace the nullpointer with the process
processList[hashedIndex] = p;
return true;
}
// If we have reached a nullpointer and have seen an empty slot before
else if (processList[hashedIndex] == nullptr && emptyIndex != -1)
{
// Replace the -1 with the process
hashedIndex = HashIndex(p->getPid(), emptyIndex);
delete processList[hashedIndex];
processList[hashedIndex] = p;
return true;
}
// If we find a process with the same PID already, exit
else if (processList[hashedIndex]->getPid() == p->getPid())
{
return false;
}
// If we have found a slot of -1
else if (processList[hashedIndex]->getStartingIndex() == -1 && emptyIndex == -1)
{
// If we can insert in the empty slot (have reached the end)
emptyIndex = i;
if (!(i + 1 < maxCount))
{
delete processList[hashedIndex];
processList[hashedIndex] = p;
return true;
}
}
}
// Insert into the empty slot - theoretically we do not need the code in the if statement of the last else if clause, but it works...
if (emptyIndex != -1)
{
unsigned int hashedIndex = HashIndex(p->getPid(), emptyIndex);
delete processList[hashedIndex];
processList[hashedIndex] = p;
return true;
}
return false;
}
/// @brief Search the hash table for the given PID
/// @param PID the pid to search for
/// @return the index of the process, or -1 if the process does not exist
int DoubleHashTable::Search(unsigned int PID)
{
for (int i = 0; i < maxCount; i++)
{
int hashedIndex = HashIndex(PID, i);
if (hashedIndex >= maxCount || processList[hashedIndex] == nullptr)
{
return -1;
}
else if (processList[hashedIndex]->getPid() == PID)
{
return hashedIndex;
}
}
return -1;
}
/// @brief Search the hash table for the given PID, and return a pointer to the process object
/// @param PID the pid to search for
/// @return A valid process object if it exists, or a nullpointer otherwise
Process *DoubleHashTable::Get(unsigned int PID)
{
for (int i = 0; i < maxCount; i++)
{
int hashedIndex = HashIndex(PID, i);
if (hashedIndex >= maxCount || processList[hashedIndex] == nullptr)
{
return nullptr;
}
else if (processList[hashedIndex]->getPid() == PID)
{
return processList[hashedIndex];
}
}
return nullptr;
}
/// @brief Remove a process object from the hash table
/// @param PID the PID of the process to remove
/// @return true if the process was successfully removed, false otherwise
bool DoubleHashTable::Remove(unsigned int PID)
{
for (int i = 0; i < maxCount; i++)
{
int hashedIndex = HashIndex(PID, i);
if (hashedIndex >= maxCount || processList[hashedIndex] == nullptr)
{
return false;
}
else if (processList[hashedIndex]->getPid() == PID)
{
delete processList[hashedIndex];
processList[hashedIndex] = new Process(0, -1);
return true;
}
}
return false;
}
/// @brief Compute the hash of k and i.
/// @param k the k value to hash (PID)
/// @param i the i value to hash (index)
/// @return the hashed value
int DoubleHashTable::HashIndex(unsigned int k, int i)
{
unsigned int h1 = k % maxCount;
unsigned int h2 = (int)std::floor(k / maxCount) % maxCount;
if (h2 % 2 == 0)
h2++;
return (h1 + i * h2) % maxCount;
}
void DoubleHashTable::Print(unsigned int m)
{
// Not implemented
}

24
P2/DoubleHashTable.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef DOUBLEHASHTABLE_H
#define DOUBLEHASHTABLE_H
#include <vector>
#include "Process.h"
#include "HashTable.h"
class DoubleHashTable : public HashTable
{
public:
bool Insert(Process *p);
int Search(unsigned int PID);
Process *Get(unsigned int PID);
bool Remove(unsigned int PID);
void Print(unsigned int m);
DoubleHashTable(int size);
~DoubleHashTable();
private:
Process **processList;
int HashIndex(unsigned int k, int i);
};
#endif

20
P2/HashTable.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <vector>
#include "Process.h"
class HashTable
{
public:
virtual bool Insert(Process *p) = 0;
virtual int Search(unsigned int PID) = 0;
virtual Process *Get(unsigned int PID) = 0;
virtual bool Remove(unsigned int PID) = 0;
virtual void Print(unsigned int m) = 0;
protected:
int maxCount;
int count;
};
#endif

2
P2/Makefile Normal file
View File

@@ -0,0 +1,2 @@
all: test.cpp ChainingHashTable.cpp DoubleHashTable.cpp Process.cpp VirtualMemory.cpp
g++ -std=c++11 test.cpp ChainingHashTable.cpp DoubleHashTable.cpp Process.cpp VirtualMemory.cpp

17
P2/Process.cpp Normal file
View File

@@ -0,0 +1,17 @@
#include "Process.h"
Process::Process(unsigned int PID, int startingIndex)
{
this->PID = PID;
this->startingIndex = startingIndex;
}
unsigned int Process::getPid()
{
return this->PID;
}
int Process::getStartingIndex()
{
return this->startingIndex;
}

16
P2/Process.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef PROCESS_H
#define PROCESS_H
class Process
{
public:
unsigned int getPid();
int getStartingIndex();
Process(unsigned int PID, int startingIndex);
private:
unsigned int PID;
int startingIndex;
};
#endif

136
P2/VirtualMemory.cpp Normal file
View File

@@ -0,0 +1,136 @@
#include <iostream>
#include "VirtualMemory.h"
#include "ChainingHashTable.h"
#include "DoubleHashTable.h"
VirtualMemory::VirtualMemory(int n, int p, bool chaining)
{
if (chaining)
{
ht = new ChainingHashTable(n / p);
}
else
{
ht = new DoubleHashTable(n / p);
}
this->chaining = chaining;
this->memorySize = n;
this->pageSize = p;
this->memory = new int[n];
// push the indices onto the free memory
for (int i = 0; i < n / p; i++)
{
freeMemory.push_back(i);
}
}
VirtualMemory::~VirtualMemory()
{
if (chaining)
{
delete (ChainingHashTable *)ht;
}
else
{
delete (DoubleHashTable *)ht;
}
delete[] memory;
}
/// @brief Allocate memory for process PID
/// @param PID the PID to allocate memory for
/// @return true if successful, false otherwise
bool VirtualMemory::Insert(unsigned int PID)
{
if (freeMemory.size() <= 0)
return false;
int memoryIndex = freeMemory.back();
freeMemory.pop_back();
Process *p = new Process(PID, memoryIndex);
if (!ht->Insert(p))
{
delete p;
freeMemory.push_back(memoryIndex);
return false;
}
return true;
}
/// @brief Search the hash table for the index of PID
/// @param PID the PID of the process to search for
/// @return the index of the process object, -1 if the object does not exist
int VirtualMemory::Search(unsigned int PID)
{
return ht->Search(PID);
}
/// @brief Write to a process's memory
/// @param PID The PID of the memory to write to
/// @param addr The virtual address of the memory to write to
/// @param x The value to write into memory
/// @return true if successful, false otherwise
bool VirtualMemory::Write(unsigned int PID, int addr, int x)
{
if (addr >= pageSize || addr < 0)
return false;
Process *p = ht->Get(PID);
// if we do not have any memory allocated to PID
if (p == nullptr)
return false;
memory[p->getStartingIndex() * pageSize + addr] = x;
return true;
}
/// @brief Read the memory
/// @param PID The PID of the process to read memory of
/// @param addr The virtual address of memory to read from
void VirtualMemory::Read(unsigned int PID, int addr)
{
if (addr >= pageSize)
{
std::cout << "failure" << std::endl;
return;
}
Process *p = ht->Get(PID);
// if we do not have any memory allocated to PID
if (p == nullptr)
{
std::cout << "failure" << std::endl;
return;
}
std::cout << addr << " " << memory[p->getStartingIndex() * pageSize + addr] << std::endl;
}
/// @brief Deallocate memory from process PID.
/// @param PID The PID of the process to dealocate memory from
/// @return true if successful, false otherwise
bool VirtualMemory::Delete(unsigned int PID)
{
Process *p = ht->Get(PID);
if (p == nullptr)
return false;
freeMemory.push_back(p->getStartingIndex());
return ht->Remove(PID);
}
/// @brief Print the chain of the hash table at index m
/// @param m the index of the chain to print
void VirtualMemory::Print(int m)
{
ht->Print(m);
}

30
P2/VirtualMemory.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef VIRTUALMEMORY_H
#define VIRTUALMEMORY_H
#include "Process.h"
#include "HashTable.h"
class VirtualMemory
{
public:
VirtualMemory(int n, int p, bool chaining);
~VirtualMemory();
bool Insert(unsigned int PID);
int Search(unsigned int PID);
bool Write(unsigned int PID, int addr, int x);
void Read(unsigned int PID, int addr);
bool Delete(unsigned int PID);
void Print(int m);
private:
HashTable *ht;
int memorySize;
int pageSize;
int *memory;
std::vector<int> freeMemory;
bool chaining;
};
#endif

103
P2/test.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include <iostream>
#include "VirtualMemory.h"
using namespace std;
int main()
{
string cmd;
VirtualMemory *vm = nullptr;
bool chaining = true;
while (cin >> cmd)
{
if (cmd == "OPEN")
{
chaining = false;
}
else if (cmd == "ORDERED")
{
chaining = true;
}
if (cmd == "M")
{
int N;
int P;
cin >> N;
cin >> P;
vm = new VirtualMemory(N, P, chaining);
cout << "success" << endl;
}
else if (cmd == "INSERT")
{
unsigned int PID;
cin >> PID;
if (vm->Insert(PID))
cout << "success" << endl;
else
cout << "failure" << endl;
}
else if (cmd == "SEARCH")
{
unsigned int PID;
cin >> PID;
int ret = vm->Search(PID);
if (ret == -1)
cout << "not found" << endl;
else
cout << "found " << PID << " in " << ret << endl;
}
else if (cmd == "WRITE")
{
unsigned int PID;
int ADDR;
int x;
cin >> PID;
cin >> ADDR;
cin >> x;
if (vm->Write(PID, ADDR, x))
cout << "success" << endl;
else
cout << "failure" << endl;
}
else if (cmd == "READ")
{
unsigned int PID;
int ADDR;
cin >> PID;
cin >> ADDR;
vm->Read(PID, ADDR);
}
else if (cmd == "DELETE")
{
unsigned int PID;
cin >> PID;
if (vm->Delete(PID))
cout << "success" << endl;
else
cout << "failure" << endl;
}
else if (cmd == "PRINT")
{
int m;
cin >> m;
vm->Print(m);
}
else if (cmd == "END")
{
break;
}
}
delete vm;
}