diff --git a/Unuk-QT/Unuk-QT b/Unuk-QT/Unuk-QT index c768e34..6637e7e 100755 Binary files a/Unuk-QT/Unuk-QT and b/Unuk-QT/Unuk-QT differ diff --git a/src/Unuk/Game.h b/src/Unuk/Game.h index 5a9b0d4..6cd21b6 100644 --- a/src/Unuk/Game.h +++ b/src/Unuk/Game.h @@ -17,6 +17,7 @@ #include "../libUnuk/NPC.h" #include "../libUnuk/Debug.h" #include "../libUnuk/Text.h" +#include "../libUnuk/MemClass.h" using namespace std; enum gameNavVal_t { gameMainMenu, gameQuitGame }; diff --git a/src/Unuk/main.cpp b/src/Unuk/main.cpp index 659f259..a457a30 100644 --- a/src/Unuk/main.cpp +++ b/src/Unuk/main.cpp @@ -7,6 +7,7 @@ #include "../libUnuk/MainMenu.h" #include "../libUnuk/NPC.h" #include "../libUnuk/Debug.h" +#include "../libUnuk/MemClass.h" #include "Constants.h" #include "Globals.h" #include "Game.h" @@ -83,6 +84,18 @@ int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { delete menu; 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; //caption << "Unuk - FPS: " << fps; diff --git a/src/libUnuk/IngameMenu.cpp b/src/libUnuk/IngameMenu.cpp index bd71a9d..683298f 100644 --- a/src/libUnuk/IngameMenu.cpp +++ b/src/libUnuk/IngameMenu.cpp @@ -69,9 +69,9 @@ ingameMenuNavVal_t IngameMenu::HandleInput(void) { } void IngameMenu::Render(void) { - btnResume.Render(); - btnSaveGame.Render(); - btnLoadGame.Render(); - btnOptions.Render(); - btnExitToMenu.Render(); + btnResume.RenderLiteral(); + btnSaveGame.RenderLiteral(); + btnLoadGame.RenderLiteral(); + btnOptions.RenderLiteral(); + btnExitToMenu.RenderLiteral(); } diff --git a/src/libUnuk/MemClass.h b/src/libUnuk/MemClass.h index 47185a0..68042a6 100644 --- a/src/libUnuk/MemClass.h +++ b/src/libUnuk/MemClass.h @@ -1,24 +1,30 @@ #ifndef _MEMCLASS_H_ #define _MEMCLASS_H_ -#include -#include #include "MemManager.h" extern MemManager gMemManager; -class Complex { +class MemClass { public: - Complex(void) : r(0), c(0) {} - Complex(double a, double b): r(a), c(b) {} + MemClass(void) : r(0), c(0) {} + MemClass(double a, double b): r(a), c(b) {} inline void* operator new(size_t size) { - return gMemManager.Allocate(sizeof(Complex)); + return gMemManager.Allocate(size); } inline void operator delete(void* 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: // Real part. double r; @@ -26,49 +32,4 @@ private: 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 jobNumber; - std::vector 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 diff --git a/src/libUnuk/MemManager.cpp b/src/libUnuk/MemManager.cpp index f3cb989..afb317e 100644 --- a/src/libUnuk/MemManager.cpp +++ b/src/libUnuk/MemManager.cpp @@ -1,65 +1,206 @@ -#include "MemManager.h" #include "MemClass.h" +#include "MemManager.h" 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* base = 0; - switch(size) { - case SCHEDULER_SIZE: { // 28 - if(_byte32PtrList.empty()) { - base = new char[32 * POOL_SIZE]; - _memoryPoolList.push_back(base); - InitByte32List(base); - } - void* blockPtr = _byte32PtrList.front(); - // Size of block set. - *((static_cast(blockPtr)) + 30) = 32; - // Block is no longer free. - *((static_cast(blockPtr)) + 31) = 0; - _byte32PtrList.pop_front(); - return blockPtr; - } +void BitMapEntry::SetRangeOfInt(int* element, int msb, int lsb, bool flag) { + if(flag) { + int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> INT_SIZE - msb - 1); + *element |= mask; + } else { + int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> INT_SIZE - msb - 1); + *element &= ~mask; + } +} - case COORDINATE_SIZE: { // 36 - if(_byte40PtrList.empty()) { - base = new char[40 * POOL_SIZE]; - _memoryPoolList.push_back(base); - InitByte40List(base); - } - void* blockPtr = _byte40PtrList.front(); - // Size of block set. - *((static_cast(blockPtr)) + 38) = 40; - // Block is no longer free. - *((static_cast(blockPtr)) + 39) = 0; - _byte40PtrList.pop_front(); - return blockPtr; - } +MemClass* BitMapEntry::FirstFreeBlock(size_t size) { + for(int i = 0; i < BIT_MAP_ELEMENTS; i++) { + if(bitMap[i] == 0) + // There aint any bits free. + continue; - case COMPLEX_SIZE: { // 16 - if(_byte24PtrList.empty()) { - base = new char[24 * POOL_SIZE]; - _memoryPoolList.push_back(base); - InitByte24List(base); - } - void* blockPtr = _byte24PtrList.front(); - // Size of block set. - *((static_cast(blockPtr)) + 22) = 32; - // Block is no longer free. - *((static_cast(blockPtr)) + 23) = 0; - _byte24PtrList.pop_front(); - return blockPtr; + // Yield the first bit position. This is a 1 + // in an int from the right. + int result = bitMap[i] & -(bitMap[i]); + void* address = 0; + int basePos = (INT_SIZE * i); + + switch(result) { + // Make the corresponfing bit 0 so block is no longer free. + case 0x00000001: return ComplexObjectAddress(basePos + 0); + case 0x00000002: return ComplexObjectAddress(basePos + 1); + case 0x00000004: return ComplexObjectAddress(basePos + 2); + case 0x00000008: return ComplexObjectAddress(basePos + 3); + 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; } + +MemClass* BitMapEntry::ComplexObjectAddress(int pos) { + SetBit(pos, false); + return &((static_cast(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::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::iterator infoI = _arrayMemoryList.begin(); + map::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(_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(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(bitMap->Head()))[BIT_MAP_SIZE - 1] >= object)) { + int position = static_cast(object)- static_cast(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& MemManager::GetMemoryPoolList(void) { + return _memoryPoolList; +} diff --git a/src/libUnuk/MemManager.h b/src/libUnuk/MemManager.h index 3f8efcb..528eef8 100644 --- a/src/libUnuk/MemManager.h +++ b/src/libUnuk/MemManager.h @@ -1,42 +1,91 @@ #ifndef _MEMMANAGER_H_ #define _MEMMANAGER_H_ -#include -#include -#include -#include +#include #include #include +#include +#include +#include +#include +#include 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 { public: virtual void* Allocate(size_t size) = 0; - virtual void Free(void* ) = 0; + virtual void Free(void* object) = 0; }; class MemManager : public IMemManager { public: - MemManager(void); - ~MemManager(void); + MemManager(void) {} + ~MemManager(void) {} void* Allocate(size_t size); void Free(void* object); + vector& GetMemoryPoolList(void); private: - list _byte8PtrList; - list _byte16PtrList; - list _byte24PtrList; - list _byte32PtrList; - list _byte40PtrList; - list _memoryPoolList; + void* AllocateArrayMemory(size_t size); + void* AllocateChunkAndInitBitMap(void); + void SetBlockBit(void* object, bool flag); + void SetMultipleBlockBits(ArrayMemoryInfo* info, bool flag); - friend class Scheduler; - friend class Coordinate; - friend class Complex; + // The following lists will maintain one to one correspondace + // and should be the same size. + vector _memoryPoolList; + vector _bitMapEntryList; - void InitByte24List(void* base); - void InitByte32List(void* base); - void InitByte40List(void* base); + set _freeMapEntries; + map _arrayMemoryList; }; #endif