Zen C++ Libraries
Zero-dependency re-usable components for C++
Loading...
Searching...
No Matches
bump_ptr_pool.hpp
Go to the documentation of this file.
1
8
9#ifndef ZEN_BUMP_PTR_POOL_HPP
10#define ZEN_BUMP_PTR_POOL_HPP
11
12#include <cstddef>
13#include <cstring>
14#include <list>
15#include <memory>
16#include <new>
17
18#include "zen/config.hpp"
19#include "zen/math.hpp"
20#include "zen/alloc.hpp"
21
22#define ZEN_DEFAULT_POOL_CHUNK_SIZE 65536
23
24#define ZEN_DEFAULT_GROWING_BUMP_PTR_POOL_MIN_SIZE 4084
25
26ZEN_NAMESPACE_START
27
38class bump_ptr_pool {
39
40 std::size_t _data_sz;
41
42 std::byte* _data_start;
43 std::byte* _data_end;
44 std::byte* _prev_slot = nullptr;
45
46 std::byte* get_slot_next_at(const std::byte* ptr) {
47 std::byte* out;
48 std::memcpy(&out, ptr, sizeof(void*));
49 return out;
50 }
51
52 destroy_fn get_slot_destroy_at(const std::byte* ptr) {
53 destroy_fn out;
54 std::memcpy(&out, ptr + sizeof(void*), sizeof(destroy_fn));
55 return out;
56 }
57
58 void* get_slot_data_at(std::byte* ptr) {
59 return ptr + sizeof(void*) + sizeof(destroy_fn);
60 }
61
62 void set_slot_next_at(std::byte* ptr, void* next) {
63 std::memcpy(ptr, &next, sizeof(void*));
64 }
65
66 void set_slot_destroy_at(std::byte* ptr, destroy_fn fn) {
67 std::memcpy(ptr + sizeof(void*), &fn, sizeof(destroy_fn));
68 }
69
70 std::byte* first_slot() {
71 return _data_end == _data_start ? nullptr : _data_start;
72 }
73
74public:
75
76 bump_ptr_pool(std::size_t sz = ZEN_DEFAULT_POOL_CHUNK_SIZE) {
77 _data_sz = sz;
78 _data_start = new std::byte[_data_sz + sizeof(void*)];
79 memset(_data_start, 0, _data_sz + sizeof(void*));
80 _data_end = _data_start;
81 }
82
83 bool empty() const {
84 return _data_start == _data_end;
85 }
86
87 std::size_t max_bytes_free() const {
88 auto free = _data_sz - (_data_end - _data_start);
89 auto header_size = sizeof(void*) + sizeof(destroy_fn);
90 return free < header_size ? 0 : free - header_size;
91 }
92
93 std::size_t capacity() const {
94 return _data_sz;
95 }
96
97 void* allocate(std::size_t sz, std::size_t alignment, destroy_fn destroy) {
98 void* data = get_slot_data_at(_data_end);
99 std::size_t free = max_bytes_free();
100 if (!std::align(alignment, sz, data, free)) {
101 return nullptr;
102 }
103 set_slot_destroy_at(_data_end, destroy);
104 if (_prev_slot) {
105 set_slot_next_at(_prev_slot, _data_end);
106 }
107 _prev_slot = _data_end;
108 _data_end = static_cast<std::byte*>(data) + sz;
109 return data;
110 }
111
112 ~bump_ptr_pool() {
113 auto curr_slot = first_slot();
114 while (curr_slot) {
115 get_slot_destroy_at(curr_slot)(get_slot_data_at(reinterpret_cast<std::byte*>(curr_slot)));
116 curr_slot = get_slot_next_at(curr_slot);
117 }
118 delete _data_start;
119 }
120
121 static std::size_t min_size_for(std::size_t sz) {
122 return power_of_2_ceil(sz + sizeof(void*) + sizeof(destroy_fn));
123 }
124
125};
126
139class growing_bump_ptr_pool {
140
141 std::list<bump_ptr_pool*> chunks;
142
143public:
144
145 growing_bump_ptr_pool(std::size_t min_size = ZEN_DEFAULT_GROWING_BUMP_PTR_POOL_MIN_SIZE) {
146 chunks.push_back(new bump_ptr_pool { power_of_2_ceil(min_size) });
147 }
148
149 growing_bump_ptr_pool(growing_bump_ptr_pool&& other):
150 chunks(std::move(other.chunks)) {}
151
152 void* allocate(std::size_t sz, std::size_t alignment, destroy_fn destroy) {
153 auto last_chunk = chunks.back();
154 void* ptr = last_chunk->allocate(sz, alignment, destroy);
155 if (ZEN_LIKELY(ptr)) {
156 return ptr;
157 }
158 auto next_chunk = new (std::nothrow) bump_ptr_pool {
159 std::max(
160 bump_ptr_pool::min_size_for(sz),
161 next_power_of_2(last_chunk->capacity())
162 )
163 };
164 if (ZEN_UNLIKELY(next_chunk == nullptr)) {
165 return nullptr;
166 }
167 chunks.push_back(next_chunk);
168 return next_chunk->allocate(sz, alignment, destroy);
169 }
170
171 ~growing_bump_ptr_pool() {
172 for (auto chunk: chunks) {
173 delete chunk;
174 }
175 }
176};
177
178ZEN_NAMESPACE_END
179
180#endif // of #ifndef ZEN_BUMP_PTR_POOL_HPP
Generic tools and utilities for using and defining allocators.
void(*)(void *) destroy_fn
Definition alloc.hpp:53
A chunk of memory for storing variable-width objects which get destroyed all at once.
Definition bump_ptr_pool.hpp:38