54 template <
typename TYPE>
63 template <
typename TYPE>
64 static void free(TYPE* ptr);
84 template<
typename TYPE,
template <
typename>
typename DERIVED>
96 template <
typename O_TYPE>
128 template<
typename O_TYPE,
typename... Args>
136 template<
typename O_TYPE>
153 template<
typename TYPE>
202 template<
typename TYPE>
213 freeChunk* next =
nullptr;
220 class allocatedChunks {
222 void* chunks =
nullptr;
223 allocatedChunks* next =
nullptr;
233 static constexpr u_integer CHUNK_SIZE =
sizeof(TYPE) >
sizeof(freeChunk*) ?
sizeof(TYPE) :
sizeof(freeChunk*);
238 freeChunk** free_list_head;
239 allocatedChunks* allocated_list_head;
277 void release()
noexcept;
347template<
typename TYPE>
354 return static_cast<TYPE*
>(
operator new(size *
sizeof(TYPE)));
355 }
catch (
const std::bad_alloc&) {
360template<
typename TYPE>
362 ::operator
delete(ptr);
365template <
typename TYPE,
template <
typename>
typename DERIVED>
371template<
typename TYPE,
template <
typename>
typename DERIVED>
374template<
typename TYPE,
template <
typename>
typename DERIVED>
375template<
typename O_TYPE,
typename... Args>
377 new (o_ptr) O_TYPE{std::forward<Args>(args)...};
380template<
typename TYPE,
template <
typename>
typename DERIVED>
381template<
typename O_TYPE>
386template<
typename TYPE>
391template<
typename TYPE>
396template<
typename TYPE>
400 while (
static_cast<u_integer>(1) << index < size) {
406template<
typename TYPE>
411 this->allocated_list_head =
nullptr;
413 for (
u_integer i = 0; i < this->size_class_count; i++) {
414 this->chunk_count[i] = this->chunk_count_init;
415 this->free_list_head[i] =
nullptr;
416 this->chunks_available[i] = 0;
420template <
typename TYPE>
423 const u_integer block_size = (1 << index) * CHUNK_SIZE;
427 new_allocated_chunk->chunks = new_free_chunk;
428 new_allocated_chunk->next = this->allocated_list_head;
429 this->allocated_list_head = new_allocated_chunk;
431 for (
u_integer i = 0; i < num_element; i++)
433 auto cur_ptr =
reinterpret_cast<freeChunk*
>(new_free_chunk + i * block_size);
434 cur_ptr->next = this->free_list_head[index];
435 this->free_list_head[index] = cur_ptr;
437 this->chunks_available[index] += num_element;
438 this->chunk_count[index] = this->chunk_count[index] + (this->chunk_count[index] >> 1);
441template<
typename TYPE>
443 while (this->allocated_list_head) {
444 auto next_chunk = this->allocated_list_head->next;
447 this->allocated_list_head = next_chunk;
450 if (this->chunk_count) {
452 this->chunk_count =
nullptr;
454 if (this->free_list_head) {
456 this->free_list_head =
nullptr;
458 if (this->chunks_available) {
460 this->chunks_available =
nullptr;
464template <
typename TYPE>
466 : size_class_count(size_class_count), chunk_count_init(count), chunk_count(nullptr),
467 free_list_head(nullptr), allocated_list_head(nullptr), chunks_available(nullptr) {
471template<
typename TYPE>
476 auto size_class_count_max =
max(this->size_class_count, other.size_class_count);
477 auto chunk_count_init_max =
max(this->chunk_count_init, other.chunk_count_init);
482 for (
u_integer i = 0; i < size_class_count_max; i++) {
483 if (i < this->size_class_count && i < other.size_class_count) {
484 chunk_count_max[i] =
max(this->chunk_count[i], other.chunk_count[i]);
485 chunks_available_max[i] = this->chunks_available[i] + other.chunks_available[i];
486 auto cur_list_head_i = other.free_list_head[i];
487 if (cur_list_head_i) {
488 while (cur_list_head_i->next) {
489 cur_list_head_i = cur_list_head_i->next;
491 cur_list_head_i->next = this->free_list_head[i];
492 free_list_head_max[i] = other.free_list_head[i];
494 free_list_head_max[i] = this->free_list_head[i];
496 }
else if (i < this->size_class_count) {
497 chunk_count_max[i] = this->chunk_count[i];
498 chunks_available_max[i] = this->chunks_available[i];
499 free_list_head_max[i] = this->free_list_head[i];
501 chunk_count_max[i] = other.chunk_count[i];
502 chunks_available_max[i] = other.chunks_available[i];
503 free_list_head_max[i] = other.free_list_head[i];
507 auto allocated_list_head_max = other.allocated_list_head;
508 auto cur_allocated_list_head = allocated_list_head_max;
509 if (cur_allocated_list_head) {
510 while (cur_allocated_list_head->next) {
511 cur_allocated_list_head = cur_allocated_list_head->next;
513 cur_allocated_list_head->next = this->allocated_list_head;
515 allocated_list_head_max = this->allocated_list_head;
517 this->allocated_list_head =
nullptr;
518 other.allocated_list_head =
nullptr;
524 this->size_class_count = size_class_count_max;
525 this->chunk_count_init = chunk_count_init_max;
526 this->chunk_count = chunk_count_max;
527 this->free_list_head = free_list_head_max;
528 this->chunks_available = chunks_available_max;
529 this->allocated_list_head = allocated_list_head_max;
534template<
typename TYPE>
536 this->operator=(std::move(other));
539template<
typename TYPE>
546 this->size_class_count = other.size_class_count;
547 this->chunk_count_init = other.chunk_count_init;
548 this->chunk_count = other.chunk_count;
549 this->free_list_head = other.free_list_head;
550 this->allocated_list_head = other.allocated_list_head;
551 this->chunks_available = other.chunks_available;
557template <
typename TYPE>
566 if (index >= this->size_class_count) {
570 if (!this->free_list_head[index] || this->chunks_available[index] * (
static_cast<u_integer>(1) << index) < size) {
571 this->chunkAllocate(
max<u_integer>(1, this->chunk_count[index]), index);
574 auto cur_ptr = this->free_list_head[index];
575 this->free_list_head[index] = this->free_list_head[index]->next;
576 this->chunks_available[index] -= 1;
577 return reinterpret_cast<TYPE*
>(cur_ptr);
580template <
typename TYPE>
589 if (index >= this->size_class_count) {
594 auto p =
reinterpret_cast<freeChunk*
>(ptr);
595 p->next = this->free_list_head[index];
596 this->free_list_head[index] = p;
597 this->chunks_available[index] += 1;
600template<
typename TYPE>
Exception for memory allocation failures.
Definition error.h:285
Interface for other memory allocator implementations.
Definition allocator.h:85
std::false_type propagate_on_container_swap
No propagation on swap.
Definition allocator.h:89
std::false_type propagate_on_container_copy_assignment
No propagation on copy.
Definition allocator.h:87
DERIVED< O_TYPE > rebind_alloc
Rebinds allocator to different type.
Definition allocator.h:97
virtual ~allocatorBase()=0
Virtual destructor.
std::false_type propagate_on_container_move_assignment
No propagation on move.
Definition allocator.h:88
void construct(O_TYPE *o_ptr, Args &&... args)
Constructs an object in allocated memory.
Definition allocator.h:376
constexpr allocatorBase()
Constructs a new allocatorBase instance.
Definition allocator.h:366
static void destroy(O_TYPE *o_ptr)
Destroys an object without deallocating.
Definition allocator.h:382
virtual void deallocate(TYPE *ptr, u_integer size)=0
Deallocates memory.
virtual TYPE * allocate(u_integer size)=0
Allocates raw memory.
std::false_type propagate_on_container_merge
No propagation on merge.
Definition allocator.h:90
Default memory allocator using allocators utilities.
Definition allocator.h:154
void deallocate(TYPE *ptr, u_integer size) override
Deallocates memory using global operator delete.
Definition allocator.h:392
TYPE * allocate(u_integer size) override
Allocates memory using global operator new.
Definition allocator.h:387
Utility class providing static memory allocation/de-allocation functions.
Definition allocator.h:43
static TYPE * malloc(u_integer size)
Allocates raw memory using global operator new.
Definition allocator.h:348
static void free(TYPE *ptr)
Deallocates memory using global operator delete.
Definition allocator.h:361
Object pool allocator for efficient fixed-size memory management.
Definition allocator.h:204
objPoolAllocator & operator+=(objPoolAllocator &other)
Merges another pool allocator into this one.
Definition allocator.h:472
objPoolAllocator(const objPoolAllocator &)=delete
Copy construction disabled.
TYPE * allocate(u_integer size) override
Allocates memory from the pool.
Definition allocator.h:558
std::true_type propagate_on_container_swap
Allows propagation on swap.
Definition allocator.h:282
void deallocate(TYPE *ptr, u_integer size) override
Returns memory to the pool.
Definition allocator.h:581
std::true_type propagate_on_container_move_assignment
Allows propagation on move.
Definition allocator.h:281
objPoolAllocator(u_integer size_class_count=8, u_integer count=4)
Constructs a new object pool allocator.
Definition allocator.h:465
std::true_type propagate_on_container_merge
Allows propagation on merge.
Definition allocator.h:283
~objPoolAllocator() override
Destructor - releases all allocated memory.
Definition allocator.h:601
objPoolAllocator & operator=(const objPoolAllocator &)=delete
Copy assignment disabled.
Compile-time error triggering utility.
Definition error.h:112
Platform-independent type definitions and compiler/platform detection.
Custom exception classes and callback validation utilities.
std::uint32_t u_integer
32-bit unsigned integer type for sizes and indexes
Definition config.h:263
Mathematical utilities and constants.
Main namespace for the project Original.
Definition algorithms.h:21
TYPE max(TYPE a, TYPE b)
Returns the larger of two given values.