-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMyMemoryPool.hpp
110 lines (93 loc) · 3.08 KB
/
MyMemoryPool.hpp
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
#ifndef OOP_PROJECT_MYMEMORYPOOL_HPP
#define OOP_PROJECT_MYMEMORYPOOL_HPP
#include "MyStack.hpp"
#include <memory>
#include <array>
/**
* Choose *lower_bound* and *upper_bound* according to specific cases
* @tparam block_num: the num of blocks in each chunk
* @tparam lower_bound: allocate from (2^lower_bound) Bytes
* @tparam upper_bound: to (2^upper_bound) Bytes
*/
template<unsigned int block_num, unsigned int lower_bound, unsigned int upper_bound>
class MyMemoryPool
{
private:
// Store the header node of all levels of FreeList
std::array<MyStack<void *>,
upper_bound - lower_bound + 1> memory_manager;
// Store the ptr to each chunk
MyStack<void *> chunks;
// Find suitable array index by size
[[nodiscard]] unsigned int which_index(unsigned long size);
public:
MyMemoryPool() = default;
~MyMemoryPool();
[[nodiscard]] void *memory_allocate(unsigned long size);
void memory_deallocate(void *p, unsigned long size);
};
template<unsigned int block_num, unsigned int lower_bound, unsigned int upper_bound>
void *
MyMemoryPool<block_num, lower_bound, upper_bound>::memory_allocate(
unsigned long size)
{
// Find out the level of FreeList
unsigned int index = which_index(size);
// If there is no Free Spaces,create one
if (memory_manager.at(index).empty())
{
// calculate the size
unsigned long data_size = (unsigned long) 1 << (index + lower_bound);
// store the address into chunks
chunks.push(::operator new(data_size * block_num));
for (int i = 0; i < block_num; ++i)
{
memory_manager.at(index).push(
(void *) ((unsigned long) chunks.top() + i * data_size));
}
}
return memory_manager.at(index).pop_get();
}
template<unsigned int block_num, unsigned int lower_bound, unsigned int upper_bound>
void
MyMemoryPool<block_num, lower_bound, upper_bound>::memory_deallocate(void *p,
unsigned long size)
{
// Find out the level of FreeList
unsigned int index = which_index(size);
memory_manager.at(index).push(p);
}
template<unsigned int block_num, unsigned int lower_bound, unsigned int upper_bound>
unsigned int
MyMemoryPool<block_num, lower_bound, upper_bound>::which_index(
unsigned long size)
{
// 2^(power - 1) < size <= 2^(power)
unsigned int power = 1;
while ((unsigned long) 1 << power < size)
{
++power;
}
// If power goes exceed bounds
if (power > upper_bound)
{
std::string message = "Cannot allocate so large!";
throw std::out_of_range(message);
}
// Give the smallest block
if (power < lower_bound)
{
return 0;
}
// return correct index
return power - lower_bound;
}
template<unsigned int block_num, unsigned int lower_bound, unsigned int upper_bound>
MyMemoryPool<block_num, lower_bound, upper_bound>::~MyMemoryPool()
{
while (!chunks.empty())
{
::operator delete(chunks.pop_get());
}
}
#endif //OOP_PROJECT_MYMEMORYPOOL_HPP