[Add] New memory management.
[Clean] Source code was messy, so I have given it a good clean.
This commit is contained in:
parent
d16472c28e
commit
896b966530
@ -12,7 +12,6 @@ HEADERS += ../src/Libs/wglext.h \
|
|||||||
../src/libUnuk/Engine/WorldManager.h \
|
../src/libUnuk/Engine/WorldManager.h \
|
||||||
../src/libUnuk/Engine/ParticleEmitter.h \
|
../src/libUnuk/Engine/ParticleEmitter.h \
|
||||||
../src/libUnuk/Engine/NPC.h \
|
../src/libUnuk/Engine/NPC.h \
|
||||||
../src/libUnuk/Engine/MemManager.h \
|
|
||||||
../src/libUnuk/Engine/MemClass.h \
|
../src/libUnuk/Engine/MemClass.h \
|
||||||
../src/libUnuk/Engine/Collision.h \
|
../src/libUnuk/Engine/Collision.h \
|
||||||
../src/libUnuk/Engine/Character.h \
|
../src/libUnuk/Engine/Character.h \
|
||||||
@ -49,11 +48,11 @@ HEADERS += ../src/Libs/wglext.h \
|
|||||||
../src/libUnuk/System/MathBox.h \
|
../src/libUnuk/System/MathBox.h \
|
||||||
../src/libUnuk/Engine/Pathfinding.h \
|
../src/libUnuk/Engine/Pathfinding.h \
|
||||||
../src/libUnuk/UI/SavegameMenu.h \
|
../src/libUnuk/UI/SavegameMenu.h \
|
||||||
../src/libUnuk/Engine/Spells.h
|
../src/libUnuk/Engine/Spells.h \
|
||||||
|
../src/libUnuk/Engine/MemManager.h
|
||||||
SOURCES += ../src/libUnuk/Engine/WorldManager.cpp \
|
SOURCES += ../src/libUnuk/Engine/WorldManager.cpp \
|
||||||
../src/libUnuk/Engine/ParticleEmitter.cpp \
|
../src/libUnuk/Engine/ParticleEmitter.cpp \
|
||||||
../src/libUnuk/Engine/NPC.cpp \
|
../src/libUnuk/Engine/NPC.cpp \
|
||||||
../src/libUnuk/Engine/MemManager.cpp \
|
|
||||||
../src/libUnuk/Engine/Collision.cpp \
|
../src/libUnuk/Engine/Collision.cpp \
|
||||||
../src/libUnuk/Engine/Character.cpp \
|
../src/libUnuk/Engine/Character.cpp \
|
||||||
../src/libUnuk/Sprite/TextureManager.cpp \
|
../src/libUnuk/Sprite/TextureManager.cpp \
|
||||||
@ -86,4 +85,5 @@ SOURCES += ../src/libUnuk/Engine/WorldManager.cpp \
|
|||||||
../src/libUnuk/UI/Bar.cpp \
|
../src/libUnuk/UI/Bar.cpp \
|
||||||
../src/libUnuk/System/Vec2.cpp \
|
../src/libUnuk/System/Vec2.cpp \
|
||||||
../src/libUnuk/UI/SavegameMenu.cpp \
|
../src/libUnuk/UI/SavegameMenu.cpp \
|
||||||
../src/libUnuk/Engine/Spells.cpp
|
../src/libUnuk/Engine/Spells.cpp \
|
||||||
|
../src/libUnuk/Engine/MemManager.cpp
|
||||||
|
@ -216,6 +216,7 @@ void Game::HandleInput(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Game::UpdateGame(void) {
|
void Game::UpdateGame(void) {
|
||||||
|
UpdateInput();
|
||||||
if(_ingameMenu.GetStatus() == false) {
|
if(_ingameMenu.GetStatus() == false) {
|
||||||
_map.Update();
|
_map.Update();
|
||||||
_player->Update();
|
_player->Update();
|
||||||
@ -234,10 +235,11 @@ void Game::UpdateGame(void) {
|
|||||||
} else {
|
} else {
|
||||||
// :D
|
// :D
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::Render(void) {
|
void Game::Render(void) {
|
||||||
//SDL_FillRect(screen, NULL, 0); // You might want to clear the buffer! --konom | I don't want a blacked out ingame menu, save it for MainMenu. --Allanis
|
//SDL_FillRect(screen, NULL, 0);
|
||||||
if(_ingameMenu.GetStatus() == false) {
|
if(_ingameMenu.GetStatus() == false) {
|
||||||
_map.Render();
|
_map.Render();
|
||||||
_player->Render();
|
_player->Render();
|
||||||
@ -276,7 +278,7 @@ void Game::NewSavegame(const string savegameIDArg) {
|
|||||||
TiXmlElement* saveElement = new TiXmlElement("save");
|
TiXmlElement* saveElement = new TiXmlElement("save");
|
||||||
|
|
||||||
TiXmlElement* nameElement = new TiXmlElement("name");
|
TiXmlElement* nameElement = new TiXmlElement("name");
|
||||||
TiXmlText* nameText = new TiXmlText("Allanis"); //TODO: replace with _player->GetName() when it works. --konom
|
TiXmlText* nameText = new TiXmlText("Allanis"); //TODO: replace with _player->GetName() when it works.
|
||||||
nameElement->LinkEndChild(nameText);
|
nameElement->LinkEndChild(nameText);
|
||||||
|
|
||||||
int spawnX;
|
int spawnX;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "../libUnuk/UI/EventHistory.h"
|
#include "../libUnuk/UI/EventHistory.h"
|
||||||
|
#include "../libUnuk/System/Input.h"
|
||||||
|
|
||||||
// Pixels * 60 / sec.
|
// Pixels * 60 / sec.
|
||||||
const float Player::PLAYER_SPEED = Character::CHARACTER_SPEED + 0.5f;
|
const float Player::PLAYER_SPEED = Character::CHARACTER_SPEED + 1.0f;
|
||||||
|
|
||||||
// Amount of Exp needed every level
|
// Amount of Exp needed every level
|
||||||
const int Player::EXP_TABLE[MAX_LEVEL] = {
|
const int Player::EXP_TABLE[MAX_LEVEL] = {
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
#include "../libUnuk/UI/SavegameMenu.h"
|
#include "../libUnuk/UI/SavegameMenu.h"
|
||||||
#include "../libUnuk/Engine/NPC.h"
|
#include "../libUnuk/Engine/NPC.h"
|
||||||
#include "../libUnuk/System/Debug.h"
|
#include "../libUnuk/System/Debug.h"
|
||||||
|
#include "../libUnuk/System/Input.h"
|
||||||
#include "../libUnuk/Engine/MemClass.h"
|
#include "../libUnuk/Engine/MemClass.h"
|
||||||
|
|
||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
@ -98,6 +100,10 @@ int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) {
|
|||||||
Debug::logger->message("Creating mainmenu..");
|
Debug::logger->message("Creating mainmenu..");
|
||||||
MainMenu* menu = new MainMenu;
|
MainMenu* menu = new MainMenu;
|
||||||
|
|
||||||
|
// Initiate input.
|
||||||
|
Debug::logger->message("Setting up I/O..");
|
||||||
|
CreateInput();
|
||||||
|
|
||||||
Debug::logger->message("\n----- Engine Initialization Complete -----");
|
Debug::logger->message("\n----- Engine Initialization Complete -----");
|
||||||
Debug::logger->message("\n----- Logic -----");
|
Debug::logger->message("\n----- Logic -----");
|
||||||
|
|
||||||
@ -134,6 +140,7 @@ int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//stringstream caption;
|
//stringstream caption;
|
||||||
//caption << "Unuk - FPS: " << fps;
|
//caption << "Unuk - FPS: " << fps;
|
||||||
|
|
||||||
@ -145,6 +152,8 @@ int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) {
|
|||||||
SDL_FreeSurface(screen);
|
SDL_FreeSurface(screen);
|
||||||
SDL_FreeSurface(errorTexture);
|
SDL_FreeSurface(errorTexture);
|
||||||
|
|
||||||
|
DestroyInput();
|
||||||
|
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
TTF_Quit();
|
TTF_Quit();
|
||||||
|
|
||||||
|
@ -46,21 +46,21 @@ public:
|
|||||||
void OnAttack(void);
|
void OnAttack(void);
|
||||||
|
|
||||||
// Overload new and delete operators to utilize MemManager.
|
// Overload new and delete operators to utilize MemManager.
|
||||||
inline void* operator new(size_t size) {
|
// inline void* operator new(size_t size) {
|
||||||
return gMemManager.Allocate(size);
|
// 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) {
|
// inline void* operator new [](size_t size) {
|
||||||
return gMemManager.Allocate(size);
|
// return gMemManager.Allocate(size);
|
||||||
}
|
// }
|
||||||
|
|
||||||
inline void operator delete [](void* object) {
|
// inline void operator delete [](void* object) {
|
||||||
gMemManager.Free(object);
|
// gMemManager.Free(object);
|
||||||
}
|
// }
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
FACING_UP,
|
FACING_UP,
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "MemManager.h"
|
|
||||||
|
|
||||||
extern MemManager gMemManager;
|
|
||||||
|
|
||||||
class MemClass {
|
|
||||||
public:
|
|
||||||
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(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;
|
|
||||||
// Complex part.
|
|
||||||
double c;
|
|
||||||
};
|
|
@ -1,206 +1,535 @@
|
|||||||
#include "MemClass.h"
|
#include <new>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "MemManager.h"
|
#include "MemManager.h"
|
||||||
|
|
||||||
MemManager gMemManager;
|
|
||||||
|
|
||||||
void BitMapEntry::SetBit(int position, bool flag) {
|
// This is rather C'ish, it can't really be helped since using new/delete inside allocation
|
||||||
blocksAvailable += flag ? 1 : -1;
|
// routines would be, well, no fun. This also excludes SDL containers.
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitMapEntry::SetMultipleBits(int position, bool flag, int count) {
|
// Don't use this here..
|
||||||
blocksAvailable += flag ? count : -count;
|
#ifdef new
|
||||||
int elementNo = position / INT_SIZE;
|
#undef new
|
||||||
int bitNo = position % INT_SIZE;
|
#endif
|
||||||
|
|
||||||
int bitSize = (count <= INT_SIZE - bitNo) ? count : INT_SIZE - bitNo;
|
// We will dump the report here..
|
||||||
SetRangeOfInt(&bitMap[elementNo], bitNo + bitSize - 1, bitNo, flag);
|
const char logFileName[] = "../Bin/MemLeaks.log";
|
||||||
count -= bitSize;
|
|
||||||
if(!count) return;
|
|
||||||
|
|
||||||
int i = ++elementNo;
|
// Longs are guaranteed to be 2 bits.
|
||||||
while(count >= 0) {
|
typedef unsigned long uint32;
|
||||||
if(count <= INT_SIZE) {
|
|
||||||
SetRangeOfInt(&bitMap[i], count - 1, 0, flag);
|
// Identifiers which are placed to allocated buffer (4-byte alignment)
|
||||||
|
const uint32 memPrefix = 0xBAADF00D;
|
||||||
|
const uint32 memPostfix = 0xBABE2BED;
|
||||||
|
const uint32 memNotUsed = 0xDEADC0DE;
|
||||||
|
|
||||||
|
// Identifiers for array / non array allocations / deleted allocations.
|
||||||
|
const uint32 nonArrayAllocation = 0x2BADF00D;
|
||||||
|
const uint32 arrayAllocation = 0xBAD4ACE2;
|
||||||
|
const uint32 invalidAllocation = 0x76543210;
|
||||||
|
|
||||||
|
// Amount. Be careful, this could be a memory overkill.
|
||||||
|
const int numberPrefix = 32; // 128 bytes.
|
||||||
|
const int numberPostfix = 32; // 128 bytes.
|
||||||
|
|
||||||
|
void RemoveMessages(void) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
MSG msg = { 0 };
|
||||||
|
while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||||
|
if(msg.message == WM_PAINT)
|
||||||
return;
|
return;
|
||||||
} else
|
|
||||||
bitMap[i] = flag ? unsigned (-1) : 0;
|
|
||||||
count -= 32;
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitMapEntry::SetRangeOfInt(int* element, int msb, int lsb, bool flag) {
|
struct AllocationUnit {
|
||||||
if(flag) {
|
// Just for convenience.
|
||||||
int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> (INT_SIZE - msb - 1));
|
uint32* prefixPointer;
|
||||||
*element |= mask;
|
uint32* postfixPointer;
|
||||||
} else {
|
uint32* dataPointer;
|
||||||
int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> (INT_SIZE - msb - 1));
|
|
||||||
*element &= ~mask;
|
// Size with and withough manager extras.
|
||||||
}
|
size_t requestedSize;
|
||||||
|
size_t overallSize;
|
||||||
|
|
||||||
|
// Catches mixing new[]/delete and new/delete[] changed from bool to int
|
||||||
|
// to catch problems with memory blocks allocated without using memory manager.
|
||||||
|
int arrayAllocated;
|
||||||
|
|
||||||
|
// Allocation info which may or may not be present.
|
||||||
|
char* allocatedFrom;
|
||||||
|
|
||||||
|
// Allocation was marked during last snapshot, therfore, it will not be shown
|
||||||
|
// at leak snapshot dump.
|
||||||
|
bool markedSnapshot;
|
||||||
|
};
|
||||||
|
|
||||||
|
AllocationUnit* CreateAllocationUnit(void) {
|
||||||
|
AllocationUnit* unit = static_cast<AllocationUnit*> (malloc(sizeof(AllocationUnit)));
|
||||||
|
|
||||||
|
unit->prefixPointer = 0;
|
||||||
|
unit->postfixPointer = 0;
|
||||||
|
unit->dataPointer = 0;
|
||||||
|
|
||||||
|
unit->requestedSize = 0;
|
||||||
|
unit->overallSize = 0;
|
||||||
|
|
||||||
|
unit->arrayAllocated = nonArrayAllocation;
|
||||||
|
unit->allocatedFrom = 0;
|
||||||
|
|
||||||
|
unit->markedSnapshot = false;
|
||||||
|
|
||||||
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemClass* BitMapEntry::FirstFreeBlock(size_t/* size*/) {
|
void deleteAllocationUnit(AllocationUnit* unit) {
|
||||||
for(int i = 0; i < BIT_MAP_ELEMENTS; i++) {
|
if(unit->allocatedFrom)
|
||||||
if(bitMap[i] == 0)
|
free(unit->allocatedFrom);
|
||||||
// There aint any bits free.
|
if(unit->prefixPointer)
|
||||||
continue;
|
free(unit->prefixPointer);
|
||||||
|
unit->arrayAllocated = invalidAllocation;
|
||||||
// Yield the first bit position. This is a 1
|
free(unit);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocation information.
|
||||||
|
|
||||||
|
struct AllocationLink {
|
||||||
|
AllocationUnit* allocationUnit;
|
||||||
|
AllocationLink* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AllocationRoot {
|
||||||
|
AllocationLink* first;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hash data.
|
||||||
|
static const int hashSize = 3677; // Prime number. Big enough?
|
||||||
|
static AllocationRoot hashMap[hashSize] = { 0 };
|
||||||
|
|
||||||
|
static int allocationCount = 0; // Amount of allocations.
|
||||||
|
static int allocationMemory = 0; // Memory allocated.
|
||||||
|
|
||||||
|
static int PeakMemoryUsage = 0;
|
||||||
|
static int peakPointers = 0;
|
||||||
|
|
||||||
|
int CalculateHashIndex(const void* buffer) {
|
||||||
|
int value = reinterpret_cast<int> (buffer);
|
||||||
|
// Shift lower bits (alignment would kill coverage).
|
||||||
|
value >>= 4;
|
||||||
|
|
||||||
|
// Create index.
|
||||||
|
value %= hashSize;
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddAllocation(AllocationUnit* allocation) {
|
||||||
|
assert(allocation);
|
||||||
|
|
||||||
|
++allocationCount;
|
||||||
|
allocationMemory += allocation->requestedSize;
|
||||||
|
|
||||||
|
AllocationLink* link = static_cast<AllocationLink*> (malloc(sizeof(AllocationLink)));
|
||||||
|
link->allocationUnit = allocation;
|
||||||
|
link->next = 0;
|
||||||
|
|
||||||
|
int hashIndex = CalculateHashIndex(allocation->dataPointer);
|
||||||
|
if(hashMap[hashIndex].first == 0)
|
||||||
|
hashMap[hashIndex].first = link;
|
||||||
|
else {
|
||||||
|
// Push front.
|
||||||
|
link->next = hashMap[hashIndex].first;
|
||||||
|
hashMap[hashIndex].first = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(allocationMemory > PeakMemoryUsage)
|
||||||
|
PeakMemoryUsage = allocationMemory;
|
||||||
|
if(allocationCount > peakPointers)
|
||||||
|
peakPointers = allocationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocationUnit* FindAllocation(void* pointer) {
|
||||||
|
int hashIndex = CalculateHashIndex(pointer);
|
||||||
|
AllocationLink* current = hashMap[hashIndex].first;
|
||||||
|
|
||||||
|
while(current) {
|
||||||
|
if(current->allocationUnit->dataPointer == pointer)
|
||||||
|
return current->allocationUnit;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveMessages();
|
||||||
|
assert(!"Allocation not found. Uninitialized pointer?");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemClass* BitMapEntry::ComplexObjectAddress(int pos) {
|
void RemoveAllocation(AllocationUnit* allocation) {
|
||||||
SetBit(pos, false);
|
if(allocationCount <= 0) {
|
||||||
return &((static_cast<MemClass*>(Head()) + (pos / INT_SIZE)) [INT_SIZE - (pos % INT_SIZE + 1)]);
|
RemoveMessages();
|
||||||
|
assert(allocationCount > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* BitMapEntry::Head(void) {
|
int hashIndex = CalculateHashIndex(allocation->dataPointer);
|
||||||
return gMemManager.GetMemoryPoolList()[index];
|
|
||||||
|
AllocationLink* current = hashMap[hashIndex].first;
|
||||||
|
AllocationLink* previous = 0;
|
||||||
|
|
||||||
|
while(current) {
|
||||||
|
if(current->allocationUnit == allocation) {
|
||||||
|
// Remove.
|
||||||
|
if(previous)
|
||||||
|
previous->next = current->next;
|
||||||
|
else
|
||||||
|
hashMap[hashIndex].first = current->next;
|
||||||
|
|
||||||
|
--allocationCount;
|
||||||
|
allocationMemory -= current->allocationUnit->requestedSize;
|
||||||
|
|
||||||
|
// Free memory.
|
||||||
|
deleteAllocationUnit(current->allocationUnit);
|
||||||
|
free(current);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
RemoveMessages();
|
||||||
|
assert(!"Allocation not found. Uninitialized pointer?");
|
||||||
}
|
}
|
||||||
|
|
||||||
void* MemManager::Allocate(size_t size) {
|
void DumpLeakReport(void) {
|
||||||
// None array.
|
if(allocationCount > 0) {
|
||||||
if(size == sizeof(MemClass)) {
|
DumpLeakSnapshot(true);
|
||||||
set<BitMapEntry*>::iterator freeMapI = _freeMapEntries.begin();
|
|
||||||
if(freeMapI != _freeMapEntries.end()) {
|
|
||||||
BitMapEntry* mapEntry = *freeMapI;
|
|
||||||
return mapEntry->FirstFreeBlock(size);
|
|
||||||
} else {
|
} else {
|
||||||
AllocateChunkAndInitBitMap();
|
// Remove file.
|
||||||
_freeMapEntries.insert(&(_bitMapEntryList[_bitMapEntryList.size() - 1]));
|
fclose(fopen(logFileName, "wt"));
|
||||||
return _bitMapEntryList[_bitMapEntryList.size() - 1].FirstFreeBlock(size);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestIdentifiers(AllocationUnit* allocation) {
|
||||||
|
for(int i = 0; i < numberPrefix; ++i) {
|
||||||
|
if(allocation->prefixPointer[i] != memPrefix) {
|
||||||
|
RemoveMessages();
|
||||||
|
assert(!"Buffer prefix messed up!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i = 0; i < numberPostfix; ++i) {
|
||||||
|
if(allocation->postfixPointer[i] != memPostfix) {
|
||||||
|
RemoveMessages();
|
||||||
|
assert(!"Buffer postfix messed up!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// After deinitialization, dump leak report on every deallocation.
|
||||||
|
struct InitializationTracker {
|
||||||
|
static bool programExiting;
|
||||||
|
|
||||||
|
InitializationTracker(void) {
|
||||||
|
programExiting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
~InitializationTracker(void) {
|
||||||
|
programExiting = true;
|
||||||
|
DumpLeakReport();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool InitializationTracker::programExiting = false;
|
||||||
|
static InitializationTracker tracker;
|
||||||
|
|
||||||
|
void MarkLeakSnapshot(void) {
|
||||||
|
if(allocationCount > 0) {
|
||||||
|
int currentIndex = 0;
|
||||||
|
for(int i = 0; i < hashSize; ++i) {
|
||||||
|
AllocationLink* currentLink = hashMap[i].first;
|
||||||
|
while(currentLink != 0) {
|
||||||
|
currentLink->allocationUnit->markedSnapshot = true;
|
||||||
|
currentLink = currentLink->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpLeakSnapshot(bool fromStart) {
|
||||||
|
if(allocationCount > 0) {
|
||||||
|
FILE* fp = fopen(logFileName, "wt");
|
||||||
|
if(fp == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!fromStart)
|
||||||
|
fprintf(fp, "(SNAPSHOT)\n\n");
|
||||||
|
fprintf(fp, "Peak memory usage: %d bytes\n", PeakMemoryUsage);
|
||||||
|
fprintf(fp, "Overall memory leaked: %d bytes\n", allocationMemory);
|
||||||
|
fprintf(fp, "Pointers left: %d\n\n", allocationCount);
|
||||||
|
|
||||||
|
int currentIndex = 0;
|
||||||
|
for(int i = 0; i < hashSize; ++i) {
|
||||||
|
AllocationLink* currentLink = hashMap[i].first;
|
||||||
|
while(currentLink != 0) {
|
||||||
|
if(!currentLink->allocationUnit->markedSnapshot || fromStart) {
|
||||||
|
//if(strcmp(currentLink->allocationUnit->allocatedFrom, "(???: line 0)") != 0)
|
||||||
|
if(!strstr(currentLink->allocationUnit->allocatedFrom, "???")) {
|
||||||
|
// Temp: show only over 2MB
|
||||||
|
//if(currentLink->allocationUnit->requestedSize > 1*1024*1024) {
|
||||||
|
fprintf(fp, "Allocation %d:\n", ++currentIndex);
|
||||||
|
fprintf(fp, "\tAllocated from: %s\n", currentLink->allocationUnit->allocatedFrom);
|
||||||
|
fprintf(fp, "\tAllocation size: %d bytes\n", currentLink->allocationUnit->requestedSize);
|
||||||
|
if(currentLink->allocationUnit->arrayAllocated == nonArrayAllocation)
|
||||||
|
fprintf(fp, "\tAllocated with new()\n");
|
||||||
|
else
|
||||||
|
fprintf(fp, "\tAllocated with new[]\n");
|
||||||
|
|
||||||
|
// To get the contents of some char array strings.
|
||||||
|
#define MEMMANAGER_MAX_PRINT_SIZE 80
|
||||||
|
int arraySize = currentLink->allocationUnit->requestedSize;
|
||||||
|
if(currentLink->allocationUnit->arrayAllocated == arrayAllocation && arraySize < MEMMANAGER_MAX_PRINT_SIZE) {
|
||||||
|
char* data = (char*)currentLink->allocationUnit->requestedSize;
|
||||||
|
char databuf[MEMMANAGER_MAX_PRINT_SIZE + 2];
|
||||||
|
bool noControlChars = true;
|
||||||
|
int j;
|
||||||
|
for(j = 0; j < arraySize; j++) {
|
||||||
|
if(data[j] == '\n' || data[j] == '\r')
|
||||||
|
databuf[j] = ' ';
|
||||||
|
else
|
||||||
|
databuf[j] = data[j];
|
||||||
|
if(data[j] < 32 && data[j] != '\n' && data[j] != '\r') {
|
||||||
|
if(data[j] != '\0') noControlChars = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
databuf[j] != '\0';
|
||||||
|
if(noControlChars) {
|
||||||
|
fprintf(fp, "\tData: \"%s\"\n", data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentLink = currentLink->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char debugAllocInfo[256 + 1] = { 0 };
|
||||||
|
int debugAllocatedSinceInfo = -1;
|
||||||
|
// Just a hack to add extra info to allocations.
|
||||||
|
void DebugSetAllocationInfo(const char* allocationInfo) {
|
||||||
|
if(allocationInfo == NULL)
|
||||||
|
debugAllocInfo[0] = '\0';
|
||||||
|
else
|
||||||
|
strncpy(debugAllocInfo, allocationInfo, 256);
|
||||||
|
debugAllocatedSinceInfo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operator new implementation.
|
||||||
|
void* operator new(size_t originalSize, const char* filename, int lineNumber, bool arrayAllocated) {
|
||||||
|
// Handle 0-byte request. we must return a unique pointer
|
||||||
|
// (or unique value actually).
|
||||||
|
if(originalSize == 0)
|
||||||
|
originalSize = 1;
|
||||||
|
|
||||||
|
// To 4-byte boundary (since our identifiers are unit32's).
|
||||||
|
if(int foo = originalSize % 4)
|
||||||
|
originalSize += 4 - foo;
|
||||||
|
|
||||||
|
// Make some room for prefix and postfix.
|
||||||
|
size_t size = originalSize;
|
||||||
|
size += numberPrefix * 4;
|
||||||
|
size += numberPostfix * 4;
|
||||||
|
|
||||||
|
// Yes, Infinate loop really is the way to go :)
|
||||||
|
while(true) {
|
||||||
|
AllocationUnit* allocation = CreateAllocationUnit();
|
||||||
|
void* buffer = malloc(size);
|
||||||
|
|
||||||
|
// Both have to succeed. We want to handle out-of-memory.
|
||||||
|
if((buffer) && (allocation)) {
|
||||||
|
char* info;
|
||||||
|
if(debugAllocInfo[0] != '\0' && debugAllocatedSinceInfo >= 0) {
|
||||||
|
info = static_cast<char*>(malloc(strlen(filename) + strlen(debugAllocInfo) + 60));
|
||||||
|
if(info) {
|
||||||
|
if(debugAllocatedSinceInfo == 0)
|
||||||
|
sprintf(info, "(%s: line %d)\t Info: \"%s\"", filename, lineNumber, debugAllocInfo);
|
||||||
|
else
|
||||||
|
sprintf(info, "(%s: line %d)\n\tInfo: (\"%s\", %d allocs ago)", filename, lineNumber, debugAllocInfo, debugAllocatedSinceInfo);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Array.
|
info = static_cast<char*> (malloc(strlen(filename) + 20));
|
||||||
if(_arrayMemoryList.empty()) {
|
if(info) {
|
||||||
return AllocateArrayMemory(size);
|
sprintf(info, "(%s: line %d)", filename, lineNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in allocation info.
|
||||||
|
allocation->prefixPointer = static_cast<uint32*> (buffer);
|
||||||
|
allocation->dataPointer = allocation->prefixPointer + numberPrefix;
|
||||||
|
allocation->postfixPointer = allocation->dataPointer + (originalSize / 4);
|
||||||
|
|
||||||
|
allocation->allocatedFrom = info;
|
||||||
|
if(arrayAllocated)
|
||||||
|
allocation->arrayAllocated = arrayAllocation;
|
||||||
|
else
|
||||||
|
allocation->arrayAllocated = nonArrayAllocation;
|
||||||
|
allocation->overallSize = size;
|
||||||
|
allocation->requestedSize = originalSize;
|
||||||
|
|
||||||
|
// Fill in our identifiers.
|
||||||
|
for(int i = 0; i < numberPrefix; ++i)
|
||||||
|
allocation->prefixPointer[i] = memPrefix;
|
||||||
|
for(int i = 0; i < int(originalSize / 4); ++i)
|
||||||
|
allocation->dataPointer[i] = memNotUsed;
|
||||||
|
for(int i = 0; i < numberPostfix; ++i)
|
||||||
|
allocation->postfixPointer[i] = memPostfix;
|
||||||
|
|
||||||
|
AddAllocation(allocation);
|
||||||
|
return allocation->dataPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If only one of them succeeded, free it first.
|
||||||
|
if(buffer)
|
||||||
|
free(buffer);
|
||||||
|
if(allocation)
|
||||||
|
deleteAllocationUnit(allocation);
|
||||||
|
|
||||||
|
// Test error-handling functions.
|
||||||
|
std::new_handler globalHandler = std::set_new_handler(0);
|
||||||
|
std::set_new_handler(globalHandler);
|
||||||
|
|
||||||
|
// If we have one, try it. otherwise throw a bad allocation.
|
||||||
|
// (And hope for someone to catch it).
|
||||||
|
if(globalHandler)
|
||||||
|
(*globalHandler) ();
|
||||||
|
else
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* buffer, bool arrayDeleted) throw() {
|
||||||
|
// Deleting null-pointer is legal.
|
||||||
|
if(buffer == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AllocationUnit* allocation = FindAllocation(buffer);
|
||||||
|
if(!allocation) {
|
||||||
|
RemoveMessages();
|
||||||
|
assert(allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test out of bounds.
|
||||||
|
TestIdentifiers(allocation);
|
||||||
|
|
||||||
|
// Test that the block was allocated by memory manager.
|
||||||
|
// Test array operator mixing.
|
||||||
|
if(allocation->arrayAllocated != arrayAllocation && allocation->arrayAllocated != nonArrayAllocation) {
|
||||||
|
RemoveMessages();
|
||||||
|
assert(!"Deleting block with invalid allocation type");
|
||||||
} else {
|
} else {
|
||||||
map<void*, ArrayMemoryInfo>::iterator infoI = _arrayMemoryList.begin();
|
if((arrayDeleted && allocation->arrayAllocated == nonArrayAllocation) || (!arrayDeleted && allocation->arrayAllocated == arrayAllocation)) {
|
||||||
map<void*, ArrayMemoryInfo>::iterator infoEndI = _arrayMemoryList.end();
|
RemoveMessages();
|
||||||
|
assert(!"Mixed array and normal versions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RemoveAllocation(allocation);
|
||||||
|
|
||||||
while(infoI != infoEndI) {
|
// If quitting, dump report on each deallocation.
|
||||||
ArrayMemoryInfo info = (*infoI).second;
|
if(InitializationTracker::programExiting == true)
|
||||||
if(info.StartPosition != 0)
|
DumpLeakReport();
|
||||||
// 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;
|
void* operator new(size_t size, const char* filename, int lineNumber) throw(std::bad_alloc) {
|
||||||
SetMultipleBlockBits(&info, false);
|
return operator new(size, filename, lineNumber, false);
|
||||||
|
}
|
||||||
|
void* operator new(size_t size) throw(std::bad_alloc) {
|
||||||
|
return operator new(size, "???", 0, false);
|
||||||
|
}
|
||||||
|
void* operator new[](size_t size, const char* filename, int lineNumber) throw(std::bad_alloc) {
|
||||||
|
return operator new(size, filename, lineNumber, true);
|
||||||
|
}
|
||||||
|
void* operator new[](size_t size) throw(std::bad_alloc) {
|
||||||
|
return operator new(size, "???", 0 , true);
|
||||||
|
}
|
||||||
|
void operator delete(void* buffer) throw() {
|
||||||
|
operator delete(buffer, false);
|
||||||
|
}
|
||||||
|
void operator delete[](void* buffer) throw() {
|
||||||
|
operator delete(buffer, true);
|
||||||
|
}
|
||||||
|
|
||||||
return baseAddress;
|
void MemManager::SetFailingPercentage(int percentage) {
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
void MemManager::ValidatePointer(void* pointer) {
|
||||||
|
AllocationUnit* allocation = FindAllocation(pointer);
|
||||||
|
if(!allocation) {
|
||||||
|
RemoveMessages();
|
||||||
|
assert(allocation);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Test out-of-bounds.
|
||||||
|
TestIdentifiers(allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemManager::ValidateAllPointers(void) {
|
||||||
|
for(int i = 0; i < hashSize; ++i) {
|
||||||
|
AllocationLink* currentLink = hashMap[i].first;
|
||||||
|
while(currentLink != 0) {
|
||||||
|
if(currentLink)
|
||||||
|
TestIdentifiers(currentLink->allocationUnit);
|
||||||
|
|
||||||
|
currentLink = currentLink->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MemManager::AmountOfMemoryAllocated(void* pointer, bool includeManagerExtra) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* MemManager::AllocateArrayMemory(size_t size) {
|
int MemManager::AmountOfMemoryInUse(void* pointer) {
|
||||||
void* chunkAddress = AllocateChunkAndInitBitMap();
|
int result = 0;
|
||||||
ArrayMemoryInfo info;
|
|
||||||
info.memPoolListIndex = _memoryPoolList.size() - 1;
|
for(int i = 0; i < hashSize; ++i) {
|
||||||
info.StartPosition = 0;
|
AllocationLink* currentLink = hashMap[i].first;
|
||||||
info.Size = size / sizeof(MemClass);
|
while(currentLink != 0) {
|
||||||
_arrayMemoryList[chunkAddress] = info;
|
if(currentLink)
|
||||||
SetMultipleBlockBits(&info, false);
|
result += currentLink->allocationUnit->requestedSize;
|
||||||
return chunkAddress;
|
currentLink = currentLink->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* MemManager::AllocateChunkAndInitBitMap(void) {
|
void MemManager::LogStatistics(const char* filename) {
|
||||||
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) {
|
void MemManager::LogUnusedPointers(const char* filename, float freePercentage) {
|
||||||
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 MemManager::AmountOfMemoryInUse(bool includeManagerExta) {
|
||||||
int i = _bitMapEntryList.size() - 1;
|
return allocationMemory;
|
||||||
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) {
|
int MemManager::AmountOfPeakMemoryInUse(bool includeManagerExtra) {
|
||||||
BitMapEntry* mapEntry = &_bitMapEntryList[info->memPoolListIndex];
|
return 0;
|
||||||
mapEntry->SetMultipleBits(info->StartPosition, flag, info->Size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<void*>& MemManager::GetMemoryPoolList(void) {
|
int MemManager::AmountOfMemoryAllocations(void) {
|
||||||
return _memoryPoolList;
|
return allocationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MemManager::AmountOfPeakMemoryAllocations(void) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,88 +1,53 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <string.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
#include <bitset>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
const int BIT_MAP_SIZE = 1024;
|
#ifndef INCLUDED_NEW
|
||||||
const int INT_SIZE = sizeof(int) * 8;
|
#define INCLUDED_NEW
|
||||||
const int BIT_MAP_ELEMENTS = BIT_MAP_SIZE / INT_SIZE;
|
#include <new>
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
class MemManager {
|
||||||
* Memory Allocation Pattern.
|
// Not implemented.
|
||||||
* 11111111 11111111 11111111
|
MemManager(void);
|
||||||
* 11111110 11111111 11111111
|
~MemManager(void);
|
||||||
* 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:
|
public:
|
||||||
BitMapEntry():blocksAvailable(BIT_MAP_SIZE) {
|
// Affect behavior.
|
||||||
// All blocks are free to begin with and bit value 1
|
static void SetFailingPercentage(int percentage);
|
||||||
// in the map denotes available blocks.
|
|
||||||
memset(bitMap, 0xff, BIT_MAP_SIZE / sizeof(char));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetBit(int position, bool flag);
|
// Pointers.
|
||||||
void SetMultipleBits(int position, bool flag, int count);
|
static void ValidatePointer(void* pointer);
|
||||||
void SetRangeOfInt(int* element, int msb, int lsb, bool flag);
|
static void ValidateAllPointers(void);
|
||||||
MemClass* FirstFreeBlock(size_t size);
|
static int AmountOfMemoryAllocated(void* pointer, bool includeManagerExtra = false);
|
||||||
MemClass* ComplexObjectAddress(int pos);
|
static int AmountOfMemoryInUse(void* pointer);
|
||||||
void* Head(void);
|
|
||||||
} BitMapEntry;
|
|
||||||
|
|
||||||
typedef struct ArrayInfo {
|
// Logging.
|
||||||
int memPoolListIndex;
|
static void LogStatistics(const char* filename);
|
||||||
int StartPosition;
|
static void LogUnusedPointers(const char* filename, float freePercentage);
|
||||||
int Size;
|
|
||||||
} ArrayMemoryInfo;
|
|
||||||
|
|
||||||
class IMemManager {
|
// Memory statistics.
|
||||||
public:
|
static int AmountOfMemoryInUse(bool includeManagerExta = false);
|
||||||
virtual void* Allocate(size_t size) = 0;
|
static int AmountOfPeakMemoryInUse(bool includeManagerExtra = false);
|
||||||
virtual void Free(void* object) = 0;
|
static int AmountOfMemoryAllocations(void);
|
||||||
|
static int AmountOfPeakMemoryAllocations(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemManager : public IMemManager {
|
// Quick hack to get some extra information about allocations.
|
||||||
public:
|
void DebugSetAllocationInfo(const char* allocationInfo);
|
||||||
MemManager(void) {}
|
void DumpLeakSnapshot(bool fromStart = false);
|
||||||
~MemManager(void) {}
|
void MarkLeakSnapshot(void);
|
||||||
|
|
||||||
void* Allocate(size_t size);
|
// Global operators.
|
||||||
void Free(void* object);
|
void* operator new(size_t size, const char* filename, int lineNumber) throw(std::bad_alloc);
|
||||||
vector<void*>& GetMemoryPoolList(void);
|
void* operator new(size_t size) throw(std::bad_alloc);
|
||||||
|
void* operator new[](size_t size, const char* filename, int lineNumber) throw(std::bad_alloc);
|
||||||
|
void* operator new[](size_t size) throw(std::bad_alloc);
|
||||||
|
void operator delete(void* buffer) throw();
|
||||||
|
void operator delete[](void* buffer) throw();
|
||||||
|
|
||||||
private:
|
// I don't think there are any compilers that don't define these, but just in case.
|
||||||
void* AllocateArrayMemory(size_t size);
|
#ifndef __FILE__
|
||||||
void* AllocateChunkAndInitBitMap(void);
|
#define __FILE__ "???"
|
||||||
void SetBlockBit(void* object, bool flag);
|
#endif
|
||||||
void SetMultipleBlockBits(ArrayMemoryInfo* info, bool flag);
|
#ifndef __LINE__
|
||||||
|
#define __LINE__ 0
|
||||||
// The following lists will maintain one to one correspondace
|
#endif
|
||||||
// and should be the same size.
|
|
||||||
vector<void*> _memoryPoolList;
|
|
||||||
vector<BitMapEntry> _bitMapEntryList;
|
|
||||||
|
|
||||||
set<BitMapEntry*> _freeMapEntries;
|
|
||||||
map<void*, ArrayMemoryInfo> _arrayMemoryList;
|
|
||||||
};
|
|
||||||
|
@ -31,6 +31,9 @@ bool CreateInput(void) {
|
|||||||
|
|
||||||
memcpy(keyboard.keys, tempKeys, sizeof(char) * keyboard.keycount);
|
memcpy(keyboard.keys, tempKeys, sizeof(char) * keyboard.keycount);
|
||||||
mouse.buttons = SDL_GetMouseState(&mouse.dx, &mouse.dy);
|
mouse.buttons = SDL_GetMouseState(&mouse.dx, &mouse.dy);
|
||||||
|
if(&keyboard > 0 || &mouse > 0){
|
||||||
|
Debug::logger->message("Input device registered");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,4 +82,5 @@ bool MouseStillUp(int button) { return(!_curr_mouse(button) && !_old_mouse(b
|
|||||||
void DestroyInput(void) {
|
void DestroyInput(void) {
|
||||||
free(keyboard.keys);
|
free(keyboard.keys);
|
||||||
free(keyboard.oldKeys);
|
free(keyboard.oldKeys);
|
||||||
|
Debug::logger->message("Input device destroyed");
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SDL/SDL.h>
|
#include <SDL/SDL.h>
|
||||||
|
|
||||||
|
#include "../System/Debug.h"
|
||||||
|
|
||||||
typedef struct mouse_s {
|
typedef struct mouse_s {
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
int oldx, oldy;
|
int oldx, oldy;
|
||||||
|
Loading…
Reference in New Issue
Block a user