-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFreeListAllocator.cpp
123 lines (103 loc) · 3.47 KB
/
FreeListAllocator.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
#include "FreeListAllocator.h"
#include <cstdlib>
#include <iostream>
FreeListAllocator::FreeListAllocator(const std::size_t totalSize) :
m_totalSize(totalSize),
m_usedBytes(0),
m_startPtr(nullptr)
{}
FreeListAllocator::~FreeListAllocator()
{
free(m_startPtr);
m_startPtr = nullptr;
//std::cout << "~FreeListAllocator" << std::endl;
}
void FreeListAllocator::Init()
{
if (m_startPtr)
{
free(m_startPtr);
m_startPtr = nullptr;
}
m_startPtr = malloc(m_totalSize + AllocationHeaderSize);
// set header
*((std::size_t*)m_startPtr) = m_totalSize;
void* data = m_startPtr + AllocationHeaderSize;
m_freeList.push_front(FreeBlock(m_totalSize, data));
}
void* FreeListAllocator::Allocate(const std::size_t size)
{
std::list<FreeListAllocator::FreeBlock>::iterator nodeIter = m_freeList.end();
Find(size, nodeIter);
if (nodeIter == m_freeList.end())
{
//std::cout << "not enough memory" << std::endl;
return nullptr;
}
if ((*nodeIter).blockSize > size)
{
std::size_t restSize = (*nodeIter).blockSize - size;
// change header for old block
*((std::size_t*)((*nodeIter).data - AllocationHeaderSize)) = size;
// set header for new block
void* data = (*nodeIter).data + size;
*((std::size_t*)data) = restSize;
data = data + AllocationHeaderSize;
m_freeList.insert(nodeIter, FreeBlock{restSize, data});
}
m_usedBytes += size + AllocationHeaderSize;
m_freeList.erase(nodeIter);
return (*nodeIter).data;
}
void FreeListAllocator::Free(void* ptr)
{
std::size_t blockSize = *((std::size_t*)(ptr - AllocationHeaderSize));
for (auto it = m_freeList.begin(); it != m_freeList.end(); ++it)
{
if (ptr < (*it).data)
{
auto prev = m_freeList.insert(it, FreeBlock{blockSize, ptr});
m_usedBytes -= (blockSize + AllocationHeaderSize);
Merge(prev, it);
return;
}
}
// if m_freeList is empty
m_freeList.push_front(FreeBlock{blockSize, ptr});
m_usedBytes -= (blockSize + AllocationHeaderSize);
}
void FreeListAllocator::Find(const std::size_t size, std::list<FreeListAllocator::FreeBlock>::iterator& nodeIter)
{
for (auto it = m_freeList.begin(); it != m_freeList.end(); ++it)
{
if ((*it).blockSize >= size)
{
nodeIter = it;
//std::cout << "find: " << (*it).data << std::endl;
return;
}
}
}
void FreeListAllocator::Merge(std::list<FreeBlock>::iterator& prev, std::list<FreeBlock>::iterator& next)
{
//std::cout << "prev.data: " << (*prev).data << std::endl;
//std::cout << "next.data: " << (*next).data << std::endl;
if ((*prev).data + (*prev).blockSize + AllocationHeaderSize == (*next).data)
{
// set header
(*(std::size_t*)((*prev).data - AllocationHeaderSize)) = (*prev).blockSize + (*next).blockSize;
(*prev).blockSize += (*next).blockSize;
m_freeList.erase(next);
}
}
void FreeListAllocator::DisplayList()
{
for (const auto& node : m_freeList)
{
std::cout << "data: " << node.data << std::endl;
std::cout << "blockSize: " << node.blockSize << std::endl;
}
}
std::size_t FreeListAllocator::GetTotalSize() const { return m_totalSize; }
std::size_t FreeListAllocator::GetUsedBytes() const { return m_usedBytes; }
const std::list<FreeListAllocator::FreeBlock>& FreeListAllocator::GetFreeList() { return m_freeList; }