#if !defined(LD_CORE_ARENA_H_) #define LD_CORE_ARENA_H_ #define AlignUp(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define AlignDown(x, a) (((x)) & ~((a) - 1)) #define KB(x) ((U64) (x) << 10) #define MB(x) ((U64) (x) << 20) #define GB(x) ((U64) (x) << 30) #if !defined(M_ARENA_CHAIN_RESERVE) #define M_ARENA_CHAIN_RESERVE MB(4) #endif function void *M_ZeroSize(void *base, U64 size); function void *M_CopySize(void *dst, void *src, U64 size); typedef U32 M_ArenaFlags; enum { // Arena is fixed size, so will not chain M_ARENA_FIXED_SIZE = (1 << 0), // Don't clear allocation M_ARENA_NO_ZERO = (1 << 1) }; typedef union M_Arena M_Arena; union M_Arena { struct { M_Arena *current; M_Arena *prev; U64 base; U64 limit; U64 offset; U64 committed; U64 increment; M_ArenaFlags flags; }; U8 __pad[64]; }; typedef struct M_ArenaOpts M_ArenaOpts; struct M_ArenaOpts { U64 initial; U64 increment; M_ArenaFlags flags; }; typedef struct M_ArenaPushOpts M_ArenaPushOpts; struct M_ArenaPushOpts { U64 count; U64 align; M_ArenaFlags flags; }; function M_Arena *_M_ArenaAlloc(U64 limit, M_ArenaOpts *opts); function void *_M_ArenaPush(M_Arena *arena, U64 esize, M_ArenaPushOpts *opts); function void *_M_ArenaPushCopy(M_Arena *arena, void *src, U64 esize, M_ArenaPushOpts *opts); #define M_ArenaAlloc(limit, ...) _M_ArenaAlloc(limit, &(M_ArenaOpts) { .initial = MB(1), .increment = KB(64), ##__VA_ARGS__ }) #define M_ArenaPush(arena, T, ...) (T *) _M_ArenaPush(arena, sizeof(T), &(M_ArenaPushOpts) { .count = 1, .align = Alignof(T), ##__VA_ARGS__ }) #define M_ArenaPushCopy(arena, T, src, ...) (T *) _M_ArenaPush(arena, src, sizeof(T), &(M_ArenaPushOpts) { .count = 1, .align = Alignof(T), ##__VA_ARGS__ }) function void M_ArenaReset(M_Arena *arena); function void M_ArenaRelease(M_Arena *arena); function U64 M_ArenaOffset(M_Arena *arena); function void M_ArenaPop(M_Arena *arena, U64 offset); function void M_ArenaPopSize(M_Arena *arena, U64 size); // Temporary memory typedef struct M_Temp M_Temp; struct M_Temp { M_Arena *arena; U64 offset; }; function M_Temp M_TempAcquire(U64 count, M_Arena **conflicts); function void M_TempRelease(M_Temp temp); #define M_TempScope(n, c) for (M_Temp temp = M_TempAcquire(n, c); temp.arena != 0; M_TempRelease(temp), temp.arena = 0) #endif // LD_CORE_ARENA_H_