Skip to content

Instantly share code, notes, and snippets.

@rexim
Created February 1, 2021 14:58
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rexim/2950df35b6e97364ba849469df9fc044 to your computer and use it in GitHub Desktop.
Save rexim/2950df35b6e97364ba849469df9fc044 to your computer and use it in GitHub Desktop.
Region-based memory management
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct Region Region;
struct Region {
Region *next;
size_t capacity;
size_t size;
char buffer[];
};
Region *region_create(size_t capacity)
{
const size_t region_size = sizeof(Region) + capacity;
Region *region = malloc(region_size);
memset(region, 0, region_size);
region->capacity = capacity;
return region;
}
typedef struct {
size_t capacity;
Region *first;
Region *last;
} Arena;
void *arena_alloc(Arena *arena, size_t size)
{
if (arena->last == NULL) {
assert(arena->first == NULL);
Region *region = region_create(
size > arena->capacity ? size : arena->capacity);
arena->last = region;
arena->first = region;
}
while (arena->last->size + size > arena->last->capacity &&
arena->last->next) {
arena->last = arena->last->next;
}
if (arena->last->size + size > arena->last->capacity) {
Region *region = region_create(
size > arena->capacity ? size : arena->capacity);
arena->last->next = region;
arena->last = region;
}
void *result = arena->last->buffer + arena->last->size;
arena->last->size += size;
return result;
}
void *arena_clean(Arena *arena)
{
for (Region *iter = arena->first;
iter != NULL;
iter = iter->next)
{
iter->size = 0;
}
arena->last = arena->first;
}
void arena_free(Arena *arena)
{
Region *iter = arena->first;
while (iter != NULL) {
Region *next = iter->next;
free(iter);
iter = next;
}
arena->first = NULL;
arena->last = NULL;
}
void arena_summary(Arena *arena)
{
if (arena->first == NULL) {
printf("[empty]");
}
for (Region *iter = arena->first;
iter != NULL;
iter = iter->next)
{
printf("[%d/%d] -> ", iter->size, iter->capacity);
}
printf("\n");
}
int main(int argc, char *argv[])
{
Arena arena = {.capacity = 640 * 1000};
arena_summary(&arena);
arena_alloc(&arena, 35);
arena_summary(&arena);
arena_alloc(&arena, 5);
arena_summary(&arena);
arena_alloc(&arena, 29);
arena_summary(&arena);
arena_alloc(&arena, 1);
arena_summary(&arena);
arena_alloc(&arena, 70);
arena_summary(&arena);
arena_clean(&arena);
arena_summary(&arena);
arena_alloc(&arena, 35);
arena_summary(&arena);
arena_free(&arena);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment