//////////////////////////////////////////////////////////// //~ Arena types #define ArenaHeaderSize 256 #define ArenaBlockSize 16384 Struct(ThreadLocalArenaCtx) { Arena *perm; Arena *scratch[2]; }; //////////////////////////////////////////////////////////// //~ Arena management Arena *AcquireArena(u64 reserve); void ReleaseArena(Arena *arena); void CopyArena(Arena *dst, Arena *src); void ShrinkArena(Arena *arena); void SetArenaReadonly(Arena *arena); void SetArenaReadWrite(Arena *arena); void *ResetArena(Arena *arena); //////////////////////////////////////////////////////////// //~ Push / pop #define PushStructs(a, type, n) ((type *)PushBytes((a), (sizeof(type) * (n)), alignof(type))) #define PushStruct(a, type) PushStructs((a), type, 1) #define PushStructsNoZero(a, type, n) ((type *)PushBytesNoZero((a), (sizeof(type) * (n)), alignof(type))) #define PushStructNoZero(a, type) PushStructsNoZero((a), type, 1) #define PopStructs(a, type, dst, n) PopBytes((a), sizeof(type) * (n), dst) #define PopStruct(a, type, dst) PopStructs((a), type, (dst), 1) #define PopStructsNoCopy(a, type, n) PopBytesNoCopy((a), sizeof(type) * (n)) #define PopStructNoCopy(a, type) PopStructsNoCopy((a), type, 1) #define ArenaFirst(arena, type) ((type *)ArenaFirst_((arena), alignof(type))) #define ArenaNext(arena, type) ((type *)ArenaNext_((arena), alignof(type))) #define ArenaCount(arena, type) ((arena)->pos / sizeof(type)) void *PushBytesNoZero(Arena *arena, u64 size, u64 align); void *PushBytes(Arena *arena, u64 size, u64 align); void *PushAlign(Arena *arena, u64 align); void PopTo(Arena *arena, u64 pos); void PopBytesNoCopy(Arena *arena, u64 size); void PopBytes(Arena *arena, u64 size, void *copy_dst); void *ArenaNext_(Arena *arena, u64 align); void *ArenaFirst_(Arena *arena, u64 align); //////////////////////////////////////////////////////////// //~ Thread arena helpers TempArena BeginTempArena(Arena *arena); void EndTempArena(TempArena temp); #define PermArena() (Base_tl.arenas.perm) //////////////////////////////////////////////////////////// //~ Scratch arena helpers TempArena BeginScratch(Arena *potential_conflict); TempArena BeginScratchNoConflict_(void); void EndScratch(TempArena scratch_temp); // This macro declares an unused "arena" variable that will produce a shadowing // warning variable is present (due to shadowing). This is for catching obvious // cases of `BeginScratchNoConflict` getting called when an `arena` variable // already exists in the caller's scope. #define BeginScratchNoConflict() \ BeginScratchNoConflict_(); \ do { \ u8 arena = 0; \ } while (0)