apool: track total&free elements
This commit is contained in:
+26
-20
@@ -1,33 +1,35 @@
|
||||
#include "pool.h"
|
||||
|
||||
APool *apool_create_ex(Allocator *allocator, U32 n_elements, U32 element_size, U32 element_align)
|
||||
APool *apool_create_ex(Allocator *allocator, const APoolCreateOptions *options)
|
||||
{
|
||||
Assert(IsPow2(element_align));
|
||||
U32 align = element_align;
|
||||
Assert(IsPow2(options->element_align));
|
||||
U32 element_align = options->element_align;
|
||||
if (element_align < alignof(APoolElement)) {
|
||||
element_align = alignof(APoolElement);
|
||||
}
|
||||
U32 size = AlignUp(element_size, element_align);
|
||||
U32 element_size = AlignUp(options->element_size, options->element_align);
|
||||
|
||||
APool *pool = allocator_push_type(allocator, APool);
|
||||
Assert(pool != NULL);
|
||||
pool->align = align;
|
||||
pool->element_size = size;
|
||||
pool->allocator = allocator;
|
||||
pool->n_elements = n_elements;
|
||||
pool->free_list = NULL;
|
||||
pool->start = NULL;
|
||||
pool->element_align= element_align;
|
||||
pool->element_size = element_size;
|
||||
pool->allocator = allocator;
|
||||
pool->n_elements = 0;
|
||||
pool->n_free = 0;
|
||||
pool->free_list = NULL;
|
||||
pool->flags = options->flags;
|
||||
|
||||
if (size != APOOL_AUTOGROW) {
|
||||
Assert(n_elements <= U32_Max / size );
|
||||
U32 total_size = n_elements * size;
|
||||
U8 * start = allocator_push(allocator, total_size, align);
|
||||
for (U32 i = 0; i < total_size; i += size) {
|
||||
if (options->n_reserved != 0) {
|
||||
Assert(options->n_reserved <= U32_Max / element_size );
|
||||
U32 total_size = options->n_reserved * element_size;
|
||||
U8 *start = allocator_push(allocator, total_size, element_align);
|
||||
for (U32 i = 0; i < total_size; i += element_size) {
|
||||
APoolElement *element = (APoolElement *)&start[i];
|
||||
element->next = pool->free_list;
|
||||
pool->free_list = element;
|
||||
pool->n_elements++;
|
||||
}
|
||||
pool->start = start;
|
||||
pool->n_free = pool->n_elements;
|
||||
}
|
||||
|
||||
return pool;
|
||||
@@ -38,8 +40,12 @@ void *apool_alloc(APool *pool)
|
||||
APoolElement *element = pool->free_list;
|
||||
if (element != NULL) {
|
||||
pool->free_list = element->next;
|
||||
} else if(pool->n_elements == APOOL_AUTOGROW) {
|
||||
element = allocator_push(pool->allocator, pool->element_size, pool->align);
|
||||
pool->n_free--;
|
||||
} else if((pool->flags & APoolFlag_AutoGrow) != 0) {
|
||||
element = allocator_push(pool->allocator, pool->element_size, pool->element_align);
|
||||
if (element != NULL) {
|
||||
pool->n_elements++;
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
@@ -48,10 +54,10 @@ void *apool_alloc(APool *pool)
|
||||
void apool_free(APool *pool, void *ptr)
|
||||
{
|
||||
if (ptr != NULL) {
|
||||
Assert((U8 *)ptr >= pool->start);
|
||||
|
||||
APoolElement *element = (APoolElement *)ptr;
|
||||
element->next = pool->free_list;
|
||||
pool->free_list = element;
|
||||
pool->n_free++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+19
-9
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
#include "core.h"
|
||||
|
||||
enum {
|
||||
APoolFlag_AutoGrow = (1 << 0)
|
||||
};
|
||||
typedef U32 APoolFlags;
|
||||
typedef union APoolElement APoolElement;
|
||||
union APoolElement {
|
||||
APoolElement *next; // offset from start to next free block (when not allocated)
|
||||
@@ -11,16 +15,22 @@ struct APool {
|
||||
APoolElement *free_list; // free list
|
||||
U8 *start; // start of user buffer
|
||||
Allocator *allocator;
|
||||
U32 element_size; // aligned size of each block
|
||||
U32 n_elements; // total number of blocks
|
||||
U32 align; // alignment
|
||||
};
|
||||
enum {
|
||||
APOOL_AUTOGROW = 0
|
||||
APoolFlags flags;
|
||||
U32 element_size; // aligned size of each element
|
||||
U32 element_align; // alignment
|
||||
U32 n_elements; // total elements in the pool
|
||||
U32 n_free; // number of free elements
|
||||
};
|
||||
typedef struct APoolCreateOptions APoolCreateOptions;
|
||||
struct APoolCreateOptions {
|
||||
U32 element_size; // aligned size of each element
|
||||
U32 element_align; // alignment of elements
|
||||
U32 n_reserved; // number of elements reserved
|
||||
APoolFlags flags;
|
||||
|
||||
#define apool_create(arena, n_elements, type) \
|
||||
apool_create_ex(arena, n_elements, sizeof(type), alignof(type));
|
||||
APool *apool_create_ex(Allocator *allocator, U32 n_elements, U32 element_size, uint32_t element_align);
|
||||
};
|
||||
#define apool_create(arena, n_reserved, type) \
|
||||
apool_create_ex(arena, &(APoolCreateOptions){sizeof(type), alignof(type), n_reserved, 0})
|
||||
APool *apool_create_ex(Allocator *allocator, const APoolCreateOptions *options);
|
||||
void *apool_alloc(APool *pool);
|
||||
void apool_free(APool *pool, void *element);
|
||||
|
||||
+38
-22
@@ -26,7 +26,7 @@ void arena_dump(const Arena *arena)
|
||||
}
|
||||
static void arena_test_1(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
ArenaOptions arena_params = {};
|
||||
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
||||
U32 commit_size = KB(8);
|
||||
@@ -53,7 +53,7 @@ static void arena_test_1(void)
|
||||
|
||||
static void arena_test_2(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
ArenaOptions arena_params = {};
|
||||
U32 arena_size = MB(3) + MemoryBlock_Header_Size;
|
||||
@@ -106,7 +106,7 @@ static void arena_test_2(void)
|
||||
|
||||
static void arena_test_3(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
ArenaOptions arena_params = {};
|
||||
U32 arena_size = KB(97) + MemoryBlock_Header_Size;
|
||||
@@ -134,7 +134,7 @@ static void arena_test_3(void)
|
||||
// gap was not accounted for. After the fix this should allocate a larger block.
|
||||
static void arena_test_4(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
U32 page_size = platform_page_size();
|
||||
ArenaOptions arena_params = {};
|
||||
@@ -167,7 +167,7 @@ static void arena_test_4(void)
|
||||
|
||||
static void arena_test_allocator_interface(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
U32 page_size = platform_page_size();
|
||||
ArenaOptions arena_params = {};
|
||||
@@ -203,7 +203,7 @@ static void arena_test_allocator_interface(void)
|
||||
|
||||
static void arena_test_decommit(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
U32 page_size = platform_page_size();
|
||||
ArenaOptions arena_params = {};
|
||||
@@ -230,7 +230,7 @@ static void arena_test_decommit(void)
|
||||
|
||||
void miniarena_test1(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
#define arena_size 4096
|
||||
MARENA_DEFINE(arena, arena_size, 8);
|
||||
@@ -269,12 +269,18 @@ struct PoolTest{
|
||||
|
||||
void apool_test(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
Arena arena;
|
||||
arena_init(&arena, &ArenaOptions_Default);
|
||||
Allocator allocator = arena_allocator(&arena);
|
||||
APool *pool = apool_create_ex(&allocator, 16, sizeof(PoolTest), alignof(PoolTest));
|
||||
APoolCreateOptions opts = {
|
||||
.n_reserved= 16,
|
||||
.element_size = sizeof(PoolTest),
|
||||
.element_align = alignof(PoolTest),
|
||||
.flags = 0
|
||||
};
|
||||
APool *pool = apool_create_ex(&allocator, &opts);
|
||||
PoolTest *list = NULL;
|
||||
for (U32 i = 0; i < U32_Max; i++) {
|
||||
PoolTest *pt = apool_alloc(pool);
|
||||
@@ -297,6 +303,7 @@ void apool_test(void)
|
||||
printf("Pooltest freeing %u\n",p->n);
|
||||
apool_free(pool, p);
|
||||
}
|
||||
printf("Pooltest total: %u free %u\n", pool->n_elements, pool->n_free);
|
||||
list = NULL;
|
||||
for (U32 i = 0; i < U32_Max; i++) {
|
||||
PoolTest *pt = apool_alloc(pool);
|
||||
@@ -316,13 +323,13 @@ void apool_test(void)
|
||||
|
||||
void apool_test_miniarena(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
MArena arena;
|
||||
U8 data[4096];
|
||||
marena_init(&arena, data, sizeof data);
|
||||
Allocator allocator = marena_allocator(&arena);
|
||||
APool *pool = apool_create_ex(&allocator, 16, sizeof(PoolTest), alignof(PoolTest));
|
||||
APool *pool = apool_create(&allocator, 16, PoolTest);
|
||||
PoolTest *list = NULL;
|
||||
for (U32 i = 0; i < U32_Max; i++) {
|
||||
PoolTest *pt = apool_alloc(pool);
|
||||
@@ -358,19 +365,26 @@ void apool_test_miniarena(void)
|
||||
for (PoolTest *p = list; p; p = p->next){
|
||||
printf("Pooltest %u\n",p->n);
|
||||
}
|
||||
printf("Pooltest total: %u free %u\n", pool->n_elements, pool->n_free);
|
||||
|
||||
allocator_free_all(&allocator);
|
||||
}
|
||||
|
||||
|
||||
void apool_test_autogrow(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
Arena arena;
|
||||
arena_init(&arena, &ArenaOptions_Default);
|
||||
Allocator allocator = arena_allocator(&arena);
|
||||
|
||||
APool *pool = apool_create(&allocator, APOOL_AUTOGROW, PoolTest);
|
||||
APoolCreateOptions opts = {
|
||||
.n_reserved = 0,
|
||||
.element_size = sizeof(PoolTest),
|
||||
.element_align = alignof(PoolTest),
|
||||
.flags = APoolFlag_AutoGrow
|
||||
};
|
||||
APool *pool = apool_create_ex(&allocator, &opts);
|
||||
PoolTest *list = NULL;
|
||||
for (U32 i = 0; i < 4; i++) {
|
||||
PoolTest *pt = apool_alloc(pool);
|
||||
@@ -384,6 +398,7 @@ void apool_test_autogrow(void)
|
||||
for (PoolTest *p = list; p; p = p->next){
|
||||
printf("Pooltest %u\n",p->n);
|
||||
}
|
||||
printf("Pooltest total: %u free %u\n", pool->n_elements, pool->n_free);
|
||||
|
||||
PoolTest *next;
|
||||
U32 count = 0;
|
||||
@@ -406,6 +421,7 @@ void apool_test_autogrow(void)
|
||||
for (PoolTest *p = list; p; p = p->next){
|
||||
printf("Pooltest %u\n",p->n);
|
||||
}
|
||||
printf("Pooltest total: %u free %u\n", pool->n_elements, pool->n_free);
|
||||
|
||||
allocator_free_all(&allocator);
|
||||
arena_free(&arena);
|
||||
@@ -414,7 +430,7 @@ void apool_test_autogrow(void)
|
||||
|
||||
void string_test_1(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
Str str1 = S("Hello");
|
||||
printf("str1: %.*s len %d\n", str1.len, str1.str, str1.len);
|
||||
@@ -431,7 +447,7 @@ void string_test_1(void)
|
||||
|
||||
void string_split_test_1(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
Str str1 = S("|a:bb|ccc|");
|
||||
Str sep = S("|:");
|
||||
@@ -445,7 +461,7 @@ void string_split_test_1(void)
|
||||
}
|
||||
void string_test_misc(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
Str str1 = S("Hello World");
|
||||
bool prefix1 = str_starts_with(str1, S("He"));
|
||||
@@ -484,7 +500,7 @@ void string_test_misc(void)
|
||||
}
|
||||
void string_test_join(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
Arena arena;
|
||||
arena_init(&arena, &ArenaOptions_Default);
|
||||
Allocator allocator = arena_allocator(&arena);
|
||||
@@ -515,7 +531,7 @@ void print_runes(Str str)
|
||||
|
||||
void string_test_utf8(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
Str str1 = S("Test 1ø2 ☺");
|
||||
|
||||
@@ -539,7 +555,7 @@ void string_test_utf8(void)
|
||||
|
||||
void string_test_hex(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
MArena arena;
|
||||
U8 data[4096];
|
||||
@@ -577,7 +593,7 @@ struct StrSList {
|
||||
|
||||
void string_test_slist(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
Str str1 = S("one");
|
||||
Str str2 = S("two");
|
||||
@@ -625,7 +641,7 @@ struct StrDList {
|
||||
|
||||
void string_test_dlist(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
TRACEF("\n\n");
|
||||
|
||||
Str str1 = S("one");
|
||||
Str str2 = S("two");
|
||||
|
||||
Reference in New Issue
Block a user