Skip to content
BudgetAllocatorInit

BudgetAllocatorInit

Description

Initialize a BudgetAllocator over a caller-owned memory region. Carves buf into a [bitmap | pad | slots] layout: the bitmap is u64-aligned at the head; slots are sizeof(void *)-aligned and padded up to sizeof(void *). The bitmap region is zeroed in place as part of init.

Side-effect-free args only – buf, buf_bytes, and slot_size are each evaluated multiple times inside the layout arithmetic.

Parameters

Name Direction Description
buf in,out Caller-owned memory region used as backing storage.
buf_bytes in Size of buf in bytes.
slot_size in Allocation size class served by this allocator.

Success

Returns a fully-initialized BudgetAllocator value with bitmap zeroed.

Failure

Aborts via LOG_FATAL when buf is NULL, buf_bytes or slot_size is 0, or the buffer is too small for the bitmap word plus one padded slot. The fatal log points at the caller’s source line.

Usage example (Cross-references)

Usage examples (Cross-references)
    ///
    #define BudgetAllocatorInitAligned(buf_ptr, total_bytes, slot_size_bytes, alignment_value)                             \
        (ASSERT_OR_FATAL((buf_ptr) != NULL, "BudgetAllocatorInit: NULL buf"),                                              \
         ASSERT_OR_FATAL((total_bytes) > 0, "BudgetAllocatorInit: zero buf_bytes"),                                        \
         ASSERT_OR_FATAL((slot_size_bytes) > 0, "BudgetAllocatorInit: zero slot_size"),                                    \
    #define BudgetAllocatorInitAligned(buf_ptr, total_bytes, slot_size_bytes, alignment_value)                             \
        (ASSERT_OR_FATAL((buf_ptr) != NULL, "BudgetAllocatorInit: NULL buf"),                                              \
         ASSERT_OR_FATAL((total_bytes) > 0, "BudgetAllocatorInit: zero buf_bytes"),                                        \
         ASSERT_OR_FATAL((slot_size_bytes) > 0, "BudgetAllocatorInit: zero slot_size"),                                    \
         ASSERT_OR_FATAL(                                                                                                  \
        (ASSERT_OR_FATAL((buf_ptr) != NULL, "BudgetAllocatorInit: NULL buf"),                                              \
         ASSERT_OR_FATAL((total_bytes) > 0, "BudgetAllocatorInit: zero buf_bytes"),                                        \
         ASSERT_OR_FATAL((slot_size_bytes) > 0, "BudgetAllocatorInit: zero slot_size"),                                    \
         ASSERT_OR_FATAL(                                                                                                  \
             (alignment_value) >= sizeof(void *) && ((alignment_value) & ((alignment_value) - 1)) == 0,                    \
         ASSERT_OR_FATAL(                                                                                                  \
             (alignment_value) >= sizeof(void *) && ((alignment_value) & ((alignment_value) - 1)) == 0,                    \
             "BudgetAllocatorInit: alignment must be a power of two >= sizeof(void *)"                                     \
         ),                                                                                                                \
         ASSERT_OR_FATAL(                                                                                                  \
             (size)(total_bytes) >= (size)(ALIGN_UP_POW2((u64)(buf_ptr), 8u) - (u64)(buf_ptr)) + sizeof(u64) +             \
                                        ALIGN_UP_POW2((slot_size_bytes), (alignment_value)) + ((alignment_value) - 1),     \
             "BudgetAllocatorInit: buffer too small for bitmap + one padded slot"                                          \
         ),                                                                                                                \
         MemSet(                                                                                                           \
    static bool test_basic_alloc_and_free(void) {
        u8              buf[1024] = {0};
        BudgetAllocator bp        = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc     = ALLOCATOR_OF(&bp);
        Node           *a         = (Node *)AllocatorAlloc(alloc, sizeof(Node), true);
    static bool test_zero_byte_alloc_returns_null(void) {
        u8              buf[256] = {0};
        BudgetAllocator bp       = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc    = ALLOCATOR_OF(&bp);
        void           *p        = AllocatorAlloc(alloc, 0, false);
    static bool test_free_null_is_noop(void) {
        u8              buf[256] = {0};
        BudgetAllocator bp       = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc    = ALLOCATOR_OF(&bp);
        AllocatorFree(alloc, NULL);
    static bool test_fails_when_empty(void) {
        u8              buf[256] = {0};
        BudgetAllocator bp       = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc    = ALLOCATOR_OF(&bp);
    static bool test_free_then_alloc_recycles(void) {
        u8              buf[1024] = {0};
        BudgetAllocator bp        = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc     = ALLOCATOR_OF(&bp);
    static bool test_alloc_distinct_pointers(void) {
        u8              buf[1024] = {0};
        BudgetAllocator bp        = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc     = ALLOCATOR_OF(&bp);
    static bool test_oversized_request_fails(void) {
        u8              buf[256] = {0};
        BudgetAllocator bp       = BudgetAllocatorInit(buf, sizeof(buf), sizeof(int));
        Allocator      *alloc    = ALLOCATOR_OF(&bp);
        void           *big      = AllocatorAlloc(alloc, 4096, true);
        // line. A passing deadend is one where the abort fired.
        u8              buf[4] = {0};
        BudgetAllocator bp     = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        BudgetAllocatorDeinit(&bp);
        return false;
        u8              buf1[1024] = {0};
        u8              buf2[1024] = {0};
        BudgetAllocator bp1        = BudgetAllocatorInit(buf1, sizeof(buf1), sizeof(Node));
        BudgetAllocator bp2        = BudgetAllocatorInit(buf2, sizeof(buf2), sizeof(Node));
        Allocator      *alloc1     = ALLOCATOR_OF(&bp1);
        u8              buf2[1024] = {0};
        BudgetAllocator bp1        = BudgetAllocatorInit(buf1, sizeof(buf1), sizeof(Node));
        BudgetAllocator bp2        = BudgetAllocatorInit(buf2, sizeof(buf2), sizeof(Node));
        Allocator      *alloc1     = ALLOCATOR_OF(&bp1);
        Allocator      *alloc2     = ALLOCATOR_OF(&bp2);
        // Pointer to bitmap region (front of buf) must be rejected as foreign.
        u8              buf[1024] = {0};
        BudgetAllocator bp        = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc     = ALLOCATOR_OF(&bp);
    static bool test_reject_misaligned_pointer(void) {
        u8              buf[1024] = {0};
        BudgetAllocator bp        = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc     = ALLOCATOR_OF(&bp);
        char           *p         = (char *)AllocatorAlloc(alloc, sizeof(Node), false);
    static bool test_reject_double_free(void) {
        u8              buf[1024] = {0};
        BudgetAllocator bp        = BudgetAllocatorInit(buf, sizeof(buf), sizeof(Node));
        Allocator      *alloc     = ALLOCATOR_OF(&bp);
        Node           *p         = (Node *)AllocatorAlloc(alloc, sizeof(Node), false);
        // is far too small for the string's backing buffer, so allocation fails.
        u8              buf[64] = {0};
        BudgetAllocator bp      = BudgetAllocatorInit(buf, sizeof(buf), 8);
    
        Str          s      = StrInit(&bp);
    
        u8              buf[64] = {0};
        BudgetAllocator bp      = BudgetAllocatorInit(buf, sizeof(buf), 8);
    
        Str            s      = StrInit(&bp);
    
        u8              buf[512] = {0};
        BudgetAllocator bp       = BudgetAllocatorInit(buf, sizeof(buf), 8);
    
        Str            s      = StrInit(&bp);
Last updated on