std1.0.0-beta-7 SafeC docs

Source alloc/pool.h

View in the repository

// SafeC Standard Library — Pool Allocator
// Variable-size first-fit allocator with coalescing on free.
// Each allocation is preceded by a PoolBlock header.
// Conforms to Allocator and ArenaAllocator (allocator.h): typed allocation
// is alloc_t / alloc_array_t / dealloc_t there.
#pragma once
#include <std/mem.h>
#include <std/alloc/allocator.h>

namespace std {

struct PoolBlock {
    unsigned long size;       // usable size (excluding header)
    int           is_free;    // 1 = free, 0 = allocated
    ?&PoolBlock   next;       // next block in the list (walked inside unsafe)
};

struct PoolAllocator {
    &heap unsigned char base;       // heap-backed managed memory
    int           owned;   // 1 if PoolAllocator::new allocated base (destroy() frees it)
    unsigned long cap;        // total buffer size
    ?&PoolBlock   head;       // first block in the list (walked inside unsafe)

    // A pool over a user-provided heap buffer (8-aligned) of `cap` bytes.
    static struct PoolAllocator over([]unsigned char buffer);

    // A heap-backed pool of `cap` bytes.
    static struct PoolAllocator new(unsigned long cap);

    // Allocate `size` bytes aligned to `align`. Every block is 8-aligned
    // (given an 8-aligned buffer: always for PoolAllocator::new), so align is honoured
    // up to 8 (0 is taken as 1). null if no free block fits, or `align` is
    // above 8 or not a power of two.
    ?&heap unsigned char alloc(unsigned long size, unsigned long align);

    // Free a previously allocated pointer (null: no-op). Coalesces adjacent
    // free blocks. Aborts with a diagnostic on a double free.
    void          dealloc(?&heap unsigned char ptr);

    // Free every block at once: the whole buffer is one free block again
    // (blocks handed out before become invalid).
    void          reset();

    // Return total free bytes (sum of all free blocks).
    unsigned long available() const;

    // Free the backing buffer (only valid for heap-backed allocators from PoolAllocator::new).
    void          drop();
    void          destroy() consume;   // = drop()

    // Internal: return the fixed header size in bytes.
    unsigned long header_size_() const;
};

} // namespace std