'PushDry' -> 'ArenaNext'

This commit is contained in:
jacob 2025-11-07 18:30:18 -06:00
parent a94e62e023
commit d9b487cea2
12 changed files with 228 additions and 222 deletions

View File

@ -1,6 +1,8 @@
SharedArenaCtx shared_arena_ctx = ZI;
/* NOTE: Application will exit if arena fails to reserve or commit initial memory. */
////////////////////////////////////////////////////////////
//~ Arena management
Arena *AcquireArena(u64 reserve)
{
__prof;
@ -58,11 +60,46 @@ void ReleaseArena(Arena *arena)
ReleaseMemory(arena);
}
/* NOTE: Application will exit if arena fails to commit memory */
/* Copy the memory from src to dst, replacing old contents.
* Dst will expand if necessary. */
void CopyArena(Arena *dst, Arena *src)
{
ResetArena(dst);
u64 data_size = src->pos;
u8 *data_src = ArenaFirst(src, u8);
u8 *data_dst = PushBytesNoZero(dst, data_size, 1);
CopyBytes(data_dst, data_src, data_size);
}
void ShrinkArena(Arena *arena)
{
/* Not implemented */
Assert(0);
LAX arena;
}
void SetArenaReadonly(Arena *arena)
{
SetMemoryReadonly(arena, arena->committed + ArenaHeaderSize);
}
void SetArenaReadWrite(Arena *arena)
{
SetMemoryReadWrite(arena, arena->committed + ArenaHeaderSize);
}
void *ResetArena(Arena *arena)
{
PopTo(arena, 0);
return ArenaFirst(arena, u8);
}
////////////////////////////////////////////////////////////
//~ Push / pop
void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
{
Assert(align > 0);
Assert(!arena->readonly);
void *ptr = 0;
u8 *base = ArenaFirst(arena, u8);
@ -111,36 +148,144 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
return ptr;
}
/* Copies the memory from the source arena into the destination arena,
* replacing old contents. Destination arena will be expanded if necessary. */
void CopyArena(Arena *dst, Arena *src)
void *PushBytes(Arena *arena, u64 size, u64 align)
{
ResetArena(dst);
u64 data_size = src->pos;
u8 *data_src = ArenaFirst(src, u8);
u8 *data_dst = PushBytesNoZero(dst, data_size, 1);
CopyBytes(data_dst, data_src, data_size);
void *p = PushBytesNoZero(arena, size, align);
ZeroBytes(p, size);
return p;
}
void ShrinkArena(Arena *arena)
void *PushAlign(Arena *arena, u64 align)
{
/* Not implemented */
if (align > 0)
{
u64 aligned_start_pos = (arena->pos + (align - 1));
aligned_start_pos -= aligned_start_pos % align;
u64 align_bytes = aligned_start_pos - (u64)arena->pos;
if (align_bytes > 0)
{
return (void *)PushStructsNoZero(arena, u8, align_bytes);
}
else
{
return (void *)(ArenaFirst(arena, u8) + arena->pos);
}
}
else
{
/* 0 alignment */
Assert(0);
LAX arena;
return (void *)(ArenaFirst(arena, u8) + arena->pos);
}
}
void SetArenaReadonly(Arena *arena)
void PopTo(Arena *arena, u64 pos)
{
#if RtcIsEnabled
arena->readonly = 1;
#endif
SetMemoryReadonly(arena, arena->committed + ArenaHeaderSize);
Assert(arena->pos >= pos);
AsanPoison(ArenaFirst(arena, u8) + pos, arena->pos - pos);
arena->pos = pos;
}
void SetArenaReadWrite(Arena *arena)
void PopBytesNoCopy(Arena *arena, u64 size)
{
SetMemoryReadWrite(arena, arena->committed + ArenaHeaderSize);
#if RtcIsEnabled
arena->readonly = 0;
#endif
Assert(arena->pos >= size);
u64 new_pos = arena->pos - size;
AsanPoison(ArenaFirst(arena, u8) + new_pos, arena->pos - new_pos);
arena->pos = new_pos;
}
void PopBytes(Arena *arena, u64 size, void *copy_dst)
{
Assert(arena->pos >= size);
u64 new_pos = arena->pos - size;
void *src = (void *)(ArenaFirst(arena, u8) + new_pos);
CopyBytes(copy_dst, src, size);
AsanPoison(ArenaFirst(arena, u8) + new_pos, arena->pos - new_pos);
arena->pos = new_pos;
}
void *ArenaFirst_(Arena *arena, u64 align)
{
u64 aligned_start_pos = align - 1;
aligned_start_pos -= aligned_start_pos % align;
void *ptr = ((u8 *)arena + ArenaHeaderSize) + aligned_start_pos;
return ptr;
}
void *ArenaNext_(Arena *arena, u64 align)
{
u64 aligned_start_pos = (arena->pos + (align - 1));
aligned_start_pos -= aligned_start_pos % align;
void *ptr = ((u8 *)arena + ArenaHeaderSize) + aligned_start_pos;
return ptr;
}
////////////////////////////////////////////////////////////
//~ Temp arena helpers
TempArena BeginTempArena(Arena *arena)
{
TempArena t = ZI;
t.arena = arena;
t.start_pos = arena->pos;
return t;
}
void EndTempArena(TempArena temp)
{
PopTo(temp.arena, temp.start_pos);
}
////////////////////////////////////////////////////////////
//~ Fiber arena helpers
FiberArenaCtx *FiberArenaCtxFromId(i16 fiber_id)
{
SharedArenaCtx *g = &shared_arena_ctx;
FiberArenaCtx *ctx = &g->arena_contexts[fiber_id];
if (!ctx->perm_arena)
{
__profn("Initialize fiber arena ctx");
ctx->perm_arena = AcquireArena(Gibi(64));
for (i32 i = 0; i < (i32)countof(ctx->scratch_arenas); ++i)
{
ctx->scratch_arenas[i] = AcquireArena(Gibi(64));
}
}
return ctx;
}
////////////////////////////////////////////////////////////
//~ Scratch arena helpers
TempArena BeginScratch(Arena *potential_conflict)
{
/* This function is currently hard-coded to search through 2 scratch arenas */
StaticAssert(ScratchArenasPerCtx == 2);
/* Use `BeginScratchNoConflict` if no conflicts are present */
Assert(potential_conflict != 0);
FiberArenaCtx *ctx = FiberArenaCtxFromId(FiberId());
Arena *scratch_arena = ctx->scratch_arenas[0];
if (scratch_arena == potential_conflict)
{
scratch_arena = ctx->scratch_arenas[1];
}
TempArena temp = BeginTempArena(scratch_arena);
return temp;
}
TempArena BeginScratchNoConflict_(void)
{
FiberArenaCtx *ctx = FiberArenaCtxFromId(FiberId());
Arena *scratch_arena = ctx->scratch_arenas[0];
TempArena temp = BeginTempArena(scratch_arena);
return temp;
}
void EndScratch(TempArena scratch_temp)
{
EndTempArena(scratch_temp);
}

View File

@ -9,19 +9,12 @@ Struct(Arena)
u64 pos;
u64 committed;
u64 reserved;
#if RtcIsEnabled
b32 readonly;
#endif
};
Struct(TempArena)
{
Arena *arena;
u64 start_pos;
#if RtcIsEnabled
u64 scratch_id;
#endif
};
////////////////////////////////////////////////////////////
@ -41,7 +34,19 @@ Struct(SharedArenaCtx)
} extern shared_arena_ctx;
////////////////////////////////////////////////////////////
//~ Arena push/pop
//~ 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)
@ -55,190 +60,46 @@ Struct(SharedArenaCtx)
#define PopStructsNoCopy(a, type, n) PopBytesNoCopy((a), sizeof(type) * (n))
#define PopStructNoCopy(a, type) PopStructsNoCopy((a), type, 1)
#define ArenaFirst(arena, type) (type *)((u8 *)(arena) + ArenaHeaderSize)
#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))
/* Returns a pointer to where the next push would be (at alignment of type).
* Equivalent to PushStruct but without actually allocating anything or modifying the arena. */
#define PushDry(a, type) (type *)(_PushDry((a), alignof(type)))
void *PushBytesNoZero(Arena *arena, u64 size, u64 align);
void *PushBytes(Arena *arena, u64 size, u64 align);
void *PushAlign(Arena *arena, u64 align);
Inline void *PushBytes(Arena *arena, u64 size, u64 align)
{
void *p = PushBytesNoZero(arena, size, align);
ZeroBytes(p, size);
return p;
}
void PopTo(Arena *arena, u64 pos);
void PopBytesNoCopy(Arena *arena, u64 size);
void PopBytes(Arena *arena, u64 size, void *copy_dst);
Inline void PopTo(Arena *arena, u64 pos)
{
Assert(arena->pos >= pos);
Assert(!arena->readonly);
AsanPoison(ArenaFirst(arena, u8) + pos, arena->pos - pos);
arena->pos = pos;
}
Inline void PopBytesNoCopy(Arena *arena, u64 size)
{
Assert(arena->pos >= size);
Assert(!arena->readonly);
u64 new_pos = arena->pos - size;
AsanPoison(ArenaFirst(arena, u8) + new_pos, arena->pos - new_pos);
arena->pos = new_pos;
}
Inline void PopBytes(Arena *arena, u64 size, void *copy_dst)
{
Assert(arena->pos >= size);
Assert(!arena->readonly);
u64 new_pos = arena->pos - size;
void *src = (void *)(ArenaFirst(arena, u8) + new_pos);
CopyBytes(copy_dst, src, size);
AsanPoison(ArenaFirst(arena, u8) + new_pos, arena->pos - new_pos);
arena->pos = new_pos;
}
Inline void *_PushDry(Arena *arena, u64 align)
{
u64 aligned_start_pos = (arena->pos + (align - 1));
aligned_start_pos -= aligned_start_pos % align;
void *ptr = ArenaFirst(arena, u8) + aligned_start_pos;
return ptr;
}
void *ArenaNext_(Arena *arena, u64 align);
void *ArenaFirst_(Arena *arena, u64 align);
////////////////////////////////////////////////////////////
//~ Arena management
//~ Temp arena helpers
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);
Inline void *PushAlign(Arena *arena, u64 align)
{
Assert(!arena->readonly);
if (align > 0)
{
u64 aligned_start_pos = (arena->pos + (align - 1));
aligned_start_pos -= aligned_start_pos % align;
u64 align_bytes = aligned_start_pos - (u64)arena->pos;
if (align_bytes > 0)
{
return (void *)PushStructsNoZero(arena, u8, align_bytes);
}
else
{
return (void *)(ArenaFirst(arena, u8) + arena->pos);
}
}
else
{
/* 0 alignment */
Assert(0);
return (void *)(ArenaFirst(arena, u8) + arena->pos);
}
}
Inline void *ResetArena(Arena *arena)
{
PopTo(arena, 0);
return ArenaFirst(arena, u8);
}
TempArena BeginTempArena(Arena *arena);
void EndTempArena(TempArena temp);
////////////////////////////////////////////////////////////
//~ Temp arena operations
Inline TempArena BeginTempArena(Arena *arena)
{
TempArena t = ZI;
t.arena = arena;
t.start_pos = arena->pos;
return t;
}
Inline void EndTempArena(TempArena temp)
{
PopTo(temp.arena, temp.start_pos);
}
////////////////////////////////////////////////////////////
//~ Fiber arena ctx operations
Inline FiberArenaCtx *FiberArenaCtxFromId(i16 fiber_id)
{
SharedArenaCtx *g = &shared_arena_ctx;
FiberArenaCtx *ctx = &g->arena_contexts[fiber_id];
if (!ctx->perm_arena)
{
__profn("Initialize fiber arena ctx");
ctx->perm_arena = AcquireArena(Gibi(64));
for (i32 i = 0; i < (i32)countof(ctx->scratch_arenas); ++i)
{
ctx->scratch_arenas[i] = AcquireArena(Gibi(64));
}
}
return ctx;
}
//~ Fiber arena helpers
FiberArenaCtx *FiberArenaCtxFromId(i16 fiber_id);
#define PermArena() (FiberArenaCtxFromId(FiberId())->perm_arena)
////////////////////////////////////////////////////////////
//~ Scratch helpers
//~ Scratch arena helpers
/* Any parameterized arenas in the caller's scope should be passed into this
* function as a potential "conflict". This is to prevent friction in case the
* passed arena is itself a scratch arena from another scope (since
* parameterized arenas are often used to allocate persistent results for the
* caller).
*
* Use `BeginScratchNoConflict` instead if there is no arena in the current
* scope that could potentially be a scratch arena from another scope. */
Inline TempArena BeginScratch(Arena *potential_conflict)
{
/* This function is currently hard-coded to search through 2 scratch arenas */
StaticAssert(ScratchArenasPerCtx == 2);
/* Use `BeginScratchNoConflict` if no conflicts are present */
Assert(potential_conflict != 0);
FiberArenaCtx *ctx = FiberArenaCtxFromId(FiberId());
Arena *scratch_arena = ctx->scratch_arenas[0];
if (scratch_arena == potential_conflict)
{
scratch_arena = ctx->scratch_arenas[1];
}
TempArena temp = BeginTempArena(scratch_arena);
return temp;
}
TempArena BeginScratch(Arena *potential_conflict);
TempArena BeginScratchNoConflict_(void);
void EndScratch(TempArena scratch_temp);
/* This macro declares an unused "arena" variable that will error if an existing "arena"
* 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 (`BeginScratch(arena)` should be called
* instead). */
* exists in the caller's scope. */
#define BeginScratchNoConflict() \
BeginScratchNoConflict_(); \
do { \
u8 arena = 0; \
LAX arena; \
} while (0)
Inline TempArena BeginScratchNoConflict_(void)
{
FiberArenaCtx *ctx = FiberArenaCtxFromId(FiberId());
Arena *scratch_arena = ctx->scratch_arenas[0];
TempArena temp = BeginTempArena(scratch_arena);
return temp;
}
Inline void EndScratch(TempArena scratch_temp)
{
EndTempArena(scratch_temp);
}

View File

@ -154,7 +154,7 @@ void FutexWakeNeq(void *addr)
if (first_id != 0)
{
TempArena scratch = BeginScratchNoConflict();
i16 *ids = PushDry(scratch.arena, i16);
i16 *ids = ArenaNext(scratch.arena, i16);
i16 ids_count = 0;
{
i16 id = first_id;

View File

@ -23,7 +23,7 @@ String StringFromU64(Arena *arena, u64 n, u64 base, u64 zfill)
/* Build backwards text starting from least significant digit */
u64 len = 0;
u8 *backwards_text = PushDry(scratch.arena, u8);
u8 *backwards_text = ArenaNext(scratch.arena, u8);
do
{
StringFromChar(scratch.arena, IntChars[n % base]);
@ -56,7 +56,7 @@ String StringFromU64(Arena *arena, u64 n, u64 base, u64 zfill)
//- Signed int conversion
String StringFromI64(Arena *arena, i64 n, u64 base, u64 zfill)
{
u8 *final_text = PushDry(arena, u8);
u8 *final_text = ArenaNext(arena, u8);
u8 len = 0;
if (n < 0)
{
@ -91,7 +91,7 @@ String StringFromF64(Arena *arena, f64 f, u32 precision)
{
TempArena scratch = BeginScratch(arena);
String result = ZI;
result.text = PushDry(arena, u8);
result.text = ArenaNext(arena, u8);
if (IsF32Nan(f))
{
@ -123,7 +123,7 @@ String StringFromF64(Arena *arena, f64 f, u32 precision)
/* Print whole part */
{
/* Build backwards text starting from least significant digit */
u8 *backwards_text = PushDry(scratch.arena, u8);
u8 *backwards_text = ArenaNext(scratch.arena, u8);
u64 backwards_text_len = 0;
do
{
@ -164,7 +164,7 @@ String StringFromF64(Arena *arena, f64 f, u32 precision)
String StringFromhandle(Arena *arena, u64 v0, u64 v1)
{
String result = ZI;
result.text = PushDry(arena, u8);
result.text = ArenaNext(arena, u8);
result.len += PushString(arena, Lit("h")).len;
result.len += StringFromU64(arena, v0, 16, 0).len;
result.len += PushString(arena, Lit("x")).len;
@ -176,7 +176,7 @@ String StringFromhandle(Arena *arena, u64 v0, u64 v1)
String StringFromUid(Arena *arena, Uid uid)
{
String result = ZI;
result.text = PushDry(arena, u8);
result.text = ArenaNext(arena, u8);
result.len += StringFromU64(arena, (uid.hi >> 32), 16, 8).len;
return result;
}
@ -242,7 +242,7 @@ String CatString(Arena *arena, String str1, String str2)
StringArray SplitString(Arena *arena, String str, String delim)
{
StringArray pieces = ZI;
pieces.strings = PushDry(arena, String);
pieces.strings = ArenaNext(arena, String);
i64 piece_start = 0;
for (i64 i = 0; i < (i64)str.len - (i64)delim.len; ++i)
{
@ -284,7 +284,7 @@ String IndentString(Arena *arena, String str, u32 indent)
TempArena scratch = BeginScratch(arena);
u64 final_len = 0;
u8 *final_text = PushDry(arena, u8);
u8 *final_text = ArenaNext(arena, u8);
StringArray split = SplitString(scratch.arena, str, Lit("\n"));
for (u64 i = 0; i < split.count; ++i)
@ -443,7 +443,7 @@ StringListNode *PushStringToList(Arena *arena, StringList *l, String s)
String StringFromList(Arena *arena, StringList l, String separator)
{
String result = ZI;
result.text = PushDry(arena, u8);
result.text = ArenaNext(arena, u8);
for (StringListNode *n = l.first; n; n = n->next)
{
String s = n->s;
@ -543,7 +543,7 @@ String FormatStringV(Arena *arena, String fmt, va_list args)
__prof;
u64 final_len = 0;
u8 *final_text = PushDry(arena, u8);
u8 *final_text = ArenaNext(arena, u8);
u8 *end = fmt.text + fmt.len;
b32 no_more_args = 0;
@ -702,7 +702,7 @@ String StringFromString16(Arena *arena, String16 str16)
{
String result = {
.len = 0,
.text = PushDry(arena, u8)
.text = ArenaNext(arena, u8)
};
u64 pos16 = 0;
@ -727,7 +727,7 @@ String StringFromString32(Arena *arena, String32 str32)
{
String result = {
.len = 0,
.text = PushDry(arena, u8)
.text = ArenaNext(arena, u8)
};
u64 pos32 = 0;
@ -754,7 +754,7 @@ String16 String16FromString(Arena *arena, String str8)
{
String16 result = {
.len = 0,
.text = PushDry(arena, u16)
.text = ArenaNext(arena, u16)
};
u64 pos8 = 0;
@ -779,7 +779,7 @@ String32 String32FromString(Arena *arena, String str8)
{
String32 result = {
.len = 0,
.text = PushDry(arena, u32)
.text = ArenaNext(arena, u32)
};
u64 pos8 = 0;

View File

@ -132,7 +132,7 @@ String SwappedStateFromName(Arena *arena, String name)
if (handle != INVALID_HANDLE_VALUE)
{
u32 chunk_size = Kibi(64);
result.text = PushDry(arena, u8);
result.text = ArenaNext(arena, u8);
for (;;)
{
u8 *chunk = PushStructsNoZero(arena, u8, chunk_size);

View File

@ -9,7 +9,7 @@ void InitLogSystem(String logfile_path)
W32_SharedLogState *g = &W32_shared_log_state;
g->logs_arena = AcquireArena(Gibi(64));
g->log_msgs_arena = AcquireArena(Gibi(64));
g->readable_log_events = PushDry(g->logs_arena, LogEvent);
g->readable_log_events = ArenaNext(g->logs_arena, LogEvent);
if (logfile_path.len > 0)
{
TempArena scratch = BeginScratchNoConflict();

View File

@ -331,7 +331,7 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
if (gjk_result.overlapping)
{
CLD_MenkowskiSimplex s = gjk_result.simplex;
proto = PushDry(scratch.arena, CLD_MenkowskiPoint);
proto = ArenaNext(scratch.arena, CLD_MenkowskiPoint);
{
Assert(s.len == 3);
CLD_MenkowskiPoint *tmp = PushStructsNoZero(scratch.arena, CLD_MenkowskiPoint, 3);
@ -990,7 +990,7 @@ f32 CLD_TimeOfImpact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, X
/* TODO: Remove this (debugging) */
Vec2Array CLD_Menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail)
{
Vec2Array result = { .points = PushDry(arena, Vec2) };
Vec2Array result = { .points = ArenaNext(arena, Vec2) };
for (u64 i = 0; i < detail; ++i)
{
f32 angle = ((f32)i / detail) * (2 * Pi);
@ -1009,7 +1009,7 @@ Vec2Array CLD_Menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xfor
Vec2Array CLD_PointCloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1)
{
/* FIXME: Account for radius */
Vec2Array result = { .points = PushDry(arena, Vec2) };
Vec2Array result = { .points = ArenaNext(arena, Vec2) };
Vec2 *points0 = shape0->points;
Vec2 *points1 = shape1->points;
u32 count0 = shape0->count;

View File

@ -244,7 +244,7 @@ F_Glyph F_GlyphFromCodepoint(F_Font *font, u32 codepoint)
F_Run F_RunFromString(Arena *arena, F_Font *font, String str)
{
F_Run result = ZI;
result.rects = PushDry(arena, F_RunRect);
result.rects = ArenaNext(arena, F_RunRect);
f32 baseline_length = 0;
for (CodepointIter it = InitCodepointIter(str); NextCodepoint(&it);)

View File

@ -80,7 +80,7 @@ String OS_ReadEntireFile(Arena *arena, OS_File file)
String result = ZI;
HANDLE handle = (HANDLE)file.handle;
u32 chunk_size = Kibi(64);
result.text = PushDry(arena, u8);
result.text = ArenaNext(arena, u8);
for (;;)
{
u8 *chunk = PushStructsNoZero(arena, u8, chunk_size);
@ -300,7 +300,7 @@ OS_CommandResult OS_RunCommand(Arena *arena, String cmd)
/* Read process output */
if (ok)
{
result.output.text = PushDry(arena, u8);
result.output.text = ArenaNext(arena, u8);
b32 exit_code_valid = 0;
i32 exit_code = 0;
b32 stdout_finished = 0;

View File

@ -64,7 +64,7 @@ MP3_Result MP3_Decode(Arena *arena, String encoded, u32 sample_rate, MP3_DecodeF
//- Read
result.samples = PushDry(arena, i16);
result.samples = ArenaNext(arena, i16);
u64 sample_bytes_read = 0;
for (;;)
{

View File

@ -29,7 +29,7 @@ N_Host *N_AcquireHost(u16 listen_port)
host->rcv_buffer_write->arena = AcquireArena(Gibi(64));
host->buddy = AcquireBuddyCtx(Gibi(64));
host->channels = PushDry(host->channel_arena, N_Channel);
host->channels = ArenaNext(host->channel_arena, N_Channel);
host->num_channel_lookup_bins = N_NumChannelLookupBins;
host->channel_lookup_bins = PushStructs(host->arena, N_ChannelLookupBin, host->num_channel_lookup_bins);

View File

@ -44,7 +44,7 @@ String P_W32_StringFromWin32Path(Arena *arena, wchar_t *src)
{
String result = {
.len = 0,
.text = PushDry(arena, u8)
.text = ArenaNext(arena, u8)
};
while (*src)