diff --git a/src/base/pool.c b/src/base/pool.c index e9cd234..112dd59 100644 --- a/src/base/pool.c +++ b/src/base/pool.c @@ -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++; + } } diff --git a/src/base/pool.h b/src/base/pool.h index d21dc1f..b94fc00 100644 --- a/src/base/pool.h +++ b/src/base/pool.h @@ -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); diff --git a/src/main.c b/src/main.c index c785523..373dc49 100644 --- a/src/main.c +++ b/src/main.c @@ -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");