Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Experimenting with custom memory management
#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;
}
}
#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