-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMemoryAllocators.cpp
More file actions
136 lines (114 loc) · 3.06 KB
/
MemoryAllocators.cpp
File metadata and controls
136 lines (114 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "MemoryAllocators.h"
#include <malloc.h>
#include <string.h>
#include <cstdio>
void (*Mem::errorCallback)(const char* inErrorMessage) = nullptr;
using namespace Mem;
void BumpAllocator::Create(size_t inMaxSize)
{
mMaxSize = inMaxSize;
mMemory = (char*)malloc(mMaxSize);
Reset();
}
void BumpAllocator::Destroy()
{
free(mMemory);
}
void* BumpAllocator::Alloc(size_t inSize)
{
if (mStackPtr + inSize > mMaxSize)
{
if (errorCallback != nullptr)
{
char errorMessage[512];
snprintf(errorMessage, sizeof(errorMessage), "Bump Allocator Error: Failed to allocate memory, the size of the requested allocation (%zu) is bigger than the remaining size left in the allocator (%zu).\n", inSize, mMaxSize - mStackPtr);
errorCallback(errorMessage);
}
return nullptr;
}
void* requestedMemory = mMemory + mStackPtr;
mStackPtr += inSize;
return requestedMemory;
}
void BumpAllocator::Reset()
{
mStackPtr = 0;
}
void PoolAllocator::Create(size_t inElementSize, size_t inMaxElements)
{
if (mMemory == nullptr)
{
if (errorCallback != nullptr)
{
errorCallback("Pool Allocator Error: Failed to create memory pool, a memory pool has already been created.");
}
return;
}
mElementSize = inElementSize;
mMaxElements = inMaxElements;
mCellUsage = (bool*)malloc(mMaxElements);
mMemory = (char*)malloc(mElementSize * mMaxElements);
Reset();
}
void PoolAllocator::Destroy()
{
free(mMemory);
free(mCellUsage);
}
PoolAllocator::~PoolAllocator()
{
Destroy();
}
PoolAllocator::Allocation PoolAllocator::Alloc()
{
for (size_t i = 0; i < mMaxElements; i++)
{
if (mCellUsage[i] == false)
{
mCellUsage[i] = true;
return Allocation{ mMemory + (mElementSize * i), i };
}
}
if (errorCallback != nullptr)
errorCallback("Pool Allocator Error: Failed to allocate memory, there are no more free cells in the memory pool.\n");
// mCellIdx is set to mMaxElements + 1 so the user doesn't accidentally free memory used by another if he doesnt acknowledge that the allocation failed.. this is checked by Free()
return Allocation{ nullptr, mMaxElements + 1 };
}
void PoolAllocator::Free(const Allocation& inAllocation)
{
if (inAllocation.mCellIdx >= mMaxElements || inAllocation.mMemory == nullptr)
{ // the user is trying to free memory that does not exist..
if (errorCallback != nullptr)
{
errorCallback("Pool Allocator Error: Failed to free memory, attempted to free memory that does not exist.\n");
}
return;
}
mCellUsage[inAllocation.mCellIdx] = false;
}
void PoolAllocator::Reset()
{
memset(mCellUsage, false, mMaxElements);
}
size_t PoolAllocator::GetNumFreeCells() const
{
size_t numRemainingElements = 0;
for (size_t i = 0; i < mMaxElements; i++)
if (mCellUsage[i] == 0)
numRemainingElements++;
return numRemainingElements;
}
bool PoolAllocator::IsFull() const
{
for (size_t i = 0; i < mMaxElements; i++)
if (mCellUsage[i] == 0)
return false;
return true;
}
void PoolAllocator::PrintUsage() const
{
printf("Memory Pool Usage: [");
for (size_t i = 0; i < mMaxElements; i++)
printf("%s", mCellUsage[i] == true ? "#" : ".");
printf("]\n");
}