From 5e5c912092bacb63ce757c791a4efa9884206fec Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Fri, 29 Aug 2025 19:24:52 +0200 Subject: [PATCH] use the specified allocator for the element caches --- TODO | 2 +- lib/ugui.c3l/src/cache.c3 | 10 +++++--- lib/ugui.c3l/src/fifo.c3 | 12 +++++---- lib/ugui.c3l/src/ugui_core.c3 | 10 ++++---- lib/ugui.c3l/src/vtree.c3 | 46 +++++++++++++++++++---------------- src/main.c3 | 8 +++++- 6 files changed, 51 insertions(+), 37 deletions(-) diff --git a/TODO b/TODO index f1e191d..c678e87 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,7 @@ [x] Port font system from C to C3 (rewrite1) [ ] Update ARCHITECTURE.md [ ] Write a README.md -[ ] Use an arena allocator for cache +[x] Use an arena allocator for cache [ ] Do not redraw if there was no update (no layout and no draw) [ ] Do command buffer damage tracking based on a context grid (see rxi writeup) [x] Better handling of the active and focused widgets, try diff --git a/lib/ugui.c3l/src/cache.c3 b/lib/ugui.c3l/src/cache.c3 index 130ffd1..04ea3a3 100644 --- a/lib/ugui.c3l/src/cache.c3 +++ b/lib/ugui.c3l/src/cache.c3 @@ -25,6 +25,7 @@ alias IdTableEntry = map::Entry{Key, usz}; const usz CACHE_NCYCLES = (usz)(SIZE * 2.0/3.0); struct Cache { + Allocator allocator; BitArr present, used; IdTable table; Value[] pool; @@ -43,19 +44,20 @@ macro Cache.cycle(&cache) @private { } } -fn void? Cache.init(&cache) +fn void? Cache.init(&cache, Allocator allocator) { - cache.table.init(allocator::heap(), capacity: SIZE); + cache.allocator = allocator; + cache.table.init(allocator, capacity: SIZE); // FIXME: this shit is SLOW foreach (idx, bit : cache.used) { cache.used[idx] = false; } foreach (idx, bit : cache.present) { cache.present[idx] = false; } - cache.pool = mem::new_array(Value, SIZE); + cache.pool = allocator::new_array(allocator, Value, SIZE); } fn void Cache.free(&cache) { (void)cache.table.free(); - (void)mem::free(cache.pool); + (void)allocator::free(cache.allocator, cache.pool); } fn Value*? Cache.search(&cache, Key id) diff --git a/lib/ugui.c3l/src/fifo.c3 b/lib/ugui.c3l/src/fifo.c3 index d9fc52e..c7dff8f 100644 --- a/lib/ugui.c3l/src/fifo.c3 +++ b/lib/ugui.c3l/src/fifo.c3 @@ -9,21 +9,23 @@ import std::sort; // TODO: specify the allocator struct Fifo { + Allocator allocator; Type[] arr; usz out; usz count; } -fn void? Fifo.init(&fifo, usz size) +fn void? Fifo.init(&fifo, usz size, Allocator allocator) { - fifo.arr = mem::new_array(Type, size); + fifo.allocator = allocator; + fifo.arr = allocator::new_array(fifo.allocator, Type, size); fifo.out = 0; fifo.count = 0; } fn void Fifo.free(&fifo) { - (void)mem::free(fifo.arr); + (void)allocator::free(fifo.allocator, fifo.arr); } fn void? Fifo.enqueue(&fifo, Type *elem) @@ -69,8 +71,8 @@ macro usz Fifo.len(&fifo) @operator(len) fn void? Fifo.sort(&fifo) { - Type[] arr = mem::new_array(Type, fifo.count); - defer mem::free(arr); + Type[] arr = allocator::new_array(fifo.allocator, Type, fifo.count); + defer allocator::free(fifo.allocator, arr); foreach(i, c: fifo) { arr[i] = c; diff --git a/lib/ugui.c3l/src/ugui_core.c3 b/lib/ugui.c3l/src/ugui_core.c3 index b85e996..e3f1a01 100644 --- a/lib/ugui.c3l/src/ugui_core.c3 +++ b/lib/ugui.c3l/src/ugui_core.c3 @@ -187,18 +187,18 @@ fn Elem*? Ctx.get_active_div(&ctx) return ctx.cache.search(id); } -fn void? Ctx.init(&ctx) +fn void? Ctx.init(&ctx, Allocator allocator) { - ctx.tree.init(MAX_ELEMENTS)!; + ctx.tree.init(MAX_ELEMENTS, allocator)!; defer catch { (void)ctx.tree.free(); } - ctx.cache.init()!; + ctx.cache.init(allocator)!; defer catch { (void)ctx.cache.free(); } - ctx.cmd_queue.init(MAX_CMDS)!; + ctx.cmd_queue.init(MAX_CMDS, allocator)!; defer catch { (void)ctx.cmd_queue.free(); } - ctx.styles.init(allocator::heap()); + ctx.styles.init(allocator); ctx.styles.register_style(&DEFAULT_STYLE, @str_hash("default")); defer catch { ctx.styles.free(); } diff --git a/lib/ugui.c3l/src/vtree.c3 b/lib/ugui.c3l/src/vtree.c3 index d18b749..7901a58 100644 --- a/lib/ugui.c3l/src/vtree.c3 +++ b/lib/ugui.c3l/src/vtree.c3 @@ -4,39 +4,43 @@ faultdef CANNOT_SHRINK, INVALID_REFERENCE, TREE_FULL, REFERENCE_NOT_PRESENT, INV module vtree{ElemType}; import std::core::mem; +import std::core::mem::allocator; import std::io; struct VTree { + Allocator allocator; usz elements; ElemType[] vector; // vector of element ids isz[] refs, ordered_refs; } -macro VTree.ref_is_valid(&tree, isz ref) { return (ref >= 0 && ref < tree.refs.len); } -macro VTree.ref_is_present(&tree, isz ref) { return tree.refs[ref] >= 0; } -macro VTree.size(&tree) { return tree.refs.len; } +macro VTree.ref_is_valid(&tree, isz ref) => (ref >= 0 && ref < tree.refs.len); +macro VTree.ref_is_present(&tree, isz ref) => tree.refs[ref] >= 0; +macro VTree.size(&tree) => tree.refs.len; -// macro to zero an elemen +// macro to zero an element macro @zero() { - $if $assignable(0, ElemType): + $if @assignable_to(0, ElemType): return 0; $else return {}; $endif } -fn void? VTree.init(&tree, usz size) +fn void? VTree.init(&tree, usz size, Allocator allocator) { - tree.vector = mem::new_array(ElemType, size); - defer catch { (void)mem::free(tree.vector); } + tree.allocator = allocator; - tree.refs = mem::new_array(isz, size); - defer catch { (void)mem::free(tree.refs); } + tree.vector = allocator::new_array(tree.allocator, ElemType, size); + defer catch { (void)allocator::free(tree.allocator, tree.vector); } - tree.ordered_refs = mem::new_array(isz, size); - defer catch { (void)mem::free(tree.ordered_refs); } + tree.refs = allocator::new_array(tree.allocator, isz, size); + defer catch { (void)allocator::free(tree.allocator, tree.refs); } + + tree.ordered_refs = allocator::new_array(tree.allocator, isz, size); + defer catch { (void)allocator::free(tree.allocator, tree.ordered_refs); } // set all refs to -1, meaning invalid (free) element tree.refs[..] = -1; @@ -46,9 +50,9 @@ fn void? VTree.init(&tree, usz size) fn void VTree.free(&tree) { - (void)mem::free(tree.vector); - (void)mem::free(tree.refs); - (void)mem::free(tree.ordered_refs); + (void)allocator::free(tree.allocator, tree.vector); + (void)allocator::free(tree.allocator, tree.refs); + (void)allocator::free(tree.allocator, tree.ordered_refs); } fn void VTree.pack(&tree) @@ -102,14 +106,14 @@ fn void? VTree.resize(&tree, usz newsize) usz old_size = tree.size(); - tree.vector = ((ElemType*)mem::realloc(tree.vector, newsize*ElemType.sizeof))[:newsize]; - defer catch { (void)mem::free(tree.vector); } + tree.vector = ((ElemType*)allocator::realloc(tree.allocator, tree.vector, newsize*ElemType.sizeof))[:newsize]; + defer catch { (void)allocator::free(tree.allocator, tree.vector); } - tree.refs = ((isz*)mem::realloc(tree.refs, newsize*isz.sizeof))[:newsize]; - defer catch { (void)mem::free(tree.refs); } + tree.refs = ((isz*)allocator::realloc(tree.allocator, tree.refs, newsize*isz.sizeof))[:newsize]; + defer catch { (void)allocator::free(tree.allocator, tree.refs); } - tree.ordered_refs = ((isz*)mem::realloc(tree.ordered_refs, newsize*isz.sizeof))[:newsize]; - defer catch { (void)mem::free(tree.ordered_refs); } + tree.ordered_refs = ((isz*)allocator::realloc(tree.allocator, tree.ordered_refs, newsize*isz.sizeof))[:newsize]; + defer catch { (void)allocator::free(tree.allocator, tree.ordered_refs); } if (newsize > tree.size()) { tree.vector[old_size..newsize-1] = @zero(); diff --git a/src/main.c3 b/src/main.c3 index 000a103..7e6fed6 100644 --- a/src/main.c3 +++ b/src/main.c3 @@ -6,6 +6,7 @@ import std::time; import std::collections::ringbuffer; import std::core::string; import std::ascii; +import std::core::mem::allocator; import sdlrenderer::ren; import sdl3::sdl; @@ -58,8 +59,13 @@ const char[*] STYLESHEET_PATH = "resources/style.css"; fn int main(String[] args) { + ArenaAllocator arena; + char[] mem = mem::new_array(char, 1024*1024); + defer (void)mem::free(mem); + arena.init(mem); + ugui::Ctx ui; - ui.init()!!; + ui.init(&arena)!!; defer ui.free(); ren::Renderer ren;