Skip to content

Commit

Permalink
allocator: add arena_allocator
Browse files Browse the repository at this point in the history
This allocator uses Lua userdatas for dynamic allocation
that is automatically freed when the current scope exits.
  • Loading branch information
takase1121 authored and Guldoman committed Oct 22, 2024
1 parent 0966be6 commit 9293a31
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/arena_allocator.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "arena_allocator.h"

#include <string.h>
#include <lauxlib.h>

void lxl_arena_init(lua_State *L, lxl_arena *arena) {
lua_newtable(L);
arena->L = L; arena->ref = lua_gettop(L);
}

void *lxl_arena_malloc(lxl_arena *arena, size_t size) {
if (!arena || !arena->L) return NULL;
if (!lua_istable(arena->L, arena->ref)) luaL_error(arena->L, "invalid arena reference");
void *data = lua_newuserdata(arena->L, size);
lua_pushlightuserdata(arena->L, data);
lua_pushvalue(arena->L, -2);
lua_settable(arena->L, arena->ref);
lua_pop(arena->L, 1);
return data;
}

void *lxl_arena_zero(lxl_arena *arena, size_t size) {
void *v = lxl_arena_malloc(arena, size);
return v ? memset(v, 0, size) : NULL;
}

char *lxl_arena_strdup(lxl_arena *arena, const char *str) {
if (!str) return NULL;
return lxl_arena_copy(arena, (void *) str, (strlen(str) + 1) * sizeof(char));
}

char *lxl_arena_copy(lxl_arena *arena, void *ptr, size_t len) {
if (!ptr) return NULL;
char *output = lxl_arena_malloc(arena, sizeof(char) * len);
return output ? memcpy(output, ptr, len) : NULL;
}

void lxl_arena_free(lxl_arena *arena, void *ptr) {
if (!arena || !arena->L || !ptr) return;
if (!lua_istable(arena->L, arena->ref)) luaL_error(arena->L, "invalid arena reference");
lua_pushlightuserdata(arena->L, ptr);
lua_pushnil(arena->L);
lua_settable(arena->L, arena->ref);
}
25 changes: 25 additions & 0 deletions src/arena_allocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* An arena allocator using the Lua state; similar to luaL_Buffer.
* Initialize the arena with lxl_arena_init(), and you can use lxl_arena_malloc(),
* lxl_arena_zero() to allocate (and optionally zero) the memory.
* lxl_arena_free() can be optionally used to free memory, but this is generally not needed.
*/

#ifndef LUA_ALLOCATOR_H
#define LUA_ALLOCATOR_H

#include <lua.h>

typedef struct lxl_arena {
lua_State *L;
int ref;
} lxl_arena;

void lxl_arena_init(lua_State *L, lxl_arena *arena);
void *lxl_arena_malloc(lxl_arena *arena, size_t size);
void *lxl_arena_zero(lxl_arena *arena, size_t size);
char *lxl_arena_copy(lxl_arena *arena, void *ptr, size_t len);
char *lxl_arena_strdup(lxl_arena *arena, const char *str);
void lxl_arena_free(lxl_arena *arena, void *ptr);

#endif
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ lite_sources = [
'api/system.c',
'api/process.c',
'api/utf8.c',
'arena_allocator.c',
'renderer.c',
'renwindow.c',
'rencache.c',
Expand Down

0 comments on commit 9293a31

Please sign in to comment.