16#include "../error_func.h"
18#include "../saveload/saveload_error.hpp"
24#define DEFINE_POOL_METHOD(type) \
25 template <class Titem, typename Tindex, size_t Tgrowth_step, PoolType Tpool_type, bool Tcache> \
26 requires std::is_base_of_v<PoolIDBase, Tindex> \
27 type Pool<Titem, Tindex, Tgrowth_step, Tpool_type, Tcache>
37 assert(index >= this->data.size());
38 assert(index < MAX_SIZE);
40 size_t old_size = this->data.size();
41 size_t new_size = std::min(MAX_SIZE,
Align(index + 1, Tgrowth_step));
43 this->data.resize(new_size);
44 this->used_bitmap.resize(
Align(new_size, BITMAP_SIZE) / BITMAP_SIZE);
45 if (old_size % BITMAP_SIZE != 0) {
47 this->used_bitmap[old_size / BITMAP_SIZE] &= ~((~static_cast<BitmapStorage>(0)) << (old_size % BITMAP_SIZE));
49 if (new_size % BITMAP_SIZE != 0) {
51 this->used_bitmap[new_size / BITMAP_SIZE] |= (~static_cast<BitmapStorage>(0)) << (new_size % BITMAP_SIZE);
61 for (
auto it = std::next(std::begin(this->used_bitmap), this->first_free / BITMAP_SIZE); it != std::end(this->used_bitmap); ++it) {
62 BitmapStorage available = ~(*it);
63 if (available == 0)
continue;
64 return std::distance(std::begin(this->used_bitmap), it) * BITMAP_SIZE +
FindFirstBit(available);
67 assert(this->first_unused == this->data.size());
69 if (this->first_unused < MAX_SIZE) {
70 this->ResizeFor(this->first_unused);
71 return this->first_unused;
74 assert(this->first_unused == MAX_SIZE);
88 assert(this->data[index] ==
nullptr);
90 this->first_unused = std::max(this->first_unused, index + 1);
94 if (Tcache && this->alloc_cache !=
nullptr) {
95 assert(
sizeof(Titem) == size);
96 item =
reinterpret_cast<Titem *
>(this->alloc_cache);
97 this->alloc_cache = this->alloc_cache->next;
99 item =
reinterpret_cast<Titem *
>(this->allocator.allocate(size));
101 this->data[index] = item;
102 SetBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);
104 return {item,
static_cast<Tindex
>(
static_cast<Tindex::BaseType
>(index))};
115 size_t index = this->FindFirstFree();
118 assert(this->checked != 0);
121 if (index == NO_FREE_ITEM) {
122 FatalError(
"{}: no more free items", this->name);
125 this->first_free = index + 1;
126 return this->AllocateItem(size, index);
138 if (index >= MAX_SIZE) {
142 if (index >= this->data.size()) this->ResizeFor(index);
144 if (this->data[index] !=
nullptr) {
148 return this->AllocateItem(size, index);
160 assert(index < this->data.size());
161 assert(this->data[index] !=
nullptr);
163 AllocCache *ac =
reinterpret_cast<AllocCache *
>(this->data[index]);
164 ac->next = this->alloc_cache;
165 this->alloc_cache = ac;
167 this->allocator.deallocate(
reinterpret_cast<uint8_t*
>(this->data[index]), size);
169 this->data[index] =
nullptr;
170 this->first_free = std::min(this->first_free, index);
172 if (!this->cleaning) {
173 ClrBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);
174 Titem::PostDestructor(index);
181 this->cleaning =
true;
182 for (
size_t i = 0; i < this->first_unused; i++) {
185 assert(this->items == 0);
187 this->data.shrink_to_fit();
188 this->used_bitmap.clear();
189 this->used_bitmap.shrink_to_fit();
190 this->first_unused = this->first_free = 0;
191 this->cleaning =
false;
194 while (this->alloc_cache !=
nullptr) {
195 AllocCache *ac = this->alloc_cache;
196 this->alloc_cache = ac->next;
197 this->allocator.deallocate(
reinterpret_cast<uint8_t*
>(ac),
sizeof(Titem));
202#undef DEFINE_POOL_METHOD
209#define INSTANTIATE_POOL_METHODS(name) \
210 template AllocationResult<name ## Pool::IndexType> name ## Pool::GetNew(size_t size); \
211 template AllocationResult<name ## Pool::IndexType> name ## Pool::GetNew(size_t size, size_t index); \
212 template void name ## Pool::FreeItem(size_t size, size_t index); \
213 template void name ## Pool::CleanPool();
Functions related to bit mathematics.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
constexpr T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
#define DEFINE_POOL_METHOD(type)
Helper for defining the method's signature.
Definition of Pool, structure used to access PoolItems, and PoolItem, base structure for Vehicle,...
void SlErrorCorruptFmt(const fmt::format_string< Args... > format, Args &&... fmt_args)
Issue an SlErrorCorrupt with a format string.