-
Notifications
You must be signed in to change notification settings - Fork 0
/
MemoryManager.h
97 lines (75 loc) · 2.48 KB
/
MemoryManager.h
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
#ifndef MEMORY_MANAGER_H_
#define MEMORY_MANAGER_H_
#include <vector>
#include <list>
#include <iostream>
struct MemoryChunk {
unsigned int leftIndex;
unsigned int rightIndex;
unsigned int size;
bool operator < (const MemoryChunk& m2) {
return leftIndex < m2.leftIndex;
}
};
/*
* Memory Manager:
* The goal of this class is to optimize cache performance and avoid the usage of 'new'
* outside of this class. Currently has 10mb buffers and cannot switch to a new buffer
* when full.
*/
namespace MemoryManager {
// Functions/Variables only useable by functions within namespace
namespace detail {
// buffers on heap
extern std::vector<unsigned char*> memoryArrays;
extern std::vector<std::list<MemoryChunk> > freeChunks;
// 10mb
const unsigned int memBlockSize = 104857600;
// If you are bigger than 10kb...
const unsigned int margin = 10240;
extern int leftIndex;
extern int rightIndex;
// Sort and merge possible free memory chunks for later use
void SortAndMerge();
}
void Init();
void CleanUp();
// Allocate space for an object of size
void* Malloc(size_t size);
// Templated Allocation/Free functions for non-vector types
// Allocate memory of the specified size and return the pointer (that must be cast)
// Keeps all memory smaller than 'margin' on the right side and all larger chunks on the left
// Stores array size right before pointer returned
// https://eli.thegreenplace.net/2014/perfect-forwarding-and-universal-references-in-c
template <class T, typename... Args>
T* Allocate(Args&&... args) {
// Allocate pointer
T* ptr = static_cast<T*>(Malloc(sizeof(T)));
// Construct pointer object and return it
return new (ptr) T(std::forward<Args>(args)...);
}
template <class T>
void Free(T* t) {
// Call destructor for recursive deletion
t->~T();
// Mark memory used by incoming pointer available for use
// Memory size is always stored 4 bytes before actual memory
unsigned int size = *((unsigned char *)t - 4);
for (int i = 0; i < detail::memoryArrays.size(); i++) {
int64_t dist = (unsigned char *)t - &detail::memoryArrays[i][0];
// If we are inside of this memory block
if (dist < detail::memBlockSize) {
MemoryChunk m = {
static_cast<unsigned int>(dist) - 4,
static_cast<unsigned int>(dist) + size,
size
};
detail::freeChunks[i].push_back(m);
// No need to look in other chunks if we found the pointer already
break;
}
}
detail::SortAndMerge();
}
}
#endif // MEMORY_MANAGER_H_