start work on changing rb tree to use linked list buckets
This commit is contained in:
parent
30153e1af3
commit
8c45c914f0
@ -176,8 +176,15 @@ static rawptr AllocAlign(usize size, usize alignment)
|
||||
if (alignment < 8)
|
||||
alignment = 8;
|
||||
|
||||
RBNode *node = NULL;
|
||||
RBTreeSearch(ALLOC.tree, size, &node);
|
||||
RBNode *node = P_RB_NIL;
|
||||
rawptr mem = NULL;
|
||||
if (!RBTreeSearchNearest(ALLOC.tree, size, &node))
|
||||
{
|
||||
AllocGrow(size);
|
||||
RBTreeSearchNearest(ALLOC.tree, size, &node);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void Free(rawptr ptr)
|
||||
@ -191,6 +198,10 @@ static void AllocGrow(usize size)
|
||||
{
|
||||
usize grow_size = size < ALLOC.grow_size ? ALLOC.grow_size : ALLOC.grow_size + size;
|
||||
MemRealloc(ALLOC.buffer, ALLOC.size, ALLOC.size + grow_size);
|
||||
|
||||
AllocInfo *info = CreateAllocInfo(ALLOC.buffer + ALLOC.size); // TODO: check this if things fuck up it could be wrong
|
||||
RBTreeFindOrInsert(ALLOC.tree, grow_size, info);
|
||||
|
||||
ALLOC.size += grow_size;
|
||||
ALLOC.free_size += grow_size;
|
||||
}
|
||||
@ -211,6 +222,13 @@ static rawptr FLMemAlloc(usize size)
|
||||
return FreeListAlloc(&FL_ALLOC, size);
|
||||
}
|
||||
|
||||
static rawptr FLMemAllocZeroed(usize size)
|
||||
{
|
||||
rawptr ptr = FreeListAlloc(&FL_ALLOC, size);
|
||||
MemZero(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void FLMemFree(rawptr ptr)
|
||||
{
|
||||
FreeListFree(&FL_ALLOC, ptr);
|
||||
|
||||
@ -34,13 +34,14 @@ static Arena *ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no);
|
||||
|
||||
typedef struct AllocInfo
|
||||
{
|
||||
rawptr *ptrs;
|
||||
u32 count;
|
||||
rawptr ptr;
|
||||
struct AllocInfo *next;
|
||||
} AllocInfo;
|
||||
|
||||
typedef struct Allocator
|
||||
{
|
||||
RBTree *tree;
|
||||
RBTree *used_tree;
|
||||
HashTable *hash_table;
|
||||
rawptr buffer;
|
||||
u64 size;
|
||||
@ -93,6 +94,7 @@ typedef struct FLAlloc
|
||||
|
||||
static void GlobalFreeListInit(usize size);
|
||||
static rawptr FLMemAlloc(usize size);
|
||||
static rawptr FLMemAllocZeroed(usize size);
|
||||
static void FLMemFree(rawptr ptr);
|
||||
static void _FreeListInit(FreeList **alloc, usize size);
|
||||
static void FreeListInit(FLAlloc *alloc, usize size);
|
||||
|
||||
89
src/ds.c
89
src/ds.c
@ -3,6 +3,9 @@
|
||||
RBNode RB_NIL = { .color = RB_BLACK };
|
||||
RBNode *P_RB_NIL = &RB_NIL;
|
||||
|
||||
RBDataNode RB_DN_NIL = {0};
|
||||
RBDataNode *P_RB_DN_NIL = &RB_DN_NIL;
|
||||
|
||||
HashNode HT_NIL = {0};
|
||||
HashNode *P_HT_NIL = &HT_NIL;
|
||||
|
||||
@ -16,24 +19,33 @@ static void RBTreeInit(RBTree *tree)
|
||||
{
|
||||
Assert(tree != NULL, "RBTree is null");
|
||||
RB_NIL.right = RB_NIL.left = RB_NIL.parent = P_RB_NIL;
|
||||
RB_DN_NIL.next = P_RB_DN_NIL;
|
||||
|
||||
tree->root = P_RB_NIL;
|
||||
tree->nil = P_RB_NIL;
|
||||
}
|
||||
|
||||
static inline void RBTreeInitNode(RBNode *node, u32 key, rawptr value)
|
||||
static inline void RBTreePushDataNode(RBDataNode *first, RBDataNode *last, rawptr value)
|
||||
{
|
||||
RBDataNode *data_node = FLMemAllocZeroed(sizeof(RBDataNode));
|
||||
data_node->data = value;
|
||||
RBQueuePush(first, last, data_node);
|
||||
}
|
||||
|
||||
static inline RBNode *RBTreeInitNode(u32 key, rawptr value)
|
||||
{
|
||||
RBNode *node = FLMemAllocZeroed(sizeof(RBNode));
|
||||
node->parent = node->left = node->right = P_RB_NIL;
|
||||
node->color = RB_BLACK;
|
||||
node->key = key;
|
||||
node->data = value;
|
||||
|
||||
RBTreePushDataNode(node->bucket.first, node->bucket.last, value);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value)
|
||||
static void RBTreeInsert(RBTree *tree, u32 key, rawptr value)
|
||||
{
|
||||
RBNode *node = FLMemAlloc(sizeof(RBNode));
|
||||
RBTreeInitNode(node, key, value);
|
||||
|
||||
RBNode *existing_node = P_RB_NIL;
|
||||
|
||||
node->left = node->right = tree->nil;
|
||||
@ -52,15 +64,16 @@ static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value)
|
||||
{
|
||||
Assert(curr_node != tree->nil, "Current Node is NIL");
|
||||
|
||||
if (curr_node->key == node->key)
|
||||
if (curr_node->key == key)
|
||||
{
|
||||
existing_node = curr_node;
|
||||
RBTreeInitDataNode(curr_node->bucket.first, curr_node->bucket.last, value);
|
||||
break;
|
||||
}
|
||||
else if (curr_node->key < node->key)
|
||||
else if (curr_node->key < key)
|
||||
{
|
||||
if (curr_node->right == tree->nil)
|
||||
{
|
||||
RBNode *node = RBTreeInitNode(key, value);
|
||||
node->parent = curr_node;
|
||||
curr_node->right = node;
|
||||
break;
|
||||
@ -74,6 +87,7 @@ static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value)
|
||||
{
|
||||
if (curr_node->left == tree->nil)
|
||||
{
|
||||
RBNode *node = RBTreeInitNode(key, value);
|
||||
node->parent = curr_node;
|
||||
curr_node->left = node;
|
||||
break;
|
||||
@ -88,8 +102,6 @@ static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value)
|
||||
|
||||
if (node->parent->color != RB_BLACK && existing_node != P_RB_NIL)
|
||||
RBTreeCorrect(tree, node);
|
||||
|
||||
return existing_node;
|
||||
}
|
||||
|
||||
static void RBTreeCorrect(RBTree *tree, RBNode *node)
|
||||
@ -135,11 +147,33 @@ static void RBTreeCorrect(RBTree *tree, RBNode *node)
|
||||
} while ((p = node->parent));
|
||||
}
|
||||
|
||||
static void RBTreeDelete(RBTree *tree, u32 key)
|
||||
static void RBTreeDelete(RBTree *tree, u32 key, rawptr value)
|
||||
{
|
||||
RBNode *node = NULL;
|
||||
Assert(RBTreeSearch(tree, key, &node), "Unable to find node in RBTreeDelete");
|
||||
|
||||
if (node->bucket.first.data != value)
|
||||
{
|
||||
Assert(node->bucket.first->next != P_RB_DN_NIL, "RBTreeDelete Failure: unable to find value to delete");
|
||||
RBDataNode *data_node = node->bucket.first->next;
|
||||
RBDataNode *prev_node = node->bucket.first;
|
||||
|
||||
while (data_node != P_RB_DN_NIL)
|
||||
{
|
||||
if (data_node->data == value)
|
||||
{
|
||||
prev_node->next = data_node->next;
|
||||
if (data_node == node->bucket.last)
|
||||
node->bucket.last = prev_node;
|
||||
|
||||
FLMemFree(data_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FLMemFree(node->bucket.first);
|
||||
|
||||
if (node == tree->root && node->left == tree->nil && node->right == tree->nil)
|
||||
{
|
||||
tree->root = tree->nil;
|
||||
@ -249,6 +283,7 @@ static void RBTreeDelete(RBTree *tree, u32 key)
|
||||
p->color = RB_BLACK;
|
||||
dn->color = RB_BLACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **out_node)
|
||||
@ -257,20 +292,36 @@ static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **out_node)
|
||||
|
||||
RBNode *node = tree->root;
|
||||
RBNode *nearest = tree->root;
|
||||
u32 nearest_diff = UINT32_MAX;
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
|
||||
if (node->key == key)
|
||||
if (node == tree->nil)
|
||||
break;
|
||||
|
||||
if (node->left == tree->nil && node->right == tree->nil)
|
||||
break;
|
||||
u32 diff = Abs(node->key - key);
|
||||
|
||||
if (node->key < key && node->right != tree->nil)
|
||||
node = node->right;
|
||||
if (diff == 0)
|
||||
{
|
||||
nearest = node;
|
||||
break;
|
||||
}
|
||||
|
||||
if (diff < nearest_diff)
|
||||
{
|
||||
nearest_diff = diff;
|
||||
nearest = node;
|
||||
}
|
||||
|
||||
if (node->key < key)
|
||||
node = node->right;
|
||||
else
|
||||
node = node->left;
|
||||
}
|
||||
|
||||
*out_node = nearest != tree->nil ? nearest : tree->nil;
|
||||
|
||||
return *out_node != tree->nil;
|
||||
}
|
||||
|
||||
static b32 RBTreeSearch(RBTree *tree, u32 key, RBNode **out_node)
|
||||
|
||||
32
src/ds.h
32
src/ds.h
@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
// ::DataStructures::Macros::Header::
|
||||
// ::DataStructures::RedBlackTree::Header::
|
||||
|
||||
#define NodeDir(node) (node == node->parent->left ? RB_LEFT : RB_RIGHT)
|
||||
|
||||
// ::DataStructures::RedBlackTree::Header::
|
||||
#define RBQueuePop(f, l) SLLQueuePop(P_RB_DN_NIL, f, l)
|
||||
#define RBQueuePush(f, l, n) SLLQueuePush(P_RB_DN_NIL, f, l, n)
|
||||
#define RBQueuePushFront(f, l, n) SLLQueuePush(P_RB_DN_NIL, f, l, n)
|
||||
|
||||
typedef enum RBNodeColor_e
|
||||
{
|
||||
@ -18,6 +19,18 @@ typedef enum RBNodeDir_e
|
||||
RB_RIGHT,
|
||||
} RBNodeDir;
|
||||
|
||||
typedef struct RBDataNode
|
||||
{
|
||||
rawptr data;
|
||||
struct RBDataNode *next;
|
||||
} RBDataNode;
|
||||
|
||||
typedef struct RBBucket
|
||||
{
|
||||
RBDataNode *first;
|
||||
RBDataNode *last;
|
||||
} RBBucket;
|
||||
|
||||
typedef struct RBNode
|
||||
{
|
||||
union
|
||||
@ -31,7 +44,7 @@ typedef struct RBNode
|
||||
};
|
||||
struct RBNode *parent;
|
||||
u32 key;
|
||||
rawptr data;
|
||||
RBBucket bucket;
|
||||
RBNodeColor color;
|
||||
} RBNode;
|
||||
|
||||
@ -42,11 +55,12 @@ typedef struct RBTree
|
||||
} RBTree;
|
||||
|
||||
static void RBTreeInit (RBTree *tree);
|
||||
static inline void RBTreeInitNode(RBNode *node, u32 key, rawptr value);
|
||||
static inline RBNode *RBTreeInitNode(u32 key, rawptr value);
|
||||
static inline void RBTreePushDataNode(RBDataNode *first, RBDataNode *last, rawptr value);
|
||||
static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value);
|
||||
static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **node);
|
||||
static b32 RBTreeSearch (RBTree *tree, u32 key, RBNode **node);
|
||||
static void RBTreeDelete (RBTree *tree, u32 key);
|
||||
static void RBTreeDelete (RBTree *tree, u32 key, rawptr value);
|
||||
static void RBTreeLeftRotate (RBTree *tree, RBNode *node);
|
||||
static void RBTreeRightRotate(RBTree *tree, RBNode *node);
|
||||
static void RBTreeRotate (RBTree *tree, RBNode *node, RBNodeDir dir);
|
||||
@ -55,9 +69,9 @@ 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)
|
||||
#define HTQueuePop(f, l) SLLQueuePop(P_HT_NIL, f, l)
|
||||
#define HTQueuePush(f, l, n) SLLQueuePush(P_HT_NIL, f, l, n)
|
||||
#define HTQueuePushFront(f, l, n) SLLQueuePush(P_HT_NIL, f, l, n)
|
||||
|
||||
typedef struct KeyValuePair
|
||||
{
|
||||
|
||||
@ -150,6 +150,8 @@ void MemCpy(rawptr dst, rawptr src, usize len);
|
||||
|
||||
#define Clamp(v, min, max) MathGeneric(Clamp, (v, min, max))
|
||||
|
||||
#define Abs(v) MathGeneric(Abs, (v))
|
||||
|
||||
#define DefMin(T) \
|
||||
T T##Min(T l, T r) \
|
||||
{ \
|
||||
@ -168,6 +170,12 @@ T T##Clamp(T v, T min, T max) \
|
||||
return Min(max, Max(v, min)); \
|
||||
}
|
||||
|
||||
#define DefAbs(T) \
|
||||
T T##Abs(T v) \
|
||||
{ \
|
||||
return v < (T)0 ? -v : v; \
|
||||
}
|
||||
|
||||
// ::Util::Hashing::Functions::Header::
|
||||
|
||||
u64 static inline HashFromString(String8 string);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user