clean up linked lists
This commit is contained in:
parent
91e83eea1d
commit
e5f91cae6d
69
alloc.d
69
alloc.d
@ -22,22 +22,23 @@ struct Scratch
|
|||||||
|
|
||||||
struct ArenaPool
|
struct ArenaPool
|
||||||
{
|
{
|
||||||
u8* mem;
|
u8* mem;
|
||||||
u64 pos;
|
u64 pos;
|
||||||
u64 length;
|
u64 length;
|
||||||
|
ArenaPool* next;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Arena
|
struct Arena
|
||||||
{
|
{
|
||||||
SLList!(ArenaPool) pools;
|
ArenaPool* first, last;
|
||||||
u64 def_size;
|
u64 def_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TempArena
|
struct TempArena
|
||||||
{
|
{
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
Node!(ArenaPool)* start_node;
|
u64 start_pos;
|
||||||
u64 start_pos;
|
ArenaPool* start_pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
T*
|
T*
|
||||||
@ -160,13 +161,13 @@ BeginTempArena(Arena* arena)
|
|||||||
arena: arena,
|
arena: arena,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto n = arena.pools.first;
|
auto n = arena.first;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if(n.next == null)
|
if(n.next == null)
|
||||||
{
|
{
|
||||||
t.start_node = n;
|
t.start_pool = n;
|
||||||
t.start_pos = n.value.pos;
|
t.start_pos = n.pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,16 +181,16 @@ void
|
|||||||
End(TempArena* t)
|
End(TempArena* t)
|
||||||
{
|
{
|
||||||
bool resetting = false;
|
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;
|
resetting = true;
|
||||||
}
|
}
|
||||||
else if(resetting)
|
else if(resetting)
|
||||||
{
|
{
|
||||||
n.value.pos = 0;
|
n.pos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,17 +234,17 @@ Alloc(T)(TempArena* t)
|
|||||||
void
|
void
|
||||||
AddArenaPool(Arena* arena, u64 size)
|
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.mem = (cast(u8*)mem) + ArenaPool.sizeof;
|
||||||
node.value.pos = 0;
|
node.pos = 0;
|
||||||
node.value.length = size;
|
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[]
|
T[]
|
||||||
@ -308,7 +309,7 @@ AllocAlign(Arena* arena, u64 size, u64 alignment)
|
|||||||
void* ptr = null;
|
void* ptr = null;
|
||||||
|
|
||||||
uintptr mem_pos, current, offset;
|
uintptr mem_pos, current, offset;
|
||||||
Node!(ArenaPool)* node = arena.pools.first;
|
ArenaPool* node = arena.first;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if(node == null)
|
if(node == null)
|
||||||
@ -319,14 +320,14 @@ AllocAlign(Arena* arena, u64 size, u64 alignment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddArenaPool(arena, Max(size, arena.def_size));
|
AddArenaPool(arena, Max(size, arena.def_size));
|
||||||
node = arena.pools.first;
|
node = arena.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_pos = cast(uintptr)node.value.mem;
|
mem_pos = cast(uintptr)node.mem;
|
||||||
current = mem_pos + node.value.pos;
|
current = mem_pos + node.pos;
|
||||||
offset = AlignPow2(current, alignment) - mem_pos;
|
offset = AlignPow2(current, alignment) - mem_pos;
|
||||||
|
|
||||||
if(offset+size <= node.value.length)
|
if(offset+size <= node.length)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -334,8 +335,8 @@ AllocAlign(Arena* arena, u64 size, u64 alignment)
|
|||||||
node = node.next;
|
node = node.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = &node.value.mem[offset];
|
ptr = &node.mem[offset];
|
||||||
node.value.pos = offset+size;
|
node.pos = offset+size;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
};
|
};
|
||||||
@ -343,10 +344,10 @@ AllocAlign(Arena* arena, u64 size, u64 alignment)
|
|||||||
void
|
void
|
||||||
Reset(Arena* arena)
|
Reset(Arena* arena)
|
||||||
{
|
{
|
||||||
Node!(ArenaPool)* node = arena.pools.first;
|
ArenaPool* node = arena.first;
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
node.value.pos = 0;
|
node.pos = 0;
|
||||||
node = node.next;
|
node = node.next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,11 +355,13 @@ Reset(Arena* arena)
|
|||||||
void
|
void
|
||||||
Free(Arena* arena)
|
Free(Arena* arena)
|
||||||
{
|
{
|
||||||
Node!(ArenaPool)* node = arena.pools.first;
|
ArenaPool* node = arena.first;
|
||||||
|
ArenaPool* next;
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
|
next = node.next;
|
||||||
Free(node);
|
Free(node);
|
||||||
node = node.next;
|
node = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
102
platform.d
102
platform.d
@ -153,13 +153,14 @@ alias MD = Modifier;
|
|||||||
|
|
||||||
struct InputEvent
|
struct InputEvent
|
||||||
{
|
{
|
||||||
Input key;
|
Input key;
|
||||||
Modifier md;
|
Modifier md;
|
||||||
bool pressed;
|
bool pressed;
|
||||||
i32 x;
|
i32 x;
|
||||||
i32 y;
|
i32 y;
|
||||||
i32 rel_x;
|
i32 rel_x;
|
||||||
i32 rel_y;
|
i32 rel_y;
|
||||||
|
InputEvent* next, prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ClipboardMode
|
enum ClipboardMode
|
||||||
@ -175,8 +176,8 @@ alias CBM = ClipboardMode;
|
|||||||
|
|
||||||
struct Inputs
|
struct Inputs
|
||||||
{
|
{
|
||||||
DLList!(InputEvent) list;
|
InputEvent* first, last;
|
||||||
Arena arena;
|
Arena arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) bool
|
pragma(inline) bool
|
||||||
@ -287,20 +288,21 @@ Unlock(TicketMut* mut)
|
|||||||
return atomicFetchAdd!(MemoryOrder.rel, u64)(mut.next_ticket, 1);
|
return atomicFetchAdd!(MemoryOrder.rel, u64)(mut.next_ticket, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
__gshared const DNode!(SysMessage) g_sys_message;
|
__gshared const SysMessage g_sys_message;
|
||||||
__gshared DNode!(SysMessage)* g_NIL_MSG;
|
__gshared SysMessage* g_NIL_MSG;
|
||||||
|
|
||||||
struct SysMessage
|
struct SysMessage
|
||||||
{
|
{
|
||||||
SysMessageType type;
|
SysMessageType type;
|
||||||
|
SysMessage* next, prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MessageQueue
|
struct MessageQueue
|
||||||
{
|
{
|
||||||
DLList!(SysMessage) list;
|
TicketMut mut;
|
||||||
DLList!(SysMessage) free_list;
|
Arena arena;
|
||||||
TicketMut mut;
|
SysMessage* first, last;
|
||||||
Arena arena;
|
LinkedList!(SysMessage) free_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueue
|
MessageQueue
|
||||||
@ -308,37 +310,35 @@ CreateMessageQueue()
|
|||||||
{
|
{
|
||||||
if(g_NIL_MSG == null)
|
if(g_NIL_MSG == null)
|
||||||
{
|
{
|
||||||
g_NIL_MSG = cast(DNode!(SysMessage)*)&g_sys_message;
|
g_NIL_MSG = cast(SysMessage*)&g_sys_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueue queue = {
|
MessageQueue queue = {
|
||||||
list: {
|
first: g_NIL_MSG,
|
||||||
first: g_NIL_MSG,
|
last: g_NIL_MSG,
|
||||||
last: g_NIL_MSG,
|
mut: CreateTicketMut(),
|
||||||
},
|
arena: CreateArena(MB(1)),
|
||||||
free_list: {
|
free_list: {
|
||||||
first: g_NIL_MSG,
|
first: g_NIL_MSG,
|
||||||
last: g_NIL_MSG,
|
last: g_NIL_MSG,
|
||||||
},
|
},
|
||||||
mut: CreateTicketMut(),
|
|
||||||
arena: CreateArena(MB(1)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return queue;
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) bool
|
pragma(inline) bool
|
||||||
Nil(DNode!(SysMessage)* msg)
|
Nil(SysMessage* msg)
|
||||||
{
|
{
|
||||||
return msg == null || msg == g_NIL_MSG;
|
return msg == null || msg == g_NIL_MSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
DNode!(SysMessage)*
|
SysMessage*
|
||||||
Pop(MessageQueue* queue)
|
Pop(MessageQueue* queue)
|
||||||
{
|
{
|
||||||
Lock(&queue.mut);
|
Lock(&queue.mut);
|
||||||
|
|
||||||
DNode!(SysMessage)* node = DLLPop(&queue.list, g_NIL_MSG);
|
SysMessage* node = DLLPop(queue, g_NIL_MSG);
|
||||||
|
|
||||||
Unlock(&queue.mut);
|
Unlock(&queue.mut);
|
||||||
|
|
||||||
@ -350,26 +350,26 @@ Push(PlatformWindow* w, SysMessageType msg)
|
|||||||
{
|
{
|
||||||
Lock(&w.msg_queue.mut);
|
Lock(&w.msg_queue.mut);
|
||||||
|
|
||||||
DNode!(SysMessage)* node = g_NIL_MSG;
|
SysMessage* node = g_NIL_MSG;
|
||||||
if(Nil(w.msg_queue.free_list.first))
|
if(Nil(w.msg_queue.free_list.first))
|
||||||
{
|
{
|
||||||
node = Alloc!(DNode!(SysMessage))(&w.msg_queue.arena);
|
node = Alloc!(SysMessage)(&w.msg_queue.arena);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node = DLLPop(&w.msg_queue.free_list, g_NIL_MSG);
|
node = DLLPop(&w.msg_queue.free_list, g_NIL_MSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.value.type = msg;
|
node.type = msg;
|
||||||
DLLPush(&w.msg_queue.list, node, g_NIL_MSG);
|
DLLPush(&w.msg_queue, node, g_NIL_MSG);
|
||||||
|
|
||||||
Unlock(&w.msg_queue.mut);
|
Unlock(&w.msg_queue.mut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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)
|
version(linux)
|
||||||
@ -548,35 +548,35 @@ Kill()
|
|||||||
void
|
void
|
||||||
ResetInputs(Inputs* inputs)
|
ResetInputs(Inputs* inputs)
|
||||||
{
|
{
|
||||||
inputs.list.first = inputs.list.last = null;
|
inputs.first = inputs.last = null;
|
||||||
Reset(&inputs.arena);
|
Reset(&inputs.arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Push(Inputs* inputs, Input input, i32 x, i32 y, bool pressed, Modifier md)
|
Push(Inputs* inputs, Input input, i32 x, i32 y, bool pressed, Modifier md)
|
||||||
{
|
{
|
||||||
DNode!(InputEvent)* node = Alloc!(DNode!(InputEvent))(&inputs.arena);
|
InputEvent* node = Alloc!(InputEvent)(&inputs.arena);
|
||||||
node.value.key = input;
|
node.key = input;
|
||||||
node.value.pressed = pressed;
|
node.pressed = pressed;
|
||||||
node.value.x = x;
|
node.x = x;
|
||||||
node.value.y = y;
|
node.y = y;
|
||||||
node.value.md = md;
|
node.md = md;
|
||||||
|
|
||||||
DLLPushFront(&inputs.list, node, null);
|
DLLPushFront(inputs, node, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PushMotion(Inputs* inputs, i32 rel_x, i32 rel_y, i32 x, i32 y)
|
PushMotion(Inputs* inputs, i32 rel_x, i32 rel_y, i32 x, i32 y)
|
||||||
{
|
{
|
||||||
DNode!(InputEvent)* node = Alloc!(DNode!(InputEvent))(&inputs.arena);
|
InputEvent* node = Alloc!(InputEvent)(&inputs.arena);
|
||||||
node.value.key = Input.MouseMotion;
|
node.key = Input.MouseMotion;
|
||||||
node.value.rel_x = rel_x;
|
node.rel_x = rel_x;
|
||||||
node.value.rel_y = rel_y;
|
node.rel_y = rel_y;
|
||||||
node.value.x = x;
|
node.x = x;
|
||||||
node.value.y = y;
|
node.y = y;
|
||||||
node.value.pressed = false;
|
node.pressed = false;
|
||||||
|
|
||||||
DLLPushFront(&inputs.list, node, null);
|
DLLPushFront(inputs, node, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PlatformWindow
|
struct PlatformWindow
|
||||||
@ -1156,7 +1156,7 @@ HandleEvents(void* window_ptr)
|
|||||||
{
|
{
|
||||||
PlatformWindow* w = cast(PlatformWindow*)window_ptr;
|
PlatformWindow* w = cast(PlatformWindow*)window_ptr;
|
||||||
|
|
||||||
DNode!(SysMessage)* sys_msg = g_NIL_MSG;
|
SysMessage* sys_msg = g_NIL_MSG;
|
||||||
XEvent e;
|
XEvent e;
|
||||||
|
|
||||||
bool ignore_mouse_events = false;
|
bool ignore_mouse_events = false;
|
||||||
@ -1173,9 +1173,7 @@ HandleEvents(void* window_ptr)
|
|||||||
|
|
||||||
if(!Nil(sys_msg))
|
if(!Nil(sys_msg))
|
||||||
{
|
{
|
||||||
SysMessage msg = sys_msg.value;
|
switch (sys_msg.type)
|
||||||
|
|
||||||
switch (msg.type)
|
|
||||||
{
|
{
|
||||||
case SMT.Quit:
|
case SMT.Quit:
|
||||||
{
|
{
|
||||||
|
|||||||
2
test.sh
2
test.sh
@ -4,7 +4,7 @@ name="Test_Runner"
|
|||||||
|
|
||||||
/bin/bash ./build.sh build
|
/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
|
rm $name.o
|
||||||
./$name
|
./$name
|
||||||
|
|||||||
206
util.d
206
util.d
@ -205,17 +205,21 @@ BitEq(u64 l, u64 r)
|
|||||||
return (l & r) == r;
|
return (l & r) == r;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DNode(T)
|
struct ListBox(T, bool doubly_linked)
|
||||||
{
|
{
|
||||||
DNode!(T)* next;
|
alias U = ListBox!(T, doubly_linked);
|
||||||
DNode!(T)* prev;
|
|
||||||
T value;
|
U* next;
|
||||||
|
static if(doubly_linked)
|
||||||
|
{
|
||||||
|
U* prev;
|
||||||
|
}
|
||||||
|
T value;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DLList(T)
|
struct LinkedList(T)
|
||||||
{
|
{
|
||||||
DNode!(T)* first;
|
T* first, last;
|
||||||
DNode!(T)* last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -320,100 +324,38 @@ DLLPush(T, U)(T* list, U* node, U* nil)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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))
|
if(CheckNil(nil, list.first) && CheckNil(nil, list.last))
|
||||||
{
|
{
|
||||||
assert(CheckNil(nil, prev));
|
|
||||||
list.first = list.last = node;
|
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.next = list.first;
|
||||||
node.prev = prev;
|
list.first.prev = node;
|
||||||
prev.next = node;
|
list.first = node;
|
||||||
|
node.prev = nil;
|
||||||
}
|
}
|
||||||
else if(list.last == prev)
|
else if(list.last == prev)
|
||||||
{
|
{
|
||||||
prev.next = node;
|
list.last.next = node;
|
||||||
node.prev = prev;
|
node.prev = list.last;
|
||||||
list.last = node;
|
list.last = node;
|
||||||
|
node.next = nil;
|
||||||
}
|
}
|
||||||
|
else if(!CheckNil(nil, prev) && CheckNil(nil, prev.next))
|
||||||
|
{}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node.next = prev.next;
|
node.prev = prev;
|
||||||
node.prev = prev;
|
node.next = prev.next;
|
||||||
prev.next = node;
|
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
|
pragma(inline) bool
|
||||||
CheckNil(T)(T* nil, T* node)
|
CheckNil(T)(T* nil, T* node)
|
||||||
{
|
{
|
||||||
@ -494,8 +436,9 @@ SLLPush(T, U)(T* list, U* node, U* nil)
|
|||||||
|
|
||||||
struct KVPair(K, V)
|
struct KVPair(K, V)
|
||||||
{
|
{
|
||||||
K key;
|
K key;
|
||||||
V value;
|
V value;
|
||||||
|
KVPair!(K, V)* next;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Result(V)
|
struct Result(V)
|
||||||
@ -508,12 +451,12 @@ struct HashTable(K, V)
|
|||||||
{
|
{
|
||||||
alias P = KVPair!(K, V);
|
alias P = KVPair!(K, V);
|
||||||
|
|
||||||
SLList!(P) free_lists;
|
LinkedList!(P) free_lists;
|
||||||
SLList!(P)[] lists;
|
LinkedList!(P)[] lists;
|
||||||
Node!(P)* nil;
|
P* nil;
|
||||||
Arena arena;
|
Arena arena;
|
||||||
u64 node_count;
|
u64 node_count;
|
||||||
u64 list_count;
|
u64 list_count;
|
||||||
|
|
||||||
void opIndexAssign(V value, K key)
|
void opIndexAssign(V value, K key)
|
||||||
{
|
{
|
||||||
@ -539,8 +482,8 @@ HashTable!(K, V)
|
|||||||
CreateHashTable(K, V)(u64 size)
|
CreateHashTable(K, V)(u64 size)
|
||||||
{
|
{
|
||||||
Arena arena = CreateArena(MB(4));
|
Arena arena = CreateArena(MB(4));
|
||||||
auto nil = Alloc!(Node!(KVPair!(K, V)))(&arena);
|
auto nil = Alloc!(KVPair!(K, V))(&arena);
|
||||||
auto lists = Alloc!(SLList!(KVPair!(K, V)))(&arena, size);
|
auto lists = Alloc!(LinkedList!(KVPair!(K, V)))(&arena, size);
|
||||||
|
|
||||||
HashTable!(K, V) table = {
|
HashTable!(K, V) table = {
|
||||||
arena: arena,
|
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)
|
Push(K, V)(HashTable!(K, V)* ht, K key, V value)
|
||||||
{
|
{
|
||||||
alias P = KVPair!(K, V);
|
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))
|
if(!CheckNil(ht.nil, ht.free_lists.first))
|
||||||
{
|
{
|
||||||
@ -586,12 +528,12 @@ Push(K, V)(HashTable!(K, V)* ht, K key, V value)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node = Alloc!(N)(&ht.arena);
|
node = Alloc!(P)(&ht.arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.next = ht.nil;
|
node.next = ht.nil;
|
||||||
node.value.key = key;
|
node.key = key;
|
||||||
node.value.value = value;
|
node.value = value;
|
||||||
|
|
||||||
SLLPush(GetList(ht, key), node, ht.nil);
|
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);
|
auto list = GetList(ht, key);
|
||||||
for(auto node = list.first; !CheckNil(ht.nil, node); node = node.next)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,7 +560,7 @@ Search(K, V)(HashTable!(K, V)* ht, K key)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) SLList!(KVPair!(K, V))*
|
pragma(inline) LinkedList!(KVPair!(K, V))*
|
||||||
GetList(K, V)(HashTable!(K, V)* ht, K key)
|
GetList(K, V)(HashTable!(K, V)* ht, K key)
|
||||||
{
|
{
|
||||||
u64 hash = Hash(&key);
|
u64 hash = Hash(&key);
|
||||||
@ -1000,8 +942,9 @@ Embed(string file_name)
|
|||||||
version(DLIB_TEST) unittest
|
version(DLIB_TEST) unittest
|
||||||
{
|
{
|
||||||
{ // Singly Linked List
|
{ // Singly Linked List
|
||||||
SLList!(u32) list;
|
alias LT = ListBox!(u32, false);
|
||||||
Node!(u32)[5] nodes;
|
LinkedList!(LT) list;
|
||||||
|
LT[5] nodes;
|
||||||
foreach(u32 i, n; nodes)
|
foreach(u32 i, n; nodes)
|
||||||
{
|
{
|
||||||
nodes[i].value = i;
|
nodes[i].value = i;
|
||||||
@ -1014,15 +957,15 @@ version(DLIB_TEST) unittest
|
|||||||
SLLRemove(&list, &nodes[1], &nodes[0], null);
|
SLLRemove(&list, &nodes[1], &nodes[0], null);
|
||||||
SLLRemove(&list, &nodes[3], &nodes[2], 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(list.first != null && list.last != null);
|
||||||
assert(n != null);
|
assert(n != null);
|
||||||
assert(n.next != 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)
|
foreach(i, v; result)
|
||||||
{
|
{
|
||||||
assert(n != null);
|
assert(n != null);
|
||||||
@ -1057,9 +1000,11 @@ version(DLIB_TEST) unittest
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Doubly Linked List
|
{ // 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)
|
foreach(i, v; result)
|
||||||
{
|
{
|
||||||
assert(n != null);
|
assert(n != null);
|
||||||
@ -1100,8 +1045,8 @@ version(DLIB_TEST) unittest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DLList!(u32) list;
|
LinkedList!(LT) list;
|
||||||
DNode!(u32)[5] nodes;
|
LT[5] nodes;
|
||||||
foreach(u32 i, n; nodes)
|
foreach(u32 i, n; nodes)
|
||||||
{
|
{
|
||||||
nodes[i].value = i;
|
nodes[i].value = i;
|
||||||
@ -1223,37 +1168,6 @@ version(DLIB_TEST) unittest
|
|||||||
assert(v3 > 0);
|
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
|
{ // Casts
|
||||||
u8[] arr = CastStr!(u8)("Test");
|
u8[] arr = CastStr!(u8)("Test");
|
||||||
char[] char_arr = ['a', 'b'];
|
char[] char_arr = ['a', 'b'];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user