mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
lock free hash trie
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
lfht_insert(Arena *arena,
|
||||||
|
LFHT_NodeChunkList *node_chunks,
|
||||||
|
LFHT_Node **root_ptr,
|
||||||
|
U64 hash,
|
||||||
|
void *data,
|
||||||
|
LFHT_IsKeyEqualFunc *is_key_equal,
|
||||||
|
void *is_key_equal_ud)
|
||||||
|
{
|
||||||
|
B32 was_inserted = 0;
|
||||||
|
LFHT_Node **curr_ptr = root_ptr;
|
||||||
|
for (U64 h = hash; ; h <<= 2) {
|
||||||
|
LFHT_Node *curr = ins_atomic_ptr_eval(curr_ptr);
|
||||||
|
|
||||||
|
if (curr == 0) {
|
||||||
|
if (node_chunks->last == 0 || node_chunks->last->count >= node_chunks->last->max) {
|
||||||
|
LFHT_NodeChunk *c = push_array(arena, LFHT_NodeChunk, 1);
|
||||||
|
c->max = 1024;
|
||||||
|
c->count = 0;
|
||||||
|
c->v = push_array_no_zero(arena, LFHT_Node, 1024);
|
||||||
|
|
||||||
|
SLLQueuePush(node_chunks->first, node_chunks->last, c);
|
||||||
|
node_chunks->chunk_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LFHT_Node *n = &node_chunks->last->v[node_chunks->last->count];
|
||||||
|
MemoryZeroStruct(n);
|
||||||
|
n->data = data;
|
||||||
|
|
||||||
|
LFHT_Node *cmp = ins_atomic_ptr_eval_cond_assign(curr_ptr, n, curr);
|
||||||
|
if (cmp == curr) {
|
||||||
|
node_chunks->last->count += 1;
|
||||||
|
node_chunks->total_count += 1;
|
||||||
|
was_inserted = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// was the key already inserted?
|
||||||
|
if (is_key_equal(is_key_equal_ud, curr->data, data)) { break; }
|
||||||
|
|
||||||
|
// descend
|
||||||
|
curr_ptr = &curr->children[h >> 62];
|
||||||
|
}
|
||||||
|
return was_inserted;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void *
|
||||||
|
lfht_search(LFHT_Node *root, U64 hash, void *data, LFHT_IsKeyEqualFunc *is_key_equal, void *is_key_equal_ud)
|
||||||
|
{
|
||||||
|
LFHT_Node *curr = root;
|
||||||
|
for (U64 h = hash; ; h <<= 2) {
|
||||||
|
if (curr == 0) { break; }
|
||||||
|
if (is_key_equal(is_key_equal_ud, curr->data, data)) { break; }
|
||||||
|
curr = curr->children[h >> 62];
|
||||||
|
}
|
||||||
|
return curr ? curr->data : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
lfht_total_count_from_node_chunk_lists(U64 list_count, LFHT_NodeChunkList *lists)
|
||||||
|
{
|
||||||
|
U64 total_count = 0;
|
||||||
|
for EachIndex(i, list_count) { total_count += lists[i].total_count; }
|
||||||
|
return total_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void **
|
||||||
|
lfht_data_from_node_chunk_lists(Arena *arena, U64 total_count, U64 list_count, LFHT_NodeChunkList *lists)
|
||||||
|
{
|
||||||
|
U64 result_count = 0;
|
||||||
|
void **result = push_array(arena, void *, total_count);
|
||||||
|
for EachIndex(list_idx, list_count) {
|
||||||
|
LFHT_NodeChunkList l = lists[list_idx];
|
||||||
|
for EachNode(c, LFHT_NodeChunk, l.first) {
|
||||||
|
Assert(result_count + c->count <= total_count);
|
||||||
|
for EachIndex(item_idx, c->count) {
|
||||||
|
result[result_count++] = c->v[item_idx].data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef LF_HASH_TABLE_H
|
||||||
|
#define LF_HAHS_TABLE_H
|
||||||
|
|
||||||
|
typedef struct LFHT_Node
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
struct LFHT_Node *children[4];
|
||||||
|
} LFHT_Node;
|
||||||
|
|
||||||
|
typedef struct LFHT_NodeChunk
|
||||||
|
{
|
||||||
|
struct LFHT_NodeChunk *next;
|
||||||
|
U64 max;
|
||||||
|
U64 count;
|
||||||
|
LFHT_Node *v;
|
||||||
|
} LFHT_NodeChunk;
|
||||||
|
|
||||||
|
typedef struct LFHT_NodeChunkList
|
||||||
|
{
|
||||||
|
U64 chunk_count;
|
||||||
|
U64 total_count;
|
||||||
|
LFHT_NodeChunk *first;
|
||||||
|
LFHT_NodeChunk *last;
|
||||||
|
} LFHT_NodeChunkList;
|
||||||
|
|
||||||
|
#define LFHT_IS_KEY_EQUAL_FUNC(name) B32 name(void *ud, void *a, void *b)
|
||||||
|
typedef LFHT_IS_KEY_EQUAL_FUNC(LFHT_IsKeyEqualFunc);
|
||||||
|
|
||||||
|
internal B32 lfht_insert(Arena *arena, LFHT_NodeChunkList *node_chunks, LFHT_Node **root_ptr, U64 hash, void *data, LFHT_IsKeyEqualFunc *is_key_equal, void *is_key_equal_ud);
|
||||||
|
|
||||||
|
internal void ** lfht_data_from_node_chunk_lists(Arena *arena, U64 total_count, U64 list_count, LFHT_NodeChunkList *lists);
|
||||||
|
|
||||||
|
#endif // LF_HASH_TABLE_H
|
||||||
Reference in New Issue
Block a user