[Add] Added Memory Manager.

-- Supports allocation of memory.
-- Memory Dealocation.
-- Arrays!
-- etc :D

'tis a bit mapped memory manager.
This commit is contained in:
Rtch90 2012-01-03 01:43:33 +00:00
parent 8db54e61bc
commit 0f9c39ec1b
7 changed files with 290 additions and 125 deletions

Binary file not shown.

View File

@ -17,6 +17,7 @@
#include "../libUnuk/NPC.h" #include "../libUnuk/NPC.h"
#include "../libUnuk/Debug.h" #include "../libUnuk/Debug.h"
#include "../libUnuk/Text.h" #include "../libUnuk/Text.h"
#include "../libUnuk/MemClass.h"
using namespace std; using namespace std;
enum gameNavVal_t { gameMainMenu, gameQuitGame }; enum gameNavVal_t { gameMainMenu, gameQuitGame };

View File

@ -7,6 +7,7 @@
#include "../libUnuk/MainMenu.h" #include "../libUnuk/MainMenu.h"
#include "../libUnuk/NPC.h" #include "../libUnuk/NPC.h"
#include "../libUnuk/Debug.h" #include "../libUnuk/Debug.h"
#include "../libUnuk/MemClass.h"
#include "Constants.h" #include "Constants.h"
#include "Globals.h" #include "Globals.h"
#include "Game.h" #include "Game.h"
@ -83,6 +84,18 @@ int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) {
delete menu; delete menu;
break; break;
} }
// This is NOT going to go nicely. But I want to test this.
MemClass* array[1000];
// Allocate a shitload of memory.
for(int i = 0; i < 5000; i++) {
for(int j = 0; j < 1000; j++) {
array[j] = new MemClass(i, j);
}
// Get rid of it.
for(int j = 0; j < 1000; j++) {
delete array[j];
}
}
} }
//stringstream caption; //stringstream caption;
//caption << "Unuk - FPS: " << fps; //caption << "Unuk - FPS: " << fps;

View File

@ -69,9 +69,9 @@ ingameMenuNavVal_t IngameMenu::HandleInput(void) {
} }
void IngameMenu::Render(void) { void IngameMenu::Render(void) {
btnResume.Render(); btnResume.RenderLiteral();
btnSaveGame.Render(); btnSaveGame.RenderLiteral();
btnLoadGame.Render(); btnLoadGame.RenderLiteral();
btnOptions.Render(); btnOptions.RenderLiteral();
btnExitToMenu.Render(); btnExitToMenu.RenderLiteral();
} }

View File

@ -1,24 +1,30 @@
#ifndef _MEMCLASS_H_ #ifndef _MEMCLASS_H_
#define _MEMCLASS_H_ #define _MEMCLASS_H_
#include <string>
#include <vector>
#include "MemManager.h" #include "MemManager.h"
extern MemManager gMemManager; extern MemManager gMemManager;
class Complex { class MemClass {
public: public:
Complex(void) : r(0), c(0) {} MemClass(void) : r(0), c(0) {}
Complex(double a, double b): r(a), c(b) {} MemClass(double a, double b): r(a), c(b) {}
inline void* operator new(size_t size) { inline void* operator new(size_t size) {
return gMemManager.Allocate(sizeof(Complex)); return gMemManager.Allocate(size);
} }
inline void operator delete(void* object) { inline void operator delete(void* object) {
gMemManager.Free(object); gMemManager.Free(object);
} }
inline void* operator new [](size_t size) {
return gMemManager.Allocate(size);
}
inline void operator delete [](void* object) {
gMemManager.Free(object);
}
private: private:
// Real part. // Real part.
double r; double r;
@ -26,49 +32,4 @@ private:
double c; double c;
}; };
class Coordinate {
int coordX;
int coordY;
int coordZ;
std::string name;
public:
Coordinate(void) : coordX(0), coordY(0), coordZ(0), name("") {}
inline void* operator new(size_t size) {
return gMemManager.Allocate(sizeof(Coordinate));
}
inline void operator delete(void* object) {
gMemManager.Free(object);
}
};
class Scheduler {
std::vector<int> jobNumber;
std::vector<int> maxJobTime;
int startTime;
public:
Scheduler(void) {}
inline void* operator new(size_t size) {
return gMemManager.Allocate(sizeof(Scheduler));
}
inline void operator delete(void* object) {
gMemManager.Free(object);
}
};
const int SCHEDULER_SIZE = sizeof(Scheduler);
const int COMPLEX_SIZE = sizeof(Complex);
const int COORDINATE_SIZE = sizeof(Coordinate);
// Number of elements in a single pool can be chosen on
// application requirement.
const int POOL_SIZE = 1024;
// Depending on the application this may change.
const int MAX_BLOCK_SIZE = 36;
#endif #endif

View File

@ -1,65 +1,206 @@
#include "MemManager.h"
#include "MemClass.h" #include "MemClass.h"
#include "MemManager.h"
MemManager gMemManager; MemManager gMemManager;
MemManager::MemManager(void) { void BitMapEntry::SetBit(int position, bool flag) {
blocksAvailable += flag ? 1 : -1;
int elementNo = position / INT_SIZE;
int bitNo = position % INT_SIZE;
if(flag)
bitMap[elementNo] = bitMap[elementNo] | (1 << bitNo);
else
bitMap[elementNo] = bitMap[elementNo] & ~(1 << bitNo);
} }
MemManager::~MemManager(void) { void BitMapEntry::SetMultipleBits(int position, bool flag, int count) {
blocksAvailable += flag ? count : -count;
int elementNo = position / INT_SIZE;
int bitNo = position % INT_SIZE;
int bitSize = (count <= INT_SIZE - bitNo) ? count : INT_SIZE - bitNo;
SetRangeOfInt(&bitMap[elementNo], bitNo + bitSize - 1, bitNo, flag);
count -= bitSize;
if(!count) return;
int i = ++elementNo;
while(count >= 0) {
if(count <= INT_SIZE) {
SetRangeOfInt(&bitMap[i], count - 1, 0, flag);
return;
} else
bitMap[i] = flag ? unsigned (-1) : 0;
count -= 32;
i++;
}
} }
void* MemManager::Allocate(size_t size) { void BitMapEntry::SetRangeOfInt(int* element, int msb, int lsb, bool flag) {
void* base = 0; if(flag) {
switch(size) { int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> INT_SIZE - msb - 1);
case SCHEDULER_SIZE: { // 28 *element |= mask;
if(_byte32PtrList.empty()) { } else {
base = new char[32 * POOL_SIZE]; int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> INT_SIZE - msb - 1);
_memoryPoolList.push_back(base); *element &= ~mask;
InitByte32List(base); }
} }
void* blockPtr = _byte32PtrList.front();
// Size of block set.
*((static_cast<char*>(blockPtr)) + 30) = 32;
// Block is no longer free.
*((static_cast<char*>(blockPtr)) + 31) = 0;
_byte32PtrList.pop_front();
return blockPtr;
}
case COORDINATE_SIZE: { // 36 MemClass* BitMapEntry::FirstFreeBlock(size_t size) {
if(_byte40PtrList.empty()) { for(int i = 0; i < BIT_MAP_ELEMENTS; i++) {
base = new char[40 * POOL_SIZE]; if(bitMap[i] == 0)
_memoryPoolList.push_back(base); // There aint any bits free.
InitByte40List(base); continue;
}
void* blockPtr = _byte40PtrList.front();
// Size of block set.
*((static_cast<char*>(blockPtr)) + 38) = 40;
// Block is no longer free.
*((static_cast<char*>(blockPtr)) + 39) = 0;
_byte40PtrList.pop_front();
return blockPtr;
}
case COMPLEX_SIZE: { // 16 // Yield the first bit position. This is a 1
if(_byte24PtrList.empty()) { // in an int from the right.
base = new char[24 * POOL_SIZE]; int result = bitMap[i] & -(bitMap[i]);
_memoryPoolList.push_back(base); void* address = 0;
InitByte24List(base); int basePos = (INT_SIZE * i);
}
void* blockPtr = _byte24PtrList.front(); switch(result) {
// Size of block set. // Make the corresponfing bit 0 so block is no longer free.
*((static_cast<char*>(blockPtr)) + 22) = 32; case 0x00000001: return ComplexObjectAddress(basePos + 0);
// Block is no longer free. case 0x00000002: return ComplexObjectAddress(basePos + 1);
*((static_cast<char*>(blockPtr)) + 23) = 0; case 0x00000004: return ComplexObjectAddress(basePos + 2);
_byte24PtrList.pop_front(); case 0x00000008: return ComplexObjectAddress(basePos + 3);
return blockPtr; case 0x00000010: return ComplexObjectAddress(basePos + 4);
case 0x00000020: return ComplexObjectAddress(basePos + 5);
case 0x00000040: return ComplexObjectAddress(basePos + 6);
case 0x00000080: return ComplexObjectAddress(basePos + 7);
case 0x00000100: return ComplexObjectAddress(basePos + 8);
case 0x00000200: return ComplexObjectAddress(basePos + 9);
case 0x00000400: return ComplexObjectAddress(basePos + 10);
case 0x00000800: return ComplexObjectAddress(basePos + 11);
case 0x00001000: return ComplexObjectAddress(basePos + 12);
case 0x00002000: return ComplexObjectAddress(basePos + 13);
case 0x00004000: return ComplexObjectAddress(basePos + 14);
case 0x00008000: return ComplexObjectAddress(basePos + 15);
case 0x00010000: return ComplexObjectAddress(basePos + 16);
case 0x00020000: return ComplexObjectAddress(basePos + 17);
case 0x00040000: return ComplexObjectAddress(basePos + 18);
case 0x00080000: return ComplexObjectAddress(basePos + 19);
case 0x00100000: return ComplexObjectAddress(basePos + 20);
case 0x00200000: return ComplexObjectAddress(basePos + 21);
case 0x00400000: return ComplexObjectAddress(basePos + 22);
case 0x00800000: return ComplexObjectAddress(basePos + 23);
case 0x01000000: return ComplexObjectAddress(basePos + 24);
case 0x02000000: return ComplexObjectAddress(basePos + 25);
case 0x04000000: return ComplexObjectAddress(basePos + 26);
case 0x08000000: return ComplexObjectAddress(basePos + 27);
case 0x10000000: return ComplexObjectAddress(basePos + 28);
case 0x20000000: return ComplexObjectAddress(basePos + 29);
case 0x40000000: return ComplexObjectAddress(basePos + 30);
case 0x80000000: return ComplexObjectAddress(basePos + 31);
default: break;
} }
default:
break;
} }
return 0; return 0;
} }
MemClass* BitMapEntry::ComplexObjectAddress(int pos) {
SetBit(pos, false);
return &((static_cast<MemClass*>(Head()) + (pos / INT_SIZE)) [INT_SIZE - (pos % INT_SIZE + 1)]);
}
void* BitMapEntry::Head(void) {
return gMemManager.GetMemoryPoolList()[index];
}
void* MemManager::Allocate(size_t size) {
// None array.
if(size == sizeof(MemClass)) {
set<BitMapEntry*>::iterator freeMapI = _freeMapEntries.begin();
if(freeMapI != _freeMapEntries.end()) {
BitMapEntry* mapEntry = *freeMapI;
return mapEntry->FirstFreeBlock(size);
} else {
AllocateChunkAndInitBitMap();
_freeMapEntries.insert(&(_bitMapEntryList[_bitMapEntryList.size() - 1]));
return _bitMapEntryList[_bitMapEntryList.size() - 1].FirstFreeBlock(size);
}
} else {
// Array.
if(_arrayMemoryList.empty()) {
return AllocateArrayMemory(size);
} else {
map<void*, ArrayMemoryInfo>::iterator infoI = _arrayMemoryList.begin();
map<void*, ArrayMemoryInfo>::iterator infoEndI = _arrayMemoryList.end();
while(infoI != infoEndI) {
ArrayMemoryInfo info = (*infoI).second;
if(info.StartPosition != 0)
// Only search the memory blocks where allocation
// is done from first byte.
continue;
else {
BitMapEntry* entry = &_bitMapEntryList[info.memPoolListIndex];
if(entry->blocksAvailable < (size / sizeof(MemClass)))
return AllocateArrayMemory(size);
else {
info.StartPosition = BIT_MAP_SIZE - entry->blocksAvailable;
info.Size = size / sizeof(MemClass);
MemClass* baseAddress = static_cast<MemClass*>(_memoryPoolList[info.memPoolListIndex]) + info.StartPosition;
_arrayMemoryList[baseAddress] = info;
SetMultipleBlockBits(&info, false);
return baseAddress;
}
}
}
}
}
return 0;
}
void* MemManager::AllocateArrayMemory(size_t size) {
void* chunkAddress = AllocateChunkAndInitBitMap();
ArrayMemoryInfo info;
info.memPoolListIndex = _memoryPoolList.size() - 1;
info.StartPosition = 0;
info.Size = size / sizeof(MemClass);
_arrayMemoryList[chunkAddress] = info;
SetMultipleBlockBits(&info, false);
return chunkAddress;
}
void* MemManager::AllocateChunkAndInitBitMap(void) {
BitMapEntry mapEntry;
MemClass* memoryBeginAddress = reinterpret_cast<MemClass*>(new char[sizeof(MemClass) * BIT_MAP_SIZE]);
_memoryPoolList.push_back(memoryBeginAddress);
mapEntry.index = _memoryPoolList.size() - 1;
_bitMapEntryList.push_back(mapEntry);
return memoryBeginAddress;
}
void MemManager::Free(void* object) {
if(_arrayMemoryList.find(object) == _arrayMemoryList.end())
// Simple block deletion.
SetBlockBit(object, true);
else {
// Memory block deletion.
ArrayMemoryInfo *info = &_arrayMemoryList[object];
SetMultipleBlockBits(info, true);
}
}
void MemManager::SetBlockBit(void* object, bool flag) {
int i = _bitMapEntryList.size() - 1;
for(; i >= 0; i--) {
BitMapEntry* bitMap = &_bitMapEntryList[i];
if((bitMap->Head() <= object) && (&(static_cast<MemClass*>(bitMap->Head()))[BIT_MAP_SIZE - 1] >= object)) {
int position = static_cast<MemClass*>(object)- static_cast<MemClass*>(bitMap->Head());
bitMap->SetBit(position, flag);
flag ? bitMap->blocksAvailable++ : bitMap->blocksAvailable--;
}
}
}
void MemManager::SetMultipleBlockBits(ArrayMemoryInfo* info, bool flag) {
BitMapEntry* mapEntry = &_bitMapEntryList[info->memPoolListIndex];
mapEntry->SetMultipleBits(info->StartPosition, flag, info->Size);
}
vector<void*>& MemManager::GetMemoryPoolList(void) {
return _memoryPoolList;
}

View File

@ -1,42 +1,91 @@
#ifndef _MEMMANAGER_H_ #ifndef _MEMMANAGER_H_
#define _MEMMANAGER_H_ #define _MEMMANAGER_H_
#include <vector> #include <iostream>
#include <set>
#include <list>
#include <stdio.h>
#include <vector> #include <vector>
#include <string> #include <string>
#include <string.h>
#include <vector>
#include <set>
#include <map>
#include <bitset>
using namespace std; using namespace std;
const int BIT_MAP_SIZE = 1024;
const int INT_SIZE = sizeof(int) * 8;
const int BIT_MAP_ELEMENTS = BIT_MAP_SIZE / INT_SIZE;
/*
* Memory Allocation Pattern.
* 11111111 11111111 11111111
* 11111110 11111111 11111111
* 11111100 11111111 11111111
*
* If all bits for the first section becomes zero go to next section.
*
* 00000000 11111111 11111111
* 00000000 11111110 11111111
* 00000000 11111100 11111111
* 00000000 11111000 11111111
*
* The lookup inside the map becomes 0(1) for the first available free block.
*/
class MemClass;
typedef struct BitMapEntry {
int index;
int blocksAvailable;
int bitMap[BIT_MAP_SIZE];
public:
BitMapEntry():blocksAvailable(BIT_MAP_SIZE) {
// All blocks are free to begin with and bit value 1
// in the map denotes available blocks.
memset(bitMap, 0xff, BIT_MAP_SIZE / sizeof(char));
}
void SetBit(int position, bool flag);
void SetMultipleBits(int position, bool flag, int count);
void SetRangeOfInt(int* element, int msb, int lsb, bool flag);
MemClass* FirstFreeBlock(size_t size);
MemClass* ComplexObjectAddress(int pos);
void* Head(void);
} BitMapEntry;
typedef struct ArrayInfo {
int memPoolListIndex;
int StartPosition;
int Size;
} ArrayMemoryInfo;
class IMemManager { class IMemManager {
public: public:
virtual void* Allocate(size_t size) = 0; virtual void* Allocate(size_t size) = 0;
virtual void Free(void* ) = 0; virtual void Free(void* object) = 0;
}; };
class MemManager : public IMemManager { class MemManager : public IMemManager {
public: public:
MemManager(void); MemManager(void) {}
~MemManager(void); ~MemManager(void) {}
void* Allocate(size_t size); void* Allocate(size_t size);
void Free(void* object); void Free(void* object);
vector<void*>& GetMemoryPoolList(void);
private: private:
list<void*> _byte8PtrList; void* AllocateArrayMemory(size_t size);
list<void*> _byte16PtrList; void* AllocateChunkAndInitBitMap(void);
list<void*> _byte24PtrList; void SetBlockBit(void* object, bool flag);
list<void*> _byte32PtrList; void SetMultipleBlockBits(ArrayMemoryInfo* info, bool flag);
list<void*> _byte40PtrList;
list<void*> _memoryPoolList;
friend class Scheduler; // The following lists will maintain one to one correspondace
friend class Coordinate; // and should be the same size.
friend class Complex; vector<void*> _memoryPoolList;
vector<BitMapEntry> _bitMapEntryList;
void InitByte24List(void* base); set<BitMapEntry*> _freeMapEntries;
void InitByte32List(void* base); map<void*, ArrayMemoryInfo> _arrayMemoryList;
void InitByte40List(void* base);
}; };
#endif #endif