infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
arena.c
Go to the documentation of this file.
1
37#include <stdint.h>
38#include <stdlib.h>
39#include <string.h>
53 // Use calloc to ensure the initial struct state is zeroed.
55 if (arena == nullptr) {
57 return nullptr;
58 }
59 arena->buffer = infix_calloc(1, initial_size);
60 if (arena->buffer == nullptr && initial_size > 0) {
63 return nullptr;
64 }
65 arena->capacity = initial_size;
67 arena->error = false;
68 arena->next_block = nullptr;
69 arena->block_size = initial_size;
70 return arena;
71}
84 if (arena == nullptr)
85 return;
86 // Traverse the chain of blocks and free each one.
87 infix_arena_t * current = arena;
88 while (current != nullptr) {
89 infix_arena_t * next = current->next_block;
90 if (current->buffer)
91 infix_free(current->buffer);
92 infix_free(current);
93 current = next;
94 }
95}
117c23_nodiscard void * infix_arena_alloc(infix_arena_t * arena, size_t size, size_t alignment) {
118 if (arena == nullptr)
119 return nullptr;
120 // Alignment must be a power of two for the bitwise alignment trick to work.
121 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
122 arena->error = true;
124 return nullptr;
125 }
126 infix_arena_t * current_block = arena;
127 while (true) { // Loop until allocation succeeds or fails definitively.
128 if (current_block->error)
129 return nullptr;
130 if (size == 0)
131 return (void *)(current_block->buffer + current_block->current_offset);
132 size_t aligned_offset = _infix_align_up(current_block->current_offset, alignment);
133 if (aligned_offset < current_block->current_offset) {
134 current_block->error = true;
136 return nullptr;
137 }
138 // Attempt to allocate in the current block.
139 if (SIZE_MAX - size >= aligned_offset && aligned_offset + size <= current_block->capacity) {
140 void * ptr = current_block->buffer + aligned_offset;
141 current_block->current_offset = aligned_offset + size;
142 return ptr; // Success: Allocation complete.
143 }
144 // If allocation failed, find or create the next block and let the loop retry.
145 if (current_block->next_block != nullptr) {
146 current_block = current_block->next_block;
147 }
148 else {
149 // Reached the end of the chain, so create a new block.
150 size_t next_size = current_block->block_size * 2;
151 if (next_size < size + alignment)
152 next_size = size + alignment;
153 current_block->next_block = infix_arena_create(next_size);
154 if (current_block->next_block == nullptr) {
155 current_block->error = true; // Mark the last valid block as errored.
156 return nullptr; // Growth failed.
157 }
158 current_block = current_block->next_block;
159 }
160 }
161 // This line should be unreachable if the logic is correct.
162 return nullptr;
163}
179c23_nodiscard void * infix_arena_calloc(infix_arena_t * arena, size_t num, size_t size, size_t alignment) {
180 // Security: Check for multiplication overflow.
181 if (size > 0 && num > SIZE_MAX / size) {
182 if (arena)
183 arena->error = true;
185 return nullptr;
186 }
187 size_t total_size = num * size;
188 void * ptr = infix_arena_alloc(arena, total_size, alignment);
189 if (ptr != nullptr)
190 memset(ptr, 0, total_size);
191 return ptr;
192}
infix_arena_t * arena
Definition 005_layouts.c:60
#define c23_nodiscard
A compatibility macro for the C23 [[nodiscard]] attribute.
Definition compat_c23.h:106
@ INFIX_CODE_INTEGER_OVERFLOW
Definition infix.h:1236
@ INFIX_CODE_UNKNOWN
Definition infix.h:1226
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1228
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1216
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1215
#define infix_free
A macro that can be defined to override the default free function.
Definition infix.h:301
void infix_arena_destroy(infix_arena_t *arena)
Destroys an arena and frees all memory allocated from it.
Definition arena.c:83
#define infix_calloc
A macro that can be defined to override the default calloc function.
Definition infix.h:293
c23_nodiscard void * infix_arena_calloc(infix_arena_t *arena, size_t num, size_t size, size_t alignment)
Allocates and zero-initializes a block of memory from an arena.
Definition arena.c:179
c23_nodiscard void * infix_arena_alloc(infix_arena_t *arena, size_t size, size_t alignment)
Allocates a block of memory from an arena.
Definition arena.c:117
c23_nodiscard infix_arena_t * infix_arena_create(size_t initial_size)
Creates a new memory arena.
Definition arena.c:52
Internal data structures, function prototypes, and constants.
void _infix_set_error(infix_error_category_t category, infix_error_code_t code, size_t position)
Sets the thread-local error state with detailed information.
Definition error.c:165
static size_t _infix_align_up(size_t value, size_t alignment)
Aligns a value up to the next multiple of a power-of-two alignment.
Definition infix_internals.h:727
Internal definition of a memory arena.
Definition infix_internals.h:138
char * buffer
Definition infix_internals.h:139
bool error
Definition infix_internals.h:142
size_t capacity
Definition infix_internals.h:140
size_t block_size
Definition infix_internals.h:144
size_t current_offset
Definition infix_internals.h:141
struct infix_arena_t * next_block
Definition infix_internals.h:143