hash table + basic profiler implemented, now using c23
This commit is contained in:
parent
a651082dcc
commit
c27b200984
@ -4,6 +4,8 @@ FLAlloc FL_ALLOC = {0};
|
||||
Allocator ALLOC = {0};
|
||||
read_only FLNode FL_NIL_NODE = {0};
|
||||
|
||||
#define ALLOC_CAP 16
|
||||
|
||||
// ::Allocator::Util::Header::
|
||||
|
||||
usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size)
|
||||
@ -32,7 +34,7 @@ usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size)
|
||||
|
||||
// ::Allocator::Arena::Start::
|
||||
|
||||
static Arena *CreateArena(rawptr buffer, usize length)
|
||||
static Arena *ArenaInit(rawptr buffer, usize length)
|
||||
{
|
||||
Arena *arena = (Arena *)buffer;
|
||||
buffer = PtrAdd(buffer, ARENA_HEADER_SIZE);
|
||||
@ -87,9 +89,9 @@ static void DeallocArena(Arena *arena)
|
||||
MemFree(arena, arena->length);
|
||||
}
|
||||
|
||||
static Arena * CreateArenaDebug(rawptr buffer, usize length, u32 init_line_no)
|
||||
static Arena * ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no)
|
||||
{
|
||||
Arena *arena = CreateArena(buffer, length);
|
||||
Arena *arena = ArenaInit(buffer, length);
|
||||
arena->init_line_no = init_line_no;
|
||||
return arena;
|
||||
}
|
||||
@ -100,45 +102,43 @@ static Arena * CreateArenaDebug(rawptr buffer, usize length, u32 init_line_no)
|
||||
|
||||
// ::Allocator::GlobalAlloc::Start::
|
||||
|
||||
static void InitAllocator(usize init_size, usize grow_size)
|
||||
static void InitAllocator(usize init_size)
|
||||
{
|
||||
usize size = init_size + sizeof(Allocator) + sizeof(FreeListBuffer) + sizeof(rawptr) + sizeof(RBNode);
|
||||
u8 *mem = (u8 *)MemAllocZeroed(size);
|
||||
Allocator *fl_alloc = (Allocator *)mem;
|
||||
ALLOC.tree = FLMemAlloc(sizeof(RBTree));
|
||||
RBTreeInit(ALLOC.tree);
|
||||
|
||||
u8 *pre_mem = mem;
|
||||
mem = (u8 *)PtrAdd(mem, sizeof(Alloc));
|
||||
usize rem_size = (size) - (pre_mem - mem);
|
||||
ALLOC.hash_table = FLMemAlloc(sizeof(HashTable));
|
||||
HashTableInit(ALLOC.hash_table, 32);
|
||||
|
||||
fl_alloc->buf_len = 1;
|
||||
fl_alloc->grow_size = grow_size;
|
||||
fl_alloc->buffers = (FreeListBuffer *)mem;
|
||||
ALLOC.buffers = FLMemAlloc(sizeof(FreeListBuffer) * ALLOC_CAP);
|
||||
ALLOC.count = 1;
|
||||
ALLOC.cap = ALLOC_CAP;
|
||||
ALLOC.grow_size = init_size;
|
||||
|
||||
pre_mem = mem;
|
||||
mem = (u8 *)PtrAdd(mem, sizeof(FreeListBuffer));
|
||||
rem_size -= pre_mem - mem;
|
||||
|
||||
fl_alloc->nil = (RBNode *)mem;
|
||||
|
||||
pre_mem = mem;
|
||||
mem = (u8 *)PtrAdd(mem, sizeof(RBNode));
|
||||
rem_size -= pre_mem - mem;
|
||||
|
||||
fl_alloc->buffers[0].buf = mem;
|
||||
fl_alloc->buffers[0].size = (u32)size;
|
||||
fl_alloc->buffers[0].free_size = (u32)rem_size;
|
||||
InitAllocatorBuffer(&ALLOC.buffers[0], init_size);
|
||||
}
|
||||
|
||||
static void InitAllocatorBuffer(FreeListBuffer *buffer, usize init_size)
|
||||
{
|
||||
buffer->buf = MemAllocZeroed(init_size);
|
||||
buffer->size = init_size;
|
||||
buffer->free_size = init_size;
|
||||
}
|
||||
|
||||
static void DeinitAlloc()
|
||||
{
|
||||
for (u8 i = ALLOC.buf_len-1; i >= 0; i--)
|
||||
for (u8 i = 0; i < ALLOC.count; i++)
|
||||
{
|
||||
MemFree(ALLOC.buffers[i].buf, ALLOC.buffers[i].size);
|
||||
}
|
||||
}
|
||||
|
||||
static rawptr Alloc(usize size)
|
||||
{
|
||||
return AllocAlign(size, DEFAULT_ALIGNMENT);
|
||||
}
|
||||
|
||||
static rawptr AllocAlign(usize size, usize alignment)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@ -150,9 +150,9 @@ static void Free(rawptr ptr)
|
||||
|
||||
static void AllocGrow()
|
||||
{
|
||||
u8 *mem = (u8 *)MemAllocZeroed(ALLOC.grow_size);
|
||||
|
||||
|
||||
Assert(ALLOC.count < ALLOC.cap, "Global allocator has reached capacity");
|
||||
InitAllocatorBuffer(&ALLOC.buffers[ALLOC.count], ALLOC.grow_size);
|
||||
ALLOC.count += 1;
|
||||
}
|
||||
|
||||
// ::Allocator::GlobalAlloc::End::
|
||||
|
||||
@ -22,13 +22,13 @@ typedef struct TempArena
|
||||
u64 pos;
|
||||
} TempArena;
|
||||
|
||||
static Arena *CreateArena(rawptr buffer, usize length);
|
||||
static Arena *ArenaInit(rawptr buffer, usize length);
|
||||
static rawptr ArenaAllocAlign(Arena *arena, usize size, usize align);
|
||||
static rawptr ArenaAlloc(Arena *arena, usize size);
|
||||
static void ArenaFree(Arena *arena);
|
||||
static void ArenaFreeZeroed(Arena *arena);
|
||||
static void DeallocArena(Arena *arena);
|
||||
static Arena *CreateArenaDebug(rawptr buffer, usize length, u32 init_line_no);
|
||||
static Arena *ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no);
|
||||
|
||||
// ::Allocator::GlobalAlloc::Header::
|
||||
|
||||
@ -41,17 +41,20 @@ typedef struct FreeListBuffer
|
||||
|
||||
typedef struct Allocator
|
||||
{
|
||||
RBNode *head;
|
||||
RBNode *nil;
|
||||
RBTree *tree;
|
||||
FreeListBuffer *buffers;
|
||||
HashTable *hash_table;
|
||||
usize grow_size;
|
||||
u8 buf_len;
|
||||
u64 count;
|
||||
u64 cap;
|
||||
} Allocator;
|
||||
|
||||
static void InitAllocator(usize init_size, usize grow_size);
|
||||
static void InitAllocator(usize init_size);
|
||||
static void InitAllocatorBuffer(FreeListBuffer *buffer, usize init_size);
|
||||
static void DeinitAlloc();
|
||||
static void AllocGrow();
|
||||
static rawptr Alloc(usize size);
|
||||
static rawptr AllocAlign(usize size, usize alignment);
|
||||
static void Free(rawptr ptr);
|
||||
|
||||
// ::Allocator::FreeList::Header::
|
||||
|
||||
111
src/ds.c
111
src/ds.c
@ -1,6 +1,10 @@
|
||||
// ::DataStructures::Globals::Start::
|
||||
|
||||
RBNode RB_NIL = { .color = RB_BLACK };
|
||||
RBNode *P_RB_NIL = &RB_NIL;
|
||||
|
||||
HashNode HT_NIL = {0};
|
||||
HashNode *P_HT_NIL = &HT_NIL;
|
||||
|
||||
// ::DataStructures::Globals::End::
|
||||
|
||||
@ -8,17 +12,19 @@ RBNode RB_NIL = { .color = RB_BLACK };
|
||||
|
||||
// ::DataStructures::RedBlackTree::Functions::Start::
|
||||
|
||||
static void CreateRBTree(RBTree *tree)
|
||||
static void RBTreeInit(RBTree *tree)
|
||||
{
|
||||
Assert(tree != NULL, "RBTree is null");
|
||||
RB_NIL.right = RB_NIL.left = RB_NIL.parent = &RB_NIL;
|
||||
RB_NIL.right = RB_NIL.left = RB_NIL.parent = P_RB_NIL;
|
||||
|
||||
tree->root = &RB_NIL;
|
||||
tree->nil = &RB_NIL;
|
||||
tree->root = P_RB_NIL;
|
||||
tree->nil = P_RB_NIL;
|
||||
}
|
||||
|
||||
static void RBTreeInsert(RBTree *tree, RBNode *node)
|
||||
static RBNode *RBTreeFindOrInsert(RBTree *tree, RBNode *node)
|
||||
{
|
||||
RBNode *existing_node = P_RB_NIL;
|
||||
|
||||
node->left = node->right = tree->nil;
|
||||
node->color = RB_RED;
|
||||
|
||||
@ -35,7 +41,12 @@ static void RBTreeInsert(RBTree *tree, RBNode *node)
|
||||
{
|
||||
Assert(curr_node != tree->nil, "Current Node is NIL");
|
||||
|
||||
if (curr_node->value < node->value)
|
||||
if (curr_node->value == node->value)
|
||||
{
|
||||
existing_node = curr_node;
|
||||
break;
|
||||
}
|
||||
else if (curr_node->value < node->value)
|
||||
{
|
||||
if (curr_node->right == tree->nil)
|
||||
{
|
||||
@ -64,8 +75,10 @@ static void RBTreeInsert(RBTree *tree, RBNode *node)
|
||||
}
|
||||
}
|
||||
|
||||
if (node->parent->color != RB_BLACK)
|
||||
if (node->parent->color != RB_BLACK && existing_node != P_RB_NIL)
|
||||
RBTreeCorrect(tree, node);
|
||||
|
||||
return existing_node;
|
||||
}
|
||||
|
||||
static void RBTreeCorrect(RBTree *tree, RBNode *node)
|
||||
@ -332,15 +345,95 @@ static void RBTreeRightRotate(RBTree *tree, RBNode *node)
|
||||
|
||||
// ::DataStructures::HashTable::Functions::Start::
|
||||
|
||||
static void InitHashTable(HashTable *table, u32 init_size)
|
||||
static void HashTableInit(HashTable *table, u32 init_size)
|
||||
{
|
||||
table->elem_count = init_size;
|
||||
table->cap = init_size;
|
||||
table->count = 0;
|
||||
table->lists = FLMemAlloc(sizeof(HashList) * init_size);
|
||||
table->free_lists.first = P_HT_NIL;
|
||||
table->free_lists.last = P_HT_NIL;
|
||||
}
|
||||
|
||||
static void HashTableConcatInPlace(HashList *list, HashList *to_concat)
|
||||
{
|
||||
SLLConcatInPlaceNoCount(list, to_concat);
|
||||
}
|
||||
|
||||
static void HashTableClear(HashTable *table)
|
||||
{
|
||||
table->count = 0;
|
||||
for (u32 i = 0; i < table->count; i++)
|
||||
{
|
||||
HashTableConcatInPlace(&table->free_lists, &table->lists[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static HashNode *HashListPop(HashList *list)
|
||||
{
|
||||
HashNode *result = list->first;
|
||||
HTQueuePop(list->first, list->last);
|
||||
return result;
|
||||
}
|
||||
|
||||
static HashNode *HashTablePush(HashTable *table, u64 hash, KeyValuePair value)
|
||||
{
|
||||
HashNode *node = NULL;
|
||||
if (table->free_lists.first != P_HT_NIL)
|
||||
node = HashListPop(&table->free_lists);
|
||||
else
|
||||
node = FLMemAlloc(sizeof(HashNode));
|
||||
|
||||
node->next = P_HT_NIL;
|
||||
node->v = value;
|
||||
|
||||
u64 index = hash % table->cap;
|
||||
HTQueuePush(table->lists[index].first, table->lists[index].last, node);
|
||||
table->count += 1;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static HashNode *HashTablePushU32(HashTable *table, u64 key, u32 value)
|
||||
{
|
||||
u64 hash = HashFromString(String8Struct(&key));
|
||||
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u32 = value });
|
||||
}
|
||||
|
||||
static HashNode *HashTablePushU64(HashTable *table, u64 key, u64 value)
|
||||
{
|
||||
u64 hash = HashFromString(String8Struct(&key));
|
||||
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u64 = value });
|
||||
}
|
||||
|
||||
static HashNode *HashTablePushString8(HashTable *table, u64 key, String8 value)
|
||||
{
|
||||
u64 hash = HashFromString(String8Struct(&key));
|
||||
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_string = value });
|
||||
}
|
||||
|
||||
static HashNode *HashTablePushRawptr(HashTable *table, u64 key, rawptr value)
|
||||
{
|
||||
u64 hash = HashFromString(String8Struct(&key));
|
||||
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_rawptr = value });
|
||||
}
|
||||
|
||||
static KeyValuePair *HashTableSearchU64(HashTable *table, u64 key)
|
||||
{
|
||||
KeyValuePair *result = NULL;
|
||||
|
||||
u64 hash = HashFromString(String8Struct(&key));
|
||||
u64 index = hash % table->cap;
|
||||
HashList *list = table->lists + index;
|
||||
for (HashNode *node = list->first; node != P_HT_NIL; node = node->next)
|
||||
{
|
||||
if (node->v.key_u64 == key)
|
||||
{
|
||||
result = &node->v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ::DataStructures::HashTable::Functions::End::
|
||||
|
||||
26
src/ds.h
26
src/ds.h
@ -41,8 +41,8 @@ typedef struct RBTree
|
||||
RBNode *nil;
|
||||
} RBTree;
|
||||
|
||||
static void CreateRBTree (RBTree *tree);
|
||||
static void RBTreeInsert (RBTree *tree, RBNode *node);
|
||||
static void RBTreeInit (RBTree *tree);
|
||||
static RBNode *RBTreeFindOrInsert(RBTree *tree, RBNode *node);
|
||||
static b32 RBTreeSearch (RBTree *tree, i32 value, RBNode **node);
|
||||
static void RBTreeDelete (RBTree *tree, i32 value);
|
||||
static void RBTreeLeftRotate (RBTree *tree, RBNode *node);
|
||||
@ -53,6 +53,10 @@ static void RBTreeTransplant (RBTree *tree, RBNode *node, RBNode *placed_node);
|
||||
|
||||
// ::DataStructures::HashTable::Functions::Header::
|
||||
|
||||
#define HTQueuePop(f, l) SLLQueuePop(&HT_NIL, f, l)
|
||||
#define HTQueuePush(f, l, n) SLLQueuePush(&HT_NIL, f, l, n)
|
||||
#define HTQueuePushFront(f, l, n) SLLQueuePush(&HT_NIL, f, l, n)
|
||||
|
||||
typedef struct KeyValuePair
|
||||
{
|
||||
union
|
||||
@ -61,7 +65,7 @@ typedef struct KeyValuePair
|
||||
};
|
||||
union
|
||||
{
|
||||
Str8 value_string;
|
||||
String8 value_string;
|
||||
rawptr value_rawptr;
|
||||
u32 value_u32;
|
||||
u64 value_u64;
|
||||
@ -82,15 +86,21 @@ typedef struct HashList
|
||||
|
||||
typedef struct HashTable
|
||||
{
|
||||
HashElement *lists;
|
||||
u32 elem_count;
|
||||
} HashTable;
|
||||
HashList *lists;
|
||||
HashList free_lists;
|
||||
u64 count;
|
||||
u32 cap;
|
||||
} HashTable;
|
||||
|
||||
static void InitHashTable(HashTable *table, u32 init_size);
|
||||
static void HashTableInit(HashTable *table, u32 init_size);
|
||||
static void HashTableClear(HashTable *table);
|
||||
static void HashTableConcatInPlace(HashList *list, HashList *to_concat);
|
||||
static u64 HashTableHash(String8 str);
|
||||
static HashNode *HashListPop(HashList *list);
|
||||
static KeyValuePair *HashTableSearchU64(HashTable *table, u64 key);
|
||||
static HashNode *HashTablePush(HashTable *table, u64 hash, KeyValuePair value);
|
||||
static HashNode *HashTablePushU32(HashTable *table, u64 key, u32 value);
|
||||
static HashNode *HashTablePushU64(HashTable *table, u64 key, u64 value);
|
||||
static HashNode *HashTablePushStr8(HashTable *table, u64 key, Str8 value);
|
||||
static HashNode *HashTablePushString8(HashTable *table, u64 key, String8 value);
|
||||
static HashNode *HashTablePushRawptr(HashTable *table, u64 key, rawptr value);
|
||||
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
# include "tests.c"
|
||||
#endif
|
||||
|
||||
static_assert(__COUNTER__ < Len(GLOBAL_PROFILER.anchors));
|
||||
|
||||
void TraverseNode(RBTree *tree, RBNode *node, RBNodeDir *dir)
|
||||
{
|
||||
char *dir_str = dir == NULL ? "Root" : *dir == RB_RIGHT ? "Right" : "Left";
|
||||
@ -48,16 +50,16 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
|
||||
u8 *mem = (u8 *)MemAllocZeroed(MB(64));
|
||||
Arena *arena = CreateArenaDebug(mem, MB(64), __LINE__);
|
||||
Arena *arena = ArenaInitDebug(mem, MB(64), __LINE__);
|
||||
|
||||
usize renderer_mem_size = MB(16);
|
||||
usize game_mem_size = MB(16);
|
||||
|
||||
rawptr renderer_mem = ArenaAlloc(arena, renderer_mem_size);
|
||||
Arena *renderer_arena = CreateArenaDebug(renderer_mem, renderer_mem_size, 2);
|
||||
Arena *renderer_arena = ArenaInitDebug(renderer_mem, renderer_mem_size, 2);
|
||||
|
||||
rawptr game_mem = ArenaAlloc(arena, game_mem_size);
|
||||
Arena *game_arena = CreateArenaDebug(game_mem, game_mem_size, 3);
|
||||
Arena *game_arena = ArenaInitDebug(game_mem, game_mem_size, 3);
|
||||
|
||||
Assert(CreatePlatformWindow(WINDOW_NAME), "Failed to initialize the window");
|
||||
|
||||
|
||||
@ -20,16 +20,16 @@ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmd_line
|
||||
#endif
|
||||
|
||||
u8 *mem = (u8 *)MemAllocZeroed(MB(32));
|
||||
Arena *arena = CreateArenaDebug(mem, MB(32), 1);
|
||||
Arena *arena = ArenaInitDebug(mem, MB(32), 1);
|
||||
|
||||
isize renderer_mem_size = MB(16);
|
||||
isize game_mem_size = MB(16);
|
||||
|
||||
rawptr renderer_mem = ArenaAlloc(arena, renderer_mem_size);
|
||||
Arena *renderer_arena = CreateArenaDebug(renderer_mem, renderer_mem_size, 2);
|
||||
Arena *renderer_arena = ArenaInitDebug(renderer_mem, renderer_mem_size, 2);
|
||||
|
||||
rawptr game_mem = ArenaAlloc(arena, game_mem_size);
|
||||
Arena *game_arena = CreateArenaDebug(game_mem, game_mem_size, 3);
|
||||
Arena *game_arena = ArenaInitDebug(game_mem, game_mem_size, 3);
|
||||
|
||||
Assert(CreatePlatformWindow(WINDOW_NAME), "Failed to initialize window");
|
||||
|
||||
|
||||
@ -186,7 +186,7 @@ static inline void PrepareGUICtx(GameContext *ctx)
|
||||
static b32 UIButton(GameContext *ctx, char *label, f32 x0, f32 y0, f32 x1, f32 y1)
|
||||
{
|
||||
GUIButton *btn = NULL;
|
||||
u64 id = HashFromString(Str8L(label));
|
||||
u64 id = HashFromString(String8CStr(label));
|
||||
if (ctx->btn_len == 0)
|
||||
{
|
||||
ctx->buttons[0].p0.x = x0;
|
||||
@ -246,7 +246,7 @@ static b32 UIButton(GameContext *ctx, char *label, f32 x0, f32 y0, f32 x1, f32 y
|
||||
static b32 UIWindow(GameContext *ctx, char *title, f32 x0, f32 y0, f32 x1, f32 y1)
|
||||
{
|
||||
GUIWindow *win = NULL;
|
||||
u32 id = HashFromString(Str8L(title));
|
||||
u32 id = HashFromString(String8CStr(title));
|
||||
if (ctx->window_len == 0)
|
||||
{
|
||||
ctx->windows[0].p0.x = x0;
|
||||
|
||||
@ -375,7 +375,7 @@ int main(int argc, c8 **argv)
|
||||
SetArrayLookups();
|
||||
|
||||
void *mem = MemAllocZeroed(GB(1));
|
||||
Arena *arena = CreateArenaDebug(mem, GB(1), __LINE__);
|
||||
Arena *arena = ArenaInitDebug(mem, GB(1), __LINE__);
|
||||
|
||||
FILE *file = fopen("assets.sgp", "w+");
|
||||
Assert(file != NULL, "File is null");
|
||||
|
||||
@ -64,3 +64,9 @@ u32 AvailableCPUCount();
|
||||
b32 ChangeDir(c8 *dir);
|
||||
c8 **GetFileNamesInDir(Arena *arena, u32 *count);
|
||||
b8 DirVisible(c8 *dir_name);
|
||||
|
||||
// ::Platform::Profiling::Functions::Header::
|
||||
|
||||
static u64 GetOSTimerFreq();
|
||||
static u64 ReadOSTimer();
|
||||
static inline u64 ReadCPUTimer();
|
||||
|
||||
@ -23,6 +23,8 @@
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <x86intrin.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
// ::Platform::Linux::Defines::Header::
|
||||
|
||||
|
||||
@ -305,3 +305,27 @@ b8 DirVisible(c8 *dir_name)
|
||||
}
|
||||
|
||||
// ::Platform::Functions::Directory::End::
|
||||
|
||||
|
||||
|
||||
// ::Platform::Profiling::Functions::Start::
|
||||
|
||||
static u64 GetOSTimerFreq()
|
||||
{
|
||||
return 1000000;
|
||||
}
|
||||
|
||||
static u64 ReadOSTimer()
|
||||
{
|
||||
struct timeval value;
|
||||
gettimeofday(&value, 0);
|
||||
|
||||
return GetOSTimerFreq() * u64(value.tv_sec) + u64(value.tv_usec);
|
||||
}
|
||||
|
||||
static inline u64 ReadCPUTimer()
|
||||
{
|
||||
return __rdtsc();
|
||||
}
|
||||
|
||||
// ::Platform::Profiling::Functions::End::
|
||||
|
||||
@ -70,7 +70,6 @@ static void BindIndexBuffer(RenderBuffer *buffer);
|
||||
static void GetViewportSize(Vec2 *size);
|
||||
static void SetGlobalUniform(ShaderGlobals *globals);
|
||||
static void SetPushConstants(PushConst *pc);
|
||||
static DescHandle UploadImageUniform();
|
||||
|
||||
// ::Renderer::Config::Header::
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ b32 InitRenderer(Arena *arena)
|
||||
Assert(arena != NULL, "Vulkan memory is null");
|
||||
renderer.perm_arena = arena;
|
||||
void *mem = ArenaAlloc(arena, MB(8));
|
||||
renderer.arena = CreateArena(mem, MB(8));
|
||||
renderer.arena = ArenaInit(mem, MB(8));
|
||||
|
||||
Assert(InitVkGlobalFunctions(), "Unable to load vulkan functions");
|
||||
{
|
||||
|
||||
@ -177,11 +177,11 @@ typedef uint32_t b32;
|
||||
|
||||
typedef void * rawptr;
|
||||
|
||||
typedef struct Str8
|
||||
typedef struct String8
|
||||
{
|
||||
u32 len;
|
||||
u8 *value;
|
||||
} Str8;
|
||||
u64 len;
|
||||
} String8;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
|
||||
29
src/tests.c
29
src/tests.c
@ -1,11 +1,16 @@
|
||||
// TODO: Make the tests actually decent
|
||||
|
||||
void RunTests()
|
||||
{
|
||||
GlobalFreeListInit(MB(32));
|
||||
TestFreeListAlloc();
|
||||
TestHashTable();
|
||||
}
|
||||
|
||||
void TestFreeListAlloc()
|
||||
{
|
||||
Printfln("Starting free list allocator tests...");
|
||||
|
||||
FLAlloc alloc = {0};
|
||||
usize alloc_size = KB(256);
|
||||
FreeListInit(&alloc, alloc_size);
|
||||
@ -46,3 +51,27 @@ void TestFreeListAlloc()
|
||||
Assert(f64_arr[i] == f64(i), "f64 memory incorrect post free");
|
||||
}
|
||||
}
|
||||
|
||||
void TestHashTable()
|
||||
{
|
||||
Printfln("Starting hash table tests...");
|
||||
HashTable table;
|
||||
HashTableInit(&table, 16);
|
||||
|
||||
for (u64 i = 1; i < 2000; i++)
|
||||
{
|
||||
HashTablePushU64(&table, i*3, i);
|
||||
}
|
||||
|
||||
for (u64 i = 1; i < 2000; i++)
|
||||
{
|
||||
KeyValuePair *result = HashTableSearchU64(&table, i*3);
|
||||
Assert(result != P_HT_NIL, "HashTable result isn't found");
|
||||
Assert(result->value_u64 == i, "HashTable result doesn't match");
|
||||
}
|
||||
|
||||
HashTableClear(&table);
|
||||
|
||||
KeyValuePair *result = HashTableSearchU64(&table, 1);
|
||||
Assert(result == NULL, "Result isn't nil after HashTable clear");
|
||||
}
|
||||
|
||||
@ -2,4 +2,5 @@
|
||||
|
||||
void RunTests();
|
||||
void TestFreeListAlloc();
|
||||
void TestHashTable();
|
||||
|
||||
|
||||
47
src/util.c
47
src/util.c
@ -1,3 +1,11 @@
|
||||
// ::Util::Globals::Start::
|
||||
|
||||
static Profiler GLOBAL_PROFILER;
|
||||
|
||||
// ::Util::Globals::End::
|
||||
|
||||
|
||||
|
||||
// ::Util::Strings::Functions::Start::
|
||||
|
||||
b32 StrEq(const char *l, const char *r) {
|
||||
@ -26,12 +34,12 @@ i32 SPrintf(char *buf, rawptr fmt, ...)
|
||||
return sprf_res;
|
||||
}
|
||||
|
||||
Str8 MakeStr8(u8 *str, u32 len)
|
||||
String8 MakeString8(u8 *str, u64 len)
|
||||
{
|
||||
return (Str8){ .len = len, .value = str };
|
||||
return (String8){ .len = len, .value = str };
|
||||
}
|
||||
|
||||
Str8 PreSplitStr8(Str8 string, Str8 delimiter)
|
||||
String8 PreSplitString8(String8 string, String8 delimiter)
|
||||
{
|
||||
if (string.len == 0 || delimiter.len == 0) return string;
|
||||
|
||||
@ -53,12 +61,12 @@ Str8 PreSplitStr8(Str8 string, Str8 delimiter)
|
||||
}
|
||||
}
|
||||
|
||||
return (Str8){ .len = new_len, .value = string.value };
|
||||
return (String8){ .len = new_len, .value = string.value };
|
||||
}
|
||||
|
||||
Str8 PreSplitNewStr8(Arena *arena, Str8 string, Str8 delimiter)
|
||||
String8 PreSplitNewString8(Arena *arena, String8 string, String8 delimiter)
|
||||
{
|
||||
Str8 result = PreSplitStr8(string, delimiter);
|
||||
String8 result = PreSplitString8(string, delimiter);
|
||||
|
||||
if (result.len > 0)
|
||||
{
|
||||
@ -192,9 +200,9 @@ u32 u32Clamp(u32 v, u32 min, u32 max)
|
||||
|
||||
// ::Util::Hashing::Functions::Start::
|
||||
|
||||
u64 static inline HashFromString(Str8 string)
|
||||
u64 static inline HashFromString(String8 string)
|
||||
{
|
||||
return XXH3_64bits_withSeed(string.value, string.len, HASH_SEED);
|
||||
return XXH3_64bits(string.value, string.len);
|
||||
}
|
||||
|
||||
// ::Util::Hashing::Functions::End::
|
||||
@ -289,3 +297,26 @@ i32 _Printfln(char *fmt, va_list arg)
|
||||
}
|
||||
|
||||
// ::Util::Print::Functions::End::
|
||||
|
||||
|
||||
|
||||
// ::Util::Profiling::Functions::Start::
|
||||
|
||||
static inline void StartProfileBlock(ProfileBlock *block, c8 *label, u32 anchor_index)
|
||||
{
|
||||
block->anchor_index = anchor_index;
|
||||
block->label = label;
|
||||
block->start_tsc = ReadCPUTimer();
|
||||
}
|
||||
|
||||
static inline void EndProfileBlock(ProfileBlock *block)
|
||||
{
|
||||
u64 elapsed = ReadCPUTimer() - block->start_tsc;
|
||||
|
||||
ProfileAnchor *anchor = GLOBAL_PROFILER.anchors + block->anchor_index;
|
||||
anchor->tsc_elapsed += elapsed;
|
||||
anchor->hit_count += 1;
|
||||
anchor->label = block->label;
|
||||
}
|
||||
|
||||
// ::Util::Profiling::Functions::End::
|
||||
|
||||
95
src/util.h
95
src/util.h
@ -21,7 +21,6 @@ typedef struct Arena Arena;
|
||||
#define MakeArray(arena, type, count) ArenaAlloc(arena, (isize)(sizeof(type)) * (isize)(count))
|
||||
#define Len(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||
|
||||
#define Str8L(x) (Str8){ .len = StrLen(x), .value = (u8 *)x }
|
||||
#define MakeString(x) #x
|
||||
|
||||
#define i8(x) ((i8)(x))
|
||||
@ -49,6 +48,49 @@ typedef struct Arena Arena;
|
||||
|
||||
#define cast(T, x) ((T)(x))
|
||||
|
||||
// ::Util::LinkedList::Macros::
|
||||
|
||||
#define CheckNil(nil, p) ((p) == 0 || (p) == nil)
|
||||
#define SetNil(nil, p) ((p) = nil)
|
||||
|
||||
// ::Util::DoubleHeadedLinkedList::Macros::
|
||||
|
||||
#define SLLConcatInPlaceNoCount(list, to_concat) do { \
|
||||
if ((to_concat)->first) \
|
||||
{ \
|
||||
if ((list)->first) \
|
||||
{ \
|
||||
(list)->last->next = (to_concat)->first; \
|
||||
(list)->last = (to_concat)->last; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(list)->first = (to_concat)->first; \
|
||||
(list)->last = (to_concat)->last; \
|
||||
} \
|
||||
MemZero(to_concat, sizeof(*to_concat)); \
|
||||
} \
|
||||
} while (0)
|
||||
#define _SLLQueuePop(nil, f, l, next) ((f) == (l) ? \
|
||||
(SetNil(nil, f), SetNil(nil, l)) : \
|
||||
((f) = (f)->next))
|
||||
#define _SLLQueuePushFront(nil, f, l, n, next) (CheckNil(nil, f) ? \
|
||||
((f) = (l) = (n), SetNil(nil, (n)->next)) : \
|
||||
((n)->next = (f), (f) = (n)))
|
||||
#define _SLLQueuePush(nil, f, l, n, next) (CheckNil(nil, f) ? \
|
||||
((f) = (l) = (n), SetNil(nil, (n)->next)) : \
|
||||
((l)->next = (n), (l) = (n), SetNil(nil, (n)->next)))
|
||||
|
||||
#define SLLQueuePop(nil, f, l) _SLLQueuePop(nil, f, l, next)
|
||||
#define SLLQueuePush(nil, f, l, n) _SLLQueuePush(nil, f, l, n, next)
|
||||
#define SLLQueuePushFront(nil, f, l, n) _SLLQueuePushFront(nil, f, l, n, next)
|
||||
|
||||
// ::Util::String8::Macros::
|
||||
|
||||
#define String8Array(v, c) MakeString8((u8 *)(v), sizeof(*(v))*(c))
|
||||
#define String8Struct(v) MakeString8((u8 *)(v), sizeof(*(v)))
|
||||
#define String8CStr(v) MakeString8((u8 *)v, StrLen(v))
|
||||
|
||||
// ::Util::Defines::Header::
|
||||
|
||||
#define HM_MAX_SYMBOLS 256
|
||||
@ -57,12 +99,12 @@ typedef struct Arena Arena;
|
||||
|
||||
// ::Util::Strings::Functions::Header::
|
||||
|
||||
String8 MakeString8(u8 *str, u64 len);
|
||||
u32 StrLen(const char *str);
|
||||
b32 StrEq(const char *l, const char *r);
|
||||
i32 SPrintf(char *buf, rawptr fmt, ...);
|
||||
Str8 MakeStr8(u8 *str, u32 len);
|
||||
Str8 PreSplitStr8(Str8 string, Str8 delimiter);
|
||||
Str8 PreSplitNewStr8(Arena *arena, Str8 string, Str8 delimiter);
|
||||
String8 PreSplitString8(String8 string, String8 delimiter);
|
||||
String8 PreSplitNewString8(Arena *arena, String8 string, String8 delimiter);
|
||||
|
||||
// ::Util::Memory::Functions::Header::
|
||||
|
||||
@ -80,7 +122,7 @@ u32 u32Clamp(u32 v, u32 min, u32 max);
|
||||
|
||||
// ::Util::Hashing::Functions::Header::
|
||||
|
||||
u64 static inline HashFromString(Str8 string);
|
||||
u64 static inline HashFromString(String8 string);
|
||||
|
||||
// ::Util::Print::Functions::Header::
|
||||
|
||||
@ -92,3 +134,46 @@ i32 _EPrint(void *str);
|
||||
i32 _Printf(char *fmt, va_list arg);
|
||||
i32 _Printfln(char *fmt, va_list arg);
|
||||
i32 _EPrintf(char *fmt, va_list arg);
|
||||
|
||||
// ::Util::Profiling::Header::
|
||||
|
||||
#define NameConcat2(a, b) a##b
|
||||
|
||||
#define NameConcat(a, b) NameConcat2(a, b)
|
||||
|
||||
#define TimeBlockStart(name) ProfileBlock NameConcat(Block, name) = {0}; \
|
||||
StartProfileBlock(&NameConcat(Block, name), #name, __COUNTER__ + 1)
|
||||
|
||||
#define TimeBlockEnd(name) EndProfileBlock(&NameConcat(Block, name))
|
||||
|
||||
#define TimeBlockFuncStart(name) ProfileBlock NameConcat(Block, function) = {0}; \
|
||||
StartProfileBlock(& NameConcat(Block, function), name, __COUNTER__ + 1)
|
||||
|
||||
#define TimeFunctionStart TimeBlockFuncStart(__func__)
|
||||
|
||||
#define TimeFunctionEnd TimeBlockEnd(function)
|
||||
|
||||
typedef struct ProfileAnchor
|
||||
{
|
||||
u64 tsc_elapsed;
|
||||
u64 hit_count;
|
||||
c8 *label;
|
||||
} ProfileAnchor;
|
||||
|
||||
typedef struct ProfileBlock
|
||||
{
|
||||
c8 *label;
|
||||
u64 start_tsc;
|
||||
u32 anchor_index;
|
||||
} ProfileBlock;
|
||||
|
||||
typedef struct Profiler
|
||||
{
|
||||
ProfileAnchor anchors[4096];
|
||||
u64 start_tsc;
|
||||
u64 end_tsc;
|
||||
} Profiler;
|
||||
|
||||
static inline void StartProfileBlock(ProfileBlock *block, c8 *label, u32 anchor_index);
|
||||
static inline void EndProfileBlock(ProfileBlock *block);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user