From e5f91cae6d90c40e458e1208c2ab8f8eb917c99a Mon Sep 17 00:00:00 2001 From: Matthew Date: Fri, 12 Dec 2025 18:53:53 +1100 Subject: [PATCH] clean up linked lists --- alloc.d | 69 +++++++++--------- platform.d | 102 +++++++++++++------------- test.sh | 2 +- util.d | 206 ++++++++++++++++------------------------------------- 4 files changed, 147 insertions(+), 232 deletions(-) diff --git a/alloc.d b/alloc.d index 1a3d607..fbfca27 100644 --- a/alloc.d +++ b/alloc.d @@ -22,22 +22,23 @@ struct Scratch struct ArenaPool { - u8* mem; - u64 pos; - u64 length; + u8* mem; + u64 pos; + u64 length; + ArenaPool* next; } struct Arena { - SLList!(ArenaPool) pools; - u64 def_size; + ArenaPool* first, last; + u64 def_size; } struct TempArena { - Arena* arena; - Node!(ArenaPool)* start_node; - u64 start_pos; + Arena* arena; + u64 start_pos; + ArenaPool* start_pool; } T* @@ -160,13 +161,13 @@ BeginTempArena(Arena* arena) arena: arena, }; - auto n = arena.pools.first; + auto n = arena.first; for(;;) { if(n.next == null) { - t.start_node = n; - t.start_pos = n.value.pos; + t.start_pool = n; + t.start_pos = n.pos; break; } @@ -180,16 +181,16 @@ void End(TempArena* t) { bool resetting = false; - for(auto n = t.arena.pools.first; n != null; n = n.next) + for(auto n = t.arena.first; n != null; n = n.next) { - if(t.start_node == n) + if(t.start_pool == n) { - n.value.pos = t.start_pos; + n.pos = t.start_pos; resetting = true; } else if(resetting) { - n.value.pos = 0; + n.pos = 0; } } } @@ -233,17 +234,17 @@ Alloc(T)(TempArena* t) void AddArenaPool(Arena* arena, u64 size) { - u8* mem = Alloc!(u8)(size + Node!(ArenaPool).sizeof).ptr; + u8* mem = Alloc!(u8)(size + ArenaPool.sizeof).ptr; - Node!(ArenaPool)* node = cast(Node!(ArenaPool)*)mem; + ArenaPool* node = cast(ArenaPool*)mem; - node.value.mem = (cast(u8*)mem) + Node!(ArenaPool).sizeof; - node.value.pos = 0; - node.value.length = size; + node.mem = (cast(u8*)mem) + ArenaPool.sizeof; + node.pos = 0; + node.length = size; - assert(node.value.mem != null, "Unable to allocate memory for arena"); + assert(node.mem != null, "Unable to allocate memory for arena"); - SLLPushFront(&arena.pools, node, null); + SLLPushFront(arena, node, null); } T[] @@ -308,7 +309,7 @@ AllocAlign(Arena* arena, u64 size, u64 alignment) void* ptr = null; uintptr mem_pos, current, offset; - Node!(ArenaPool)* node = arena.pools.first; + ArenaPool* node = arena.first; while (true) { if(node == null) @@ -319,14 +320,14 @@ AllocAlign(Arena* arena, u64 size, u64 alignment) } AddArenaPool(arena, Max(size, arena.def_size)); - node = arena.pools.first; + node = arena.first; } - mem_pos = cast(uintptr)node.value.mem; - current = mem_pos + node.value.pos; + mem_pos = cast(uintptr)node.mem; + current = mem_pos + node.pos; offset = AlignPow2(current, alignment) - mem_pos; - if(offset+size <= node.value.length) + if(offset+size <= node.length) { break; } @@ -334,8 +335,8 @@ AllocAlign(Arena* arena, u64 size, u64 alignment) node = node.next; } - ptr = &node.value.mem[offset]; - node.value.pos = offset+size; + ptr = &node.mem[offset]; + node.pos = offset+size; return ptr; }; @@ -343,10 +344,10 @@ AllocAlign(Arena* arena, u64 size, u64 alignment) void Reset(Arena* arena) { - Node!(ArenaPool)* node = arena.pools.first; + ArenaPool* node = arena.first; while (node != null) { - node.value.pos = 0; + node.pos = 0; node = node.next; } } @@ -354,11 +355,13 @@ Reset(Arena* arena) void Free(Arena* arena) { - Node!(ArenaPool)* node = arena.pools.first; + ArenaPool* node = arena.first; + ArenaPool* next; while (node != null) { + next = node.next; Free(node); - node = node.next; + node = next; } } diff --git a/platform.d b/platform.d index 03c3974..1cdfe60 100644 --- a/platform.d +++ b/platform.d @@ -153,13 +153,14 @@ alias MD = Modifier; struct InputEvent { - Input key; - Modifier md; - bool pressed; - i32 x; - i32 y; - i32 rel_x; - i32 rel_y; + Input key; + Modifier md; + bool pressed; + i32 x; + i32 y; + i32 rel_x; + i32 rel_y; + InputEvent* next, prev; } enum ClipboardMode @@ -175,8 +176,8 @@ alias CBM = ClipboardMode; struct Inputs { - DLList!(InputEvent) list; - Arena arena; + InputEvent* first, last; + Arena arena; } pragma(inline) bool @@ -287,20 +288,21 @@ Unlock(TicketMut* mut) return atomicFetchAdd!(MemoryOrder.rel, u64)(mut.next_ticket, 1); } -__gshared const DNode!(SysMessage) g_sys_message; -__gshared DNode!(SysMessage)* g_NIL_MSG; +__gshared const SysMessage g_sys_message; +__gshared SysMessage* g_NIL_MSG; struct SysMessage { SysMessageType type; + SysMessage* next, prev; } struct MessageQueue { - DLList!(SysMessage) list; - DLList!(SysMessage) free_list; - TicketMut mut; - Arena arena; + TicketMut mut; + Arena arena; + SysMessage* first, last; + LinkedList!(SysMessage) free_list; } MessageQueue @@ -308,37 +310,35 @@ CreateMessageQueue() { if(g_NIL_MSG == null) { - g_NIL_MSG = cast(DNode!(SysMessage)*)&g_sys_message; + g_NIL_MSG = cast(SysMessage*)&g_sys_message; } MessageQueue queue = { - list: { - first: g_NIL_MSG, - last: g_NIL_MSG, - }, + first: g_NIL_MSG, + last: g_NIL_MSG, + mut: CreateTicketMut(), + arena: CreateArena(MB(1)), free_list: { first: g_NIL_MSG, - last: g_NIL_MSG, + last: g_NIL_MSG, }, - mut: CreateTicketMut(), - arena: CreateArena(MB(1)), }; return queue; } pragma(inline) bool -Nil(DNode!(SysMessage)* msg) +Nil(SysMessage* msg) { return msg == null || msg == g_NIL_MSG; } -DNode!(SysMessage)* +SysMessage* Pop(MessageQueue* queue) { Lock(&queue.mut); - DNode!(SysMessage)* node = DLLPop(&queue.list, g_NIL_MSG); + SysMessage* node = DLLPop(queue, g_NIL_MSG); Unlock(&queue.mut); @@ -350,26 +350,26 @@ Push(PlatformWindow* w, SysMessageType msg) { Lock(&w.msg_queue.mut); - DNode!(SysMessage)* node = g_NIL_MSG; + SysMessage* node = g_NIL_MSG; if(Nil(w.msg_queue.free_list.first)) { - node = Alloc!(DNode!(SysMessage))(&w.msg_queue.arena); + node = Alloc!(SysMessage)(&w.msg_queue.arena); } else { node = DLLPop(&w.msg_queue.free_list, g_NIL_MSG); } - node.value.type = msg; - DLLPush(&w.msg_queue.list, node, g_NIL_MSG); + node.type = msg; + DLLPush(&w.msg_queue, node, g_NIL_MSG); Unlock(&w.msg_queue.mut); } void -PushFree(PlatformWindow* w, DNode!(SysMessage)* node) +PushFree(PlatformWindow* w, SysMessage* node) { - DLLPush(&w.msg_queue.list, node, g_NIL_MSG); + DLLPush(&w.msg_queue, node, g_NIL_MSG); } version(linux) @@ -548,35 +548,35 @@ Kill() void ResetInputs(Inputs* inputs) { - inputs.list.first = inputs.list.last = null; + inputs.first = inputs.last = null; Reset(&inputs.arena); } void Push(Inputs* inputs, Input input, i32 x, i32 y, bool pressed, Modifier md) { - DNode!(InputEvent)* node = Alloc!(DNode!(InputEvent))(&inputs.arena); - node.value.key = input; - node.value.pressed = pressed; - node.value.x = x; - node.value.y = y; - node.value.md = md; + InputEvent* node = Alloc!(InputEvent)(&inputs.arena); + node.key = input; + node.pressed = pressed; + node.x = x; + node.y = y; + node.md = md; - DLLPushFront(&inputs.list, node, null); + DLLPushFront(inputs, node, null); } void PushMotion(Inputs* inputs, i32 rel_x, i32 rel_y, i32 x, i32 y) { - DNode!(InputEvent)* node = Alloc!(DNode!(InputEvent))(&inputs.arena); - node.value.key = Input.MouseMotion; - node.value.rel_x = rel_x; - node.value.rel_y = rel_y; - node.value.x = x; - node.value.y = y; - node.value.pressed = false; + InputEvent* node = Alloc!(InputEvent)(&inputs.arena); + node.key = Input.MouseMotion; + node.rel_x = rel_x; + node.rel_y = rel_y; + node.x = x; + node.y = y; + node.pressed = false; - DLLPushFront(&inputs.list, node, null); + DLLPushFront(inputs, node, null); } struct PlatformWindow @@ -1156,7 +1156,7 @@ HandleEvents(void* window_ptr) { PlatformWindow* w = cast(PlatformWindow*)window_ptr; - DNode!(SysMessage)* sys_msg = g_NIL_MSG; + SysMessage* sys_msg = g_NIL_MSG; XEvent e; bool ignore_mouse_events = false; @@ -1173,9 +1173,7 @@ HandleEvents(void* window_ptr) if(!Nil(sys_msg)) { - SysMessage msg = sys_msg.value; - - switch (msg.type) + switch (sys_msg.type) { case SMT.Quit: { diff --git a/test.sh b/test.sh index 5c9e3e7..4ab3fc9 100755 --- a/test.sh +++ b/test.sh @@ -4,7 +4,7 @@ name="Test_Runner" /bin/bash ./build.sh build -ldc2 platform.d aliases.d math.d util.d alloc.d assets.d external/xxhash/xxhash.d build/libcglm.a -d-version=DLIB_TEST -Xcc=-mno-sse -P-I/usr/include/freetype2 -L-lfreetype --main --unittest -g --of=$name +ldc2 platform.d aliases.d math.d util.d alloc.d assets.d external/xxhash/xxhash.d build/libcglm.a -d-version=DLIB_TEST -Xcc=-mno-sse -P-I/usr/include/freetype2 -L-lfreetype --main --unittest -g --of=$name -verrors=8 rm $name.o ./$name diff --git a/util.d b/util.d index 914b26b..949f133 100644 --- a/util.d +++ b/util.d @@ -205,17 +205,21 @@ BitEq(u64 l, u64 r) return (l & r) == r; } -struct DNode(T) +struct ListBox(T, bool doubly_linked) { - DNode!(T)* next; - DNode!(T)* prev; - T value; + alias U = ListBox!(T, doubly_linked); + + U* next; + static if(doubly_linked) + { + U* prev; + } + T value; } -struct DLList(T) +struct LinkedList(T) { - DNode!(T)* first; - DNode!(T)* last; + T* first, last; } void @@ -320,100 +324,38 @@ DLLPush(T, U)(T* list, U* node, U* nil) } void -DLLInsert(T, U)(T* list, U* node, U* prev, U* nil) +DLLInsert(T, U)(T* list, U* node, U* prev, U* nil) if(hasMember!(T, "last") && hasMember!(U, "prev")) { - node.next = node.prev = nil; - if(CheckNil(nil, list.first) && CheckNil(nil, list.last)) { - assert(CheckNil(nil, prev)); list.first = list.last = node; + node.next = node.prev = nil; } - else if(list.first == prev && list.last == prev) + else if(!CheckNil(nil, prev)) { - list.last = node; - node.prev = prev; - prev.next = node; + node.next = list.first; + list.first.prev = node; + list.first = node; + node.prev = nil; } else if(list.last == prev) { - prev.next = node; - node.prev = prev; - list.last = node; + list.last.next = node; + node.prev = list.last; + list.last = node; + node.next = nil; } + else if(!CheckNil(nil, prev) && CheckNil(nil, prev.next)) + {} else { - node.next = prev.next; - node.prev = prev; - prev.next = node; + node.prev = prev; + node.next = prev.next; + node.next.prev = node; + prev.next = node; } } -struct Stack(T) -{ - Node!(T)* top; - Node!(T)* free; - Node!(T)* nil; -} - -void -SPush(T)(Arena* arena, Stack!(T)* stack, T value) -{ - Node!(T)* node; - if(!CheckNil(stack.nil, stack.free)) - { - node = stack.free; - stack.free = node.next; - } - else - { - node = Alloc!(Node!(T))(arena); - } - - node.value = value; - - if(CheckNil(stack.nil, stack.top)) - { - stack.top = node; - node.next = stack.nil; - } - else - { - node.next = stack.top; - stack.top = node; - } -} - -T -SPop(T)(Stack!(T)* stack) -{ - T result; - - if(!CheckNil(stack.nil, stack.top)) - { - result = stack.top.value; - - Node!(T)* free_node = stack.top; - stack.top = free_node.next; - free_node.next = stack.free; - stack.free = free_node; - } - - return result; -} - -struct Node(T) -{ - Node!(T)* next; - T value; -} - -struct SLList(T) -{ - Node!(T)* first; - Node!(T)* last; -} - pragma(inline) bool CheckNil(T)(T* nil, T* node) { @@ -494,8 +436,9 @@ SLLPush(T, U)(T* list, U* node, U* nil) struct KVPair(K, V) { - K key; - V value; + K key; + V value; + KVPair!(K, V)* next; } struct Result(V) @@ -508,12 +451,12 @@ struct HashTable(K, V) { alias P = KVPair!(K, V); - SLList!(P) free_lists; - SLList!(P)[] lists; - Node!(P)* nil; - Arena arena; - u64 node_count; - u64 list_count; + LinkedList!(P) free_lists; + LinkedList!(P)[] lists; + P* nil; + Arena arena; + u64 node_count; + u64 list_count; void opIndexAssign(V value, K key) { @@ -539,8 +482,8 @@ HashTable!(K, V) CreateHashTable(K, V)(u64 size) { Arena arena = CreateArena(MB(4)); - auto nil = Alloc!(Node!(KVPair!(K, V)))(&arena); - auto lists = Alloc!(SLList!(KVPair!(K, V)))(&arena, size); + auto nil = Alloc!(KVPair!(K, V))(&arena); + auto lists = Alloc!(LinkedList!(KVPair!(K, V)))(&arena, size); HashTable!(K, V) table = { arena: arena, @@ -572,13 +515,12 @@ Clear(K, V)(HashTable!(K, V)* ht) } } -pragma(inline) Node!(KVPair!(K, V))* +pragma(inline) KVPair!(K, V)* Push(K, V)(HashTable!(K, V)* ht, K key, V value) { alias P = KVPair!(K, V); - alias N = Node!(P); - N* node = ht.nil; + P* node = ht.nil; if(!CheckNil(ht.nil, ht.free_lists.first)) { @@ -586,12 +528,12 @@ Push(K, V)(HashTable!(K, V)* ht, K key, V value) } else { - node = Alloc!(N)(&ht.arena); + node = Alloc!(P)(&ht.arena); } - node.next = ht.nil; - node.value.key = key; - node.value.value = value; + node.next = ht.nil; + node.key = key; + node.value = value; SLLPush(GetList(ht, key), node, ht.nil); @@ -608,9 +550,9 @@ Search(K, V)(HashTable!(K, V)* ht, K key) auto list = GetList(ht, key); for(auto node = list.first; !CheckNil(ht.nil, node); node = node.next) { - if(node.value.key == key) + if(node.key == key) { - result = &node.value; + result = node; break; } } @@ -618,7 +560,7 @@ Search(K, V)(HashTable!(K, V)* ht, K key) return result; } -pragma(inline) SLList!(KVPair!(K, V))* +pragma(inline) LinkedList!(KVPair!(K, V))* GetList(K, V)(HashTable!(K, V)* ht, K key) { u64 hash = Hash(&key); @@ -1000,8 +942,9 @@ Embed(string file_name) version(DLIB_TEST) unittest { { // Singly Linked List - SLList!(u32) list; - Node!(u32)[5] nodes; + alias LT = ListBox!(u32, false); + LinkedList!(LT) list; + LT[5] nodes; foreach(u32 i, n; nodes) { nodes[i].value = i; @@ -1014,15 +957,15 @@ version(DLIB_TEST) unittest SLLRemove(&list, &nodes[1], &nodes[0], null); SLLRemove(&list, &nodes[3], &nodes[2], null); - Node!(u32)* n = list.first; + LT* n = list.first; assert(list.first != null && list.last != null); assert(n != null); assert(n.next != null); - void TestSLList(SLList!(u32)* list, u32[] result) + void TestSLList(LinkedList!(LT)* list, u32[] result) { - Node!(u32)* n = list.first; + LT* n = list.first; foreach(i, v; result) { assert(n != null); @@ -1057,9 +1000,11 @@ version(DLIB_TEST) unittest } { // Doubly Linked List - void TestDLList(DLList!(u32)* list, u32[] result) + alias LT = ListBox!(u32, true); + + void TestDLList(T)(T* list, u32[] result) { - DNode!(u32)* n = list.first; + LT* n = list.first; foreach(i, v; result) { assert(n != null); @@ -1100,8 +1045,8 @@ version(DLIB_TEST) unittest } } - DLList!(u32) list; - DNode!(u32)[5] nodes; + LinkedList!(LT) list; + LT[5] nodes; foreach(u32 i, n; nodes) { nodes[i].value = i; @@ -1223,37 +1168,6 @@ version(DLIB_TEST) unittest assert(v3 > 0); } - { // Stack - Stack!(u32) stack; - Arena arena = CreateArena(MB(1)); - - u32 v1 = 1; - u32 v2 = 2; - u32 v3 = 3; - - Node!(u32) nil; - - stack.nil = &nil; - - SPush(&arena, &stack, v1); - SPush(&arena, &stack, v2); - SPush(&arena, &stack, v3); - - u32 count = 3; - for (auto n = stack.top; !CheckNil(null, n); n = n.next, count -= 1) - { - assert(n.value == count); - } - - count = 3; - for (u32 n = SPop(&stack); n != 0; n = SPop(&stack), count -= 1) - { - assert(n == count); - } - - assert(stack.top == &nil); - } - { // Casts u8[] arr = CastStr!(u8)("Test"); char[] char_arr = ['a', 'b'];