forked from endurodave/StateMachine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Allocator.cpp
134 lines (117 loc) · 3.32 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
#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)
{
SM_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;
}