-
Notifications
You must be signed in to change notification settings - Fork 41
/
Allocator.cpp
141 lines (124 loc) · 3.52 KB
/
Allocator.cpp
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 "Allocator.h"
#include "DataTypes.h"
#include "Fault.h"
#include <new>
//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
Allocator::Allocator(size_t size, UINT objects, CHAR* memory, const CHAR* name) :
m_blockSize(size < sizeof(long*) ? sizeof(long*):size),
m_objectSize(size),
m_maxObjects(objects),
m_pHead(NULL),
m_poolIndex(0),
m_blockCnt(0),
m_blocksInUse(0),
m_allocations(0),
m_deallocations(0),
m_name(name)
{
// If using a fixed memory pool
if (m_maxObjects)
{
// If caller provided an external memory pool
if (memory)
{
m_pPool = memory;
m_allocatorMode = STATIC_POOL;
}
else
{
m_pPool = (CHAR*)new CHAR[m_blockSize * m_maxObjects];
m_allocatorMode = HEAP_POOL;
}
}
else
m_allocatorMode = HEAP_BLOCKS;
}
//------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------
Allocator::~Allocator()
{
// If using pool then destroy it, otherwise traverse free-list and
// destroy each individual block
if (m_allocatorMode == HEAP_POOL)
delete [] m_pPool;
else if (m_allocatorMode == HEAP_BLOCKS)
{
while(m_pHead)
delete [] (CHAR*)Pop();
}
}
//------------------------------------------------------------------------------
// Allocate
//------------------------------------------------------------------------------
void* Allocator::Allocate(size_t size)
{
ASSERT_TRUE(size <= m_objectSize);
// If can't obtain existing block then get a new one
void* pBlock = Pop();
if (!pBlock)
{
// If using a pool method then get block from pool,
// otherwise using dynamic so get block from heap
if (m_maxObjects)
{
// If we have not exceeded the pool maximum
if(m_poolIndex < m_maxObjects)
{
pBlock = (void*)(m_pPool + (m_poolIndex++ * m_blockSize));
}
else
{
// Get the pointer to the new handler
std::new_handler handler = std::set_new_handler(0);
std::set_new_handler(handler);
// If a new handler is defined, call it
if (handler)
(*handler)();
else
ASSERT();
}
}
else
{
m_blockCnt++;
pBlock = (void*)new CHAR[m_blockSize];
}
}
m_blocksInUse++;
m_allocations++;
return pBlock;
}
//------------------------------------------------------------------------------
// Deallocate
//------------------------------------------------------------------------------
void Allocator::Deallocate(void* pBlock)
{
Push(pBlock);
m_blocksInUse--;
m_deallocations++;
}
//------------------------------------------------------------------------------
// Push
//------------------------------------------------------------------------------
void Allocator::Push(void* pMemory)
{
Block* pBlock = (Block*)pMemory;
pBlock->pNext = m_pHead;
m_pHead = pBlock;
}
//------------------------------------------------------------------------------
// Pop
//------------------------------------------------------------------------------
void* Allocator::Pop()
{
Block* pBlock = NULL;
if (m_pHead)
{
pBlock = m_pHead;
m_pHead = m_pHead->pNext;
}
return (void*)pBlock;
}