Cogs.Core
ConfigurablePagedPool.h
1#pragma once
2
3#include <vector>
4
5namespace Cogs
6{
7 namespace Collections
8 {
13 {
16 };
17
19 {
20 // Context free.
21 };
22
30 template<typename T>
32 {
34 DefaultPage() = default;
35
42 DefaultPage(DefaultContext & context, size_t pageSize)
43 {
44 // Unused parameter.
45 (void)context;
46
47 static_assert(sizeof(T) >= sizeof(intptr_t), "T must be at least of pointer size.");
48
49 const size_t elementSize = sizeof(T);
50
51 bytes.resize(pageSize * elementSize);
52
53 auto head = reinterpret_cast<ItemHeader *>(bytes.data());
54
55 // Initialize the linked list of elements chaining all elements in the page together.
56 for (size_t i = 0; i < pageSize; ++i) {
57 ItemHeader * block = head + i;
58
59 block->next = block + 1;
60 }
61
62 // Terminate the free list at the end of the page.
63 (head + (pageSize - 1))->next = nullptr;
64 }
65
67 T * getHead() { return reinterpret_cast<T *>(bytes.data()); }
68
69 private:
71 std::vector<uint8_t> bytes;
72 };
73
90 template<typename Context, typename Page, typename Item>
92 {
93 public:
96
106 ConfigurablePagedPool(Context context, size_t capacity, size_t pageSize) :
107 context(context),
108 pageSize(pageSize)
109 {
110 resize(capacity);
111 }
112
122 void initialize(Context context, size_t capacity, size_t pageSize)
123 {
124 this->context = context;
125 this->pageSize = pageSize;
126
127 resize(capacity);
128 }
129
144 {
145 if (!head) resize(capacity + pageSize);
146
147 auto item = head;
148 head = head->next;
149
150 return reinterpret_cast<Item *>(item);
151 }
152
161 void deallocate(Item * item)
162 {
163 reinterpret_cast<ItemHeader *>(item)->next = head;
164 head = reinterpret_cast<ItemHeader *>(item);
165 }
166
172 void resize(size_t capacity)
173 {
174 while (capacity > this->capacity) {
175 addPage();
176 }
177 }
178
179 private:
181 void addPage()
182 {
183 pages.emplace_back(context, pageSize);
184
185 auto & lastPage = pages.back();
186
187 if (!head) {
188 head = reinterpret_cast<ItemHeader *>(lastPage.getHead());
189 } else {
190 ItemHeader * last = head;
191
192 while (last->next) {
193 last = last->next;
194 }
195
196 last->next = reinterpret_cast<ItemHeader *>(lastPage.getHead());
197 }
198
199 capacity += pageSize;
200 }
201
202 protected:
204 Context context;
205 std::vector<Page> pages;
206 size_t capacity = 0;
207 size_t pageSize = 0;
208
209 ItemHeader * head = nullptr;
211 };
212 }
213}
Provides a configurable pool implementation usable as base implementation for several pool-like stora...
ConfigurablePagedPool(Context context, size_t capacity, size_t pageSize)
Constructs a pool with the given context, capacity and pageSize.
void addPage()
Adds a new page to the pool, linking its reserved elements with any current free elements.
void deallocate(Item *item)
Deallocate the given item.
void resize(size_t capacity)
Resize the pool to the given capacity.
Item * allocate()
Allocates storage for a new item and returns a pointer to the item.
ConfigurablePagedPool()=default
Constructs a default, empty pool.
void initialize(Context context, size_t capacity, size_t pageSize)
Initialize the pool with the given parameters.
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
Default page type that maintains storage for elements of type T in the pool page and provides pooled ...
std::vector< uint8_t > bytes
Backing storage bytes.
DefaultPage()=default
Default constructor.
DefaultPage(DefaultContext &context, size_t pageSize)
Construct a new page with the given page size.
T * getHead()
Retrieve a pointer to the first element of the page.
Header struct used to alias with the stored type to chain elements in the storage together.
ItemHeader * next
Pointer to the next element in the free list.