179 lines
3.4 KiB
C
179 lines
3.4 KiB
C
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
|
|
#define ARENA_MEMORY_ALIGN 8
|
|
|
|
typedef struct Chunk{
|
|
size_t size;
|
|
size_t offset;
|
|
unsigned char *buffer;
|
|
struct Chunk *next;
|
|
}Chunk;
|
|
|
|
typedef struct{
|
|
Chunk *current;
|
|
Chunk *first;
|
|
}Arena;
|
|
|
|
Arena arena_create(size_t);
|
|
void* arena_alloc(Arena*, size_t);
|
|
void arena_free(Arena*);
|
|
void arena_print(Arena*);
|
|
|
|
Chunk* arena_chunk_create(size_t);
|
|
void arena_chunk_free(Chunk*);
|
|
void* arena_chunk_alloc(Arena*, Chunk*, size_t);
|
|
|
|
int main(void){
|
|
|
|
Arena arena = arena_create(32);
|
|
|
|
arena_print(&arena);
|
|
|
|
arena_alloc(&arena, 100);
|
|
|
|
arena_print(&arena);
|
|
|
|
arena_alloc(&arena, 40);
|
|
|
|
arena_print(&arena);
|
|
|
|
arena_free(&arena);
|
|
|
|
arena_print(&arena);
|
|
return 0;
|
|
}
|
|
|
|
void* arena_chunk_alloc(Arena* ref_arena, Chunk* chunk, size_t s){
|
|
size_t aligned = (chunk->offset + (ARENA_MEMORY_ALIGN - 1)) & ~(ARENA_MEMORY_ALIGN -1);
|
|
if ((aligned + s <= chunk->size)){
|
|
chunk->offset = aligned;
|
|
void* start = (void *)(chunk->buffer + chunk->offset);
|
|
chunk->offset = aligned + s;
|
|
return start;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
Chunk* arena_chunk_create(size_t s){
|
|
printf("Creating a new chunk of %zu bytes\n", s);
|
|
Chunk* chunk1 = (Chunk*)malloc(sizeof(Chunk));
|
|
|
|
if(chunk1 == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
chunk1->size = s;
|
|
chunk1->offset = 0;
|
|
chunk1->next = NULL;
|
|
|
|
chunk1->buffer = (unsigned char *)malloc(s);
|
|
|
|
if(chunk1->buffer == NULL){
|
|
perror("Error creando chunk...\n");
|
|
free(chunk1);
|
|
chunk1 = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
printf("Chunk creado correctamente\n");
|
|
|
|
return chunk1;
|
|
|
|
}
|
|
|
|
void arena_chunk_free(Chunk* chunk){
|
|
printf("Liberando %zu bytes de memoria\n", chunk->size);
|
|
if(chunk->buffer != NULL){
|
|
free(chunk->buffer);
|
|
chunk->buffer = NULL;
|
|
}
|
|
free(chunk);
|
|
}
|
|
|
|
void* arena_alloc(Arena* ref_arena, size_t s){
|
|
if(ref_arena == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
if(ref_arena->current == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
Chunk* current_chunk = ref_arena->current;
|
|
|
|
void* ptr = arena_chunk_alloc(ref_arena, current_chunk, s);
|
|
|
|
if(ptr == NULL){
|
|
|
|
size_t new_size = current_chunk->size * 2;
|
|
|
|
if(new_size < s){
|
|
new_size = s;
|
|
}
|
|
|
|
Chunk *new_chunk = arena_chunk_create(new_size);
|
|
if(new_chunk == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
current_chunk->next = new_chunk;
|
|
new_chunk->next = NULL;
|
|
ref_arena->current = new_chunk;
|
|
|
|
return arena_alloc(ref_arena, s);
|
|
}
|
|
|
|
return ptr;
|
|
|
|
|
|
}
|
|
|
|
Arena arena_create(size_t s){
|
|
Arena new_arena = {
|
|
.current = NULL,
|
|
.first = NULL
|
|
};
|
|
|
|
Chunk* chunk1 = arena_chunk_create(s);
|
|
|
|
if(chunk1 == NULL){
|
|
perror("Error creando arena\n");
|
|
exit(1);
|
|
}
|
|
|
|
new_arena.current = chunk1;
|
|
new_arena.first = chunk1;
|
|
|
|
printf("Arena creada correctamente\n");
|
|
|
|
return new_arena;
|
|
|
|
}
|
|
|
|
void arena_free(Arena* ref_arena){
|
|
Chunk* item = ref_arena->first;
|
|
while (item != NULL) {
|
|
Chunk *next = item->next;
|
|
arena_chunk_free(item);
|
|
item = next;
|
|
}
|
|
|
|
ref_arena->first = NULL;
|
|
ref_arena->current = NULL;
|
|
|
|
printf("Arena liberada\n");
|
|
}
|
|
|
|
void arena_print(Arena* ref_arena){
|
|
printf("ARENA INFO\n");
|
|
printf("==========\n");
|
|
|
|
printf("first: %p\n", ref_arena->first);
|
|
printf("next: %p\n", ref_arena->current);
|
|
|
|
printf("==========\n");
|
|
}
|