aboutsummaryrefslogtreecommitdiff
path: root/src/tilde/tb_arena.h
blob: 67ec0e1813f44f197f12d495ad44f429adbd230a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#pragma once
#include <stddef.h>
#include <stdbool.h>

#ifndef TB_API
#  ifdef __cplusplus
#    define TB_EXTERN extern "C"
#  else
#    define TB_EXTERN
#  endif
#  ifdef TB_DLL
#    ifdef TB_IMPORT_DLL
#      define TB_API TB_EXTERN __declspec(dllimport)
#    else
#      define TB_API TB_EXTERN __declspec(dllexport)
#    endif
#  else
#    define TB_API TB_EXTERN
#  endif
#endif

enum {
    TB_ARENA_SMALL_CHUNK_SIZE  =         4 * 1024,
    TB_ARENA_MEDIUM_CHUNK_SIZE =       512 * 1024,
    TB_ARENA_LARGE_CHUNK_SIZE  = 16 * 1024 * 1024,

    TB_ARENA_ALIGNMENT = 16,
};

typedef struct TB_ArenaChunk TB_ArenaChunk;
struct TB_ArenaChunk {
    TB_ArenaChunk* next;
    size_t pad;
    char data[];
};

typedef struct TB_Arena {
    size_t chunk_size;
    TB_ArenaChunk* base;
    TB_ArenaChunk* top;

    // top of the allocation space
    char* watermark;
    char* high_point; // &top->data[chunk_size]
} TB_Arena;

typedef struct TB_ArenaSavepoint {
    TB_ArenaChunk* top;
    char* watermark;
} TB_ArenaSavepoint;

#define TB_ARENA_FOR(it, arena) for (TB_ArenaChunk* it = (arena)->base; it != NULL; it = it->next)

#define TB_ARENA_ALLOC(arena, T) tb_arena_alloc(arena, sizeof(T))
#define TB_ARENA_ARR_ALLOC(arena, count, T) tb_arena_alloc(arena, (count) * sizeof(T))

TB_API void tb_arena_create(TB_Arena* restrict arena, size_t chunk_size);
TB_API void tb_arena_destroy(TB_Arena* restrict arena);

TB_API void* tb_arena_unaligned_alloc(TB_Arena* restrict arena, size_t size);
TB_API void* tb_arena_alloc(TB_Arena* restrict arena, size_t size);

// return false on failure
TB_API bool tb_arena_free(TB_Arena* restrict arena, void* ptr, size_t size);
TB_API void tb_arena_pop(TB_Arena* restrict arena, void* ptr, size_t size);

// in case you wanna mix unaligned and aligned arenas
TB_API void tb_arena_realign(TB_Arena* restrict arena);

TB_API bool tb_arena_is_empty(TB_Arena* arena);

TB_API size_t tb_arena_current_size(TB_Arena* arena);

// savepoints
TB_API TB_ArenaSavepoint tb_arena_save(TB_Arena* arena);
TB_API void tb_arena_restore(TB_Arena* arena, TB_ArenaSavepoint sp);

// resets to only having one chunk
TB_API void tb_arena_clear(TB_Arena* arena);