summaryrefslogtreecommitdiff
path: root/archive/src/std/mem.h
blob: 56c1230b0ae8867fe57803a123cd99c6b9c2d7a4 (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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
 * @file mem.h
 * @brief Allocators, memory tracking
 * @version 0.1
 * @date 2024-02-24
 *
 * @copyright Copyright (c) 2024
 *
 */
#pragma once

#include <stddef.h>
#include "defines.h"

typedef void* (*alloc_fn)(size_t size);
typedef void (*free_fn)(void* ptr);

typedef struct allocator_t {
  alloc_fn alloc;
  free_fn free;
} allocator_t;

// --- Arena

// Inspired by https://nullprogram.com/blog/2023/09/27/
typedef struct arena {
  char* begin;
  char* curr;
  char* end;
} arena;

typedef struct arena_save {
  arena* arena;
  char* savepoint;
} arena_save;

arena arena_create(void* backing_buffer, size_t capacity);
void* arena_alloc(arena* a, size_t size);
void* arena_alloc_align(arena* a, size_t size, size_t align);
void arena_free_all(arena* a);
void arena_free_storage(arena* a);
arena_save arena_savepoint(arena* a);
void arena_rewind(arena_save savepoint);
// TODO: arena_resize

// --- Pool

typedef struct void_pool_header void_pool_header;
struct void_pool_header {
  void_pool_header* next;
};

typedef struct void_pool {
  u64 capacity;
  u64 entry_size;
  u64 count;
  void* backing_buffer;
  void_pool_header* free_list_head;
  const char* debug_label;
} void_pool;

void_pool void_pool_create(arena* a, const char* debug_label, u64 capacity, u64 entry_size);
void void_pool_free_all(void_pool* pool);
bool void_pool_is_empty(void_pool* pool);
bool void_pool_is_full(void_pool* pool);
void* void_pool_get(void_pool* pool, u32 raw_handle);
void* void_pool_alloc(void_pool* pool, u32* out_raw_handle);
void void_pool_dealloc(void_pool* pool, u32 raw_handle);
u32 void_pool_insert(void_pool* pool, void* item);
// TODO: fn to dealloc from the pointer that was handed out

// TODO: macro that lets us specialise

/* typedef struct Name##_handle Name##_handle;      \ */
#define TYPED_POOL(T, Name)                                                         \
  typedef struct Name##_pool {                                                      \
    void_pool inner;                                                                \
  } Name##_pool;                                                                    \
                                                                                    \
  static Name##_pool Name##_pool_create(arena* a, u64 cap, u64 entry_size) {        \
    void_pool p = void_pool_create(a, "\"" #Name "\"", cap, entry_size);            \
    return (Name##_pool){ .inner = p };                                             \
  }                                                                                 \
  static inline T* Name##_pool_get(Name##_pool* pool, Name##Handle handle) {        \
    return (T*)void_pool_get(&pool->inner, handle.raw);                             \
  }                                                                                 \
  static inline T* Name##_pool_alloc(Name##_pool* pool, Name##Handle* out_handle) { \
    return (T*)void_pool_alloc(&pool->inner, &out_handle->raw);                     \
  }                                                                                 \
  static inline void Name##_pool_dealloc(Name##_pool* pool, Name##Handle handle) {  \
    void_pool_dealloc(&pool->inner, handle.raw);                                    \
  }                                                                                 \
  static Name##Handle Name##_pool_insert(Name##_pool* pool, T* item) {              \
    u32 raw_handle = void_pool_insert(pool, item);                                  \
    return (Name##Handle){ .raw = raw_handle };                                     \
  }