All of my "arenas" have an additional fixed-length list of function pointers that they call in sequence before resetting/de-allocating the memory. That way they can manage any form of memory (or non-memory resource) you want:
char *dat = malloc(42);
arena_push_dtor(ar, dat, free);
// use dat
Neatly solves the problem of stuff that's too awkward to put in linear memory while still letting you be lazy about cleanup.
Also: if you don't need the contiguity you can simply break up your dynamic array into linked buckets the same way the arena internally does with its own memory. Iteration and random access will still be fast.
FWIW, if you aren’t interleaving other allocations (which includes on other threads), the ArenaAllocator in Zig doesn’t have this problem. If you attempt to resize the most recent allocation, it will do so in place if possible.
All of my "arenas" have an additional fixed-length list of function pointers that they call in sequence before resetting/de-allocating the memory. That way they can manage any form of memory (or non-memory resource) you want:
Neatly solves the problem of stuff that's too awkward to put in linear memory while still letting you be lazy about cleanup.Also: if you don't need the contiguity you can simply break up your dynamic array into linked buckets the same way the arena internally does with its own memory. Iteration and random access will still be fast.
FWIW, if you aren’t interleaving other allocations (which includes on other threads), the ArenaAllocator in Zig doesn’t have this problem. If you attempt to resize the most recent allocation, it will do so in place if possible.
https://ziglang.org/documentation/0.16.0/std/#std.heap.Arena...