Last active
May 26, 2017 22:55
-
-
Save braustin20/2388d753abad8b6e47d0c5d31d93a5b1 to your computer and use it in GitHub Desktop.
Experimenting with custom memory management
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "MemoryManager.h" | |
namespace MemoryManager | |
{ | |
//Helper functions to help determine allocation sizes | |
int convertSize(int x); | |
int calcSize(int right, int left); | |
const int MM_POOL_SIZE = 65536; | |
char MM_pool[MM_POOL_SIZE]; | |
// Initialize set up any data needed to manage the memory pool | |
void initializeMemoryManager(void) | |
{ | |
//Set the entire pool to null at start | |
for (int x = 0; x < MM_POOL_SIZE; x++) | |
{ | |
MM_pool[x] = '\0'; | |
} | |
} | |
// return a pointer inside the memory pool | |
// If no chunk can accommodate aSize call onOutOfMemory() | |
void* allocate(int aSize) | |
{ | |
//Check available size and max size to ensure we have enough space | |
if (aSize >= (MM_POOL_SIZE) || aSize >= largestFree()) | |
{ | |
onOutOfMemory(); | |
return nullptr; | |
} | |
else | |
{ | |
int first = 0; | |
int current = 0; | |
//Iterate through the pool to find available spaces | |
for (int x = 0; x < MM_POOL_SIZE; x++) | |
{ | |
//Increment through to calculate length of contiguous empty chunks | |
if (MM_pool[x] == '\0') | |
{ | |
if (current == 0) | |
{ | |
first = x; | |
} | |
current++; | |
} | |
//If we find a filled chunk, read it's size value so that we can skip over it | |
else | |
{ | |
current = 0; | |
//Size is calculated from first two bytes of the chunk | |
int size_r = (int)MM_pool[x]; | |
int size_l = (int)MM_pool[x + 1]; | |
//Skip over this chunk since we know how big it is | |
x = (x + 1) + calcSize(size_l, size_r); | |
} | |
//If current is larger than the necessary size, use | |
if (current >= aSize + 2) | |
{ | |
break; | |
} | |
} | |
//Fill the chunk with default data | |
for (int x = first + 2; x < first + 2 + aSize; x++) | |
{ | |
MM_pool[x] = 'A'; | |
} | |
//Set the size values for reference later | |
MM_pool[first] = (char)((int)((aSize + 1) / 256) + 1); | |
MM_pool[first + 1] = (char)((aSize - ((int)MM_pool[first] - 1) * 256) + 1); | |
//Return a pointer to the start of the chunk following the size value | |
return ((void*)(MM_pool + first + 2)); | |
} | |
return ((void*) 0); | |
} | |
// Free up a chunk previously allocated | |
void deallocate(void* aPointer) | |
{ | |
if (aPointer == nullptr) | |
{ | |
onIllegalOperation("Pointer is already null, cannot deallocate"); | |
} | |
else | |
{ | |
//Get the size values from the start of the memory chunk | |
int x1 = (int)(*((char*)aPointer - 1)); | |
int x2 = ((int)(*((char*)aPointer - 2))); | |
int x = calcSize(x1, x2); | |
//Replace the entirety of the chunk with null values | |
int i = 0; | |
while (x > i) | |
{ | |
*((char*)aPointer + i) = '\0'; | |
i++; | |
} | |
//Empty the size values | |
*((char*)aPointer - 1) = '\0'; | |
*((char*)aPointer - 2) = '\0'; | |
} | |
} | |
//--- | |
//--- support routines | |
//--- | |
// Will scan the memory pool and return the total free space remaining | |
int freeRemaining(void) | |
{ | |
//Iterate through the pool and find total non-contiguous free space by counting null entries | |
int remaining = 0; | |
for (int x = 0; x < MM_POOL_SIZE; x++) | |
{ | |
if (MM_pool[x] == '\0') | |
{ | |
remaining++; | |
} | |
else | |
{ | |
//If we found a non-null character, read the size values and skip to end of chunk | |
int size_r = (int)MM_pool[x]; | |
int size_l = (int)MM_pool[x + 1]; | |
x = x + 1 + calcSize(size_l, size_r); | |
} | |
} | |
return remaining; | |
} | |
// Will scan the memory pool and return the largest free space remaining | |
int largestFree(void) | |
{ | |
int largest = 0; | |
int current = 0; | |
for (int x = 0; x < MM_POOL_SIZE; x++) | |
{ | |
//Increment current for each null found | |
if (MM_pool[x] == '\0') | |
{ | |
current++; | |
//Set largest value if we've found a new biggest chunk | |
if (current > largest) | |
{ | |
largest = current; | |
} | |
} | |
else | |
{ | |
//If we found a non-null character, read the size values and skip to end of chunk | |
current = 0; | |
int size_r = (int)MM_pool[x]; | |
int size_l = (int)MM_pool[x + 1]; | |
x = x + 1 + calcSize(size_l, size_r); | |
} | |
} | |
return largest; | |
} | |
// will scan the memory pool and return the smallest free space remaining | |
int smallestFree(void) | |
{ | |
//Start with the largest maximum size | |
int smallest = MM_POOL_SIZE; | |
int current = 0; | |
for (int x = 0; x < MM_POOL_SIZE; x++) | |
{ | |
//Increment current for each null found | |
if (MM_pool[x] == '\0') | |
{ | |
current++; | |
//Set smallest value if we've found a new smallest chunk | |
if (current < smallest) | |
{ | |
smallest = current; | |
} | |
} | |
else | |
{ | |
//If we found a non-null character, read the size values and skip to end of chunk | |
current = 0; | |
int size_r = (int)MM_pool[x]; | |
int size_l = (int)MM_pool[x + 1]; | |
x = x + 1 + calcSize(size_l, size_r); | |
} | |
} | |
return smallest; | |
} | |
//Make sure size is not a negative number, offset if so | |
int convertSize(int x) | |
{ | |
if (x < 0) | |
{ | |
x = 256 + x; | |
} | |
return x; | |
} | |
//Get the total size of a single allocation | |
int calcSize(int right, int left) | |
{ | |
//Convert characters to correct integer values | |
right = convertSize(right); | |
left = convertSize(left); | |
//Get the total allocation size of the chunk | |
int r = (right - 1) + (left - 1) * 256; | |
return r; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#ifndef __MEMORY_MANAGER_H__ | |
#define __MEMORY_MANAGER_H__ | |
namespace MemoryManager | |
{ | |
// Initialize any data needed to manage the memory pool | |
void initializeMemoryManager(void); | |
// return a pointer inside the memory pool | |
// If no chunk can accommodate aSize call OnAllocFail() | |
void* allocate(int aSize); | |
// Free up a chunk previously allocated | |
void deallocate(void* aPointer); | |
//--- | |
//--- support routines | |
//--- | |
// Will scan the memory pool and return the total free space remaining | |
int freeRemaining(void); | |
// Will scan the memory pool and return the largest free space remaining | |
int largestFree(void); | |
// will scan the memory pool and return the smallest free space remaining | |
int smallestFree(void); | |
// Call if no space is left for the allocation request | |
void onOutOfMemory(void); | |
// If the caller makes any illegal request your code should call this | |
// provided failure function (which will not return): | |
void onIllegalOperation(const char* fmt,...); | |
// eg: | |
// int errorCode; | |
// ... | |
// onIllegalOperation("Error in createQueue: %d", errorCode); | |
}; | |
#endif // __MEMORY_MANAGER_H__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment