This repository has been archived by the owner on Jan 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pool.h
72 lines (59 loc) · 2.33 KB
/
pool.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
#pragma once
#include "likely.h"
#include <list>
#include <memory>
#include <cassert>
#include <cstdint>
#include <cstring>
namespace yzw2v {
namespace mem {
class Pool {
public:
explicit Pool(const size_t block_size)
: default_block_size{block_size} {
blocks_.emplace_back(default_block_size);
}
template <typename T>
T* Get(const size_t size) {
return reinterpret_cast<T*>(GetAligned(sizeof(T) * size, alignof(T)));
}
private:
static void* Align(const size_t alignment, const size_t size, void*&ptr, size_t& space) noexcept;
void* GetAligned(const size_t size, const size_t alignment) {
auto* res = blocks_.back().current;
if (Align(alignment, size, res, blocks_.back().memory_left)) {
blocks_.back().current = reinterpret_cast<uint8_t*>(res) + size;
blocks_.back().memory_left -= size;
return res;
} else {
const auto size_to_allocate = default_block_size < size + alignment - 1
? size + alignment - 1
: default_block_size;
blocks_.emplace_back(size_to_allocate);
}
res = Align(alignment, size,
blocks_.back().current, blocks_.back().memory_left);
if (!res) {
assert(false); // you was wrong
}
blocks_.back().current = reinterpret_cast<uint8_t*>(res) + size;
blocks_.back().memory_left -= size;
return res;
}
struct Block {
void* current;
size_t memory_left;
std::unique_ptr<uint8_t[]> begin;
explicit Block(const size_t custom_block_size)
: memory_left{custom_block_size}
, begin{new uint8_t[custom_block_size]}
{
current = begin.get();
std::memset(current, 0, memory_left);
}
};
size_t default_block_size;
std::list<Block> blocks_;
};
};
}