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)
|
if (alignment < 8)
|
||||||
alignment = 8;
|
alignment = 8;
|
||||||
|
|
||||||
RBNode *node = NULL;
|
RBNode *node = P_RB_NIL;
|
||||||
RBTreeSearch(ALLOC.tree, size, &node);
|
rawptr mem = NULL;
|
||||||
|
if (!RBTreeSearchNearest(ALLOC.tree, size, &node))
|
||||||
|
{
|
||||||
|
AllocGrow(size);
|
||||||
|
RBTreeSearchNearest(ALLOC.tree, size, &node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Free(rawptr ptr)
|
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;
|
usize grow_size = size < ALLOC.grow_size ? ALLOC.grow_size : ALLOC.grow_size + size;
|
||||||
MemRealloc(ALLOC.buffer, ALLOC.size, ALLOC.size + grow_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.size += grow_size;
|
||||||
ALLOC.free_size += grow_size;
|
ALLOC.free_size += grow_size;
|
||||||
}
|
}
|
||||||
@ -211,6 +222,13 @@ static rawptr FLMemAlloc(usize size)
|
|||||||
return FreeListAlloc(&FL_ALLOC, 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)
|
static void FLMemFree(rawptr ptr)
|
||||||
{
|
{
|
||||||
FreeListFree(&FL_ALLOC, ptr);
|
FreeListFree(&FL_ALLOC, ptr);
|
||||||
|
|||||||
@ -34,13 +34,14 @@ static Arena *ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no);
|
|||||||
|
|
||||||
typedef struct AllocInfo
|
typedef struct AllocInfo
|
||||||
{
|
{
|
||||||
rawptr *ptrs;
|
rawptr ptr;
|
||||||
u32 count;
|
struct AllocInfo *next;
|
||||||
} AllocInfo;
|
} AllocInfo;
|
||||||
|
|
||||||
typedef struct Allocator
|
typedef struct Allocator
|
||||||
{
|
{
|
||||||
RBTree *tree;
|
RBTree *tree;
|
||||||
|
RBTree *used_tree;
|
||||||
HashTable *hash_table;
|
HashTable *hash_table;
|
||||||
rawptr buffer;
|
rawptr buffer;
|
||||||
u64 size;
|
u64 size;
|
||||||
@ -93,6 +94,7 @@ typedef struct FLAlloc
|
|||||||
|
|
||||||
static void GlobalFreeListInit(usize size);
|
static void GlobalFreeListInit(usize size);
|
||||||
static rawptr FLMemAlloc(usize size);
|
static rawptr FLMemAlloc(usize size);
|
||||||
|
static rawptr FLMemAllocZeroed(usize size);
|
||||||
static void FLMemFree(rawptr ptr);
|
static void FLMemFree(rawptr ptr);
|
||||||
static void _FreeListInit(FreeList **alloc, usize size);
|
static void _FreeListInit(FreeList **alloc, usize size);
|
||||||
static void FreeListInit(FLAlloc *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 RB_NIL = { .color = RB_BLACK };
|
||||||
RBNode *P_RB_NIL = &RB_NIL;
|
RBNode *P_RB_NIL = &RB_NIL;
|
||||||
|
|
||||||
|
RBDataNode RB_DN_NIL = {0};
|
||||||
|
RBDataNode *P_RB_DN_NIL = &RB_DN_NIL;
|
||||||
|
|
||||||
HashNode HT_NIL = {0};
|
HashNode HT_NIL = {0};
|
||||||
HashNode *P_HT_NIL = &HT_NIL;
|
HashNode *P_HT_NIL = &HT_NIL;
|
||||||
|
|
||||||
@ -16,24 +19,33 @@ static void RBTreeInit(RBTree *tree)
|
|||||||
{
|
{
|
||||||
Assert(tree != NULL, "RBTree is null");
|
Assert(tree != NULL, "RBTree is null");
|
||||||
RB_NIL.right = RB_NIL.left = RB_NIL.parent = P_RB_NIL;
|
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->root = P_RB_NIL;
|
||||||
tree->nil = 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->parent = node->left = node->right = P_RB_NIL;
|
||||||
node->color = RB_BLACK;
|
node->color = RB_BLACK;
|
||||||
node->key = key;
|
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;
|
RBNode *existing_node = P_RB_NIL;
|
||||||
|
|
||||||
node->left = node->right = tree->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");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
else if (curr_node->key < node->key)
|
else if (curr_node->key < key)
|
||||||
{
|
{
|
||||||
if (curr_node->right == tree->nil)
|
if (curr_node->right == tree->nil)
|
||||||
{
|
{
|
||||||
|
RBNode *node = RBTreeInitNode(key, value);
|
||||||
node->parent = curr_node;
|
node->parent = curr_node;
|
||||||
curr_node->right = node;
|
curr_node->right = node;
|
||||||
break;
|
break;
|
||||||
@ -74,6 +87,7 @@ static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value)
|
|||||||
{
|
{
|
||||||
if (curr_node->left == tree->nil)
|
if (curr_node->left == tree->nil)
|
||||||
{
|
{
|
||||||
|
RBNode *node = RBTreeInitNode(key, value);
|
||||||
node->parent = curr_node;
|
node->parent = curr_node;
|
||||||
curr_node->left = node;
|
curr_node->left = node;
|
||||||
break;
|
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)
|
if (node->parent->color != RB_BLACK && existing_node != P_RB_NIL)
|
||||||
RBTreeCorrect(tree, node);
|
RBTreeCorrect(tree, node);
|
||||||
|
|
||||||
return existing_node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RBTreeCorrect(RBTree *tree, RBNode *node)
|
static void RBTreeCorrect(RBTree *tree, RBNode *node)
|
||||||
@ -135,11 +147,33 @@ static void RBTreeCorrect(RBTree *tree, RBNode *node)
|
|||||||
} while ((p = node->parent));
|
} while ((p = node->parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RBTreeDelete(RBTree *tree, u32 key)
|
static void RBTreeDelete(RBTree *tree, u32 key, rawptr value)
|
||||||
{
|
{
|
||||||
RBNode *node = NULL;
|
RBNode *node = NULL;
|
||||||
Assert(RBTreeSearch(tree, key, &node), "Unable to find node in RBTreeDelete");
|
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)
|
if (node == tree->root && node->left == tree->nil && node->right == tree->nil)
|
||||||
{
|
{
|
||||||
tree->root = tree->nil;
|
tree->root = tree->nil;
|
||||||
@ -250,6 +284,7 @@ static void RBTreeDelete(RBTree *tree, u32 key)
|
|||||||
dn->color = RB_BLACK;
|
dn->color = RB_BLACK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **out_node)
|
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 *node = tree->root;
|
||||||
RBNode *nearest = tree->root;
|
RBNode *nearest = tree->root;
|
||||||
|
u32 nearest_diff = UINT32_MAX;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
if (node == tree->nil)
|
||||||
|
|
||||||
if (node->key == key)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (node->left == tree->nil && node->right == tree->nil)
|
u32 diff = Abs(node->key - key);
|
||||||
break;
|
|
||||||
|
|
||||||
if (node->key < key && node->right != tree->nil)
|
if (diff == 0)
|
||||||
node = node->right;
|
{
|
||||||
|
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)
|
static b32 RBTreeSearch(RBTree *tree, u32 key, RBNode **out_node)
|
||||||
|
|||||||
32
src/ds.h
32
src/ds.h
@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// ::DataStructures::Macros::Header::
|
// ::DataStructures::RedBlackTree::Header::
|
||||||
|
|
||||||
#define NodeDir(node) (node == node->parent->left ? RB_LEFT : RB_RIGHT)
|
#define NodeDir(node) (node == node->parent->left ? RB_LEFT : RB_RIGHT)
|
||||||
|
#define RBQueuePop(f, l) SLLQueuePop(P_RB_DN_NIL, f, l)
|
||||||
// ::DataStructures::RedBlackTree::Header::
|
#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
|
typedef enum RBNodeColor_e
|
||||||
{
|
{
|
||||||
@ -18,6 +19,18 @@ typedef enum RBNodeDir_e
|
|||||||
RB_RIGHT,
|
RB_RIGHT,
|
||||||
} RBNodeDir;
|
} RBNodeDir;
|
||||||
|
|
||||||
|
typedef struct RBDataNode
|
||||||
|
{
|
||||||
|
rawptr data;
|
||||||
|
struct RBDataNode *next;
|
||||||
|
} RBDataNode;
|
||||||
|
|
||||||
|
typedef struct RBBucket
|
||||||
|
{
|
||||||
|
RBDataNode *first;
|
||||||
|
RBDataNode *last;
|
||||||
|
} RBBucket;
|
||||||
|
|
||||||
typedef struct RBNode
|
typedef struct RBNode
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
@ -31,7 +44,7 @@ typedef struct RBNode
|
|||||||
};
|
};
|
||||||
struct RBNode *parent;
|
struct RBNode *parent;
|
||||||
u32 key;
|
u32 key;
|
||||||
rawptr data;
|
RBBucket bucket;
|
||||||
RBNodeColor color;
|
RBNodeColor color;
|
||||||
} RBNode;
|
} RBNode;
|
||||||
|
|
||||||
@ -42,11 +55,12 @@ typedef struct RBTree
|
|||||||
} RBTree;
|
} RBTree;
|
||||||
|
|
||||||
static void RBTreeInit (RBTree *tree);
|
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 RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value);
|
||||||
static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **node);
|
static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **node);
|
||||||
static b32 RBTreeSearch (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 RBTreeLeftRotate (RBTree *tree, RBNode *node);
|
||||||
static void RBTreeRightRotate(RBTree *tree, RBNode *node);
|
static void RBTreeRightRotate(RBTree *tree, RBNode *node);
|
||||||
static void RBTreeRotate (RBTree *tree, RBNode *node, RBNodeDir dir);
|
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::
|
// ::DataStructures::HashTable::Functions::Header::
|
||||||
|
|
||||||
#define HTQueuePop(f, l) SLLQueuePop(&HT_NIL, f, l)
|
#define HTQueuePop(f, l) SLLQueuePop(P_HT_NIL, f, l)
|
||||||
#define HTQueuePush(f, l, n) SLLQueuePush(&HT_NIL, f, l, n)
|
#define HTQueuePush(f, l, n) SLLQueuePush(P_HT_NIL, f, l, n)
|
||||||
#define HTQueuePushFront(f, l, n) SLLQueuePush(&HT_NIL, f, l, n)
|
#define HTQueuePushFront(f, l, n) SLLQueuePush(P_HT_NIL, f, l, n)
|
||||||
|
|
||||||
typedef struct KeyValuePair
|
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 Clamp(v, min, max) MathGeneric(Clamp, (v, min, max))
|
||||||
|
|
||||||
|
#define Abs(v) MathGeneric(Abs, (v))
|
||||||
|
|
||||||
#define DefMin(T) \
|
#define DefMin(T) \
|
||||||
T T##Min(T l, T r) \
|
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)); \
|
return Min(max, Max(v, min)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DefAbs(T) \
|
||||||
|
T T##Abs(T v) \
|
||||||
|
{ \
|
||||||
|
return v < (T)0 ? -v : v; \
|
||||||
|
}
|
||||||
|
|
||||||
// ::Util::Hashing::Functions::Header::
|
// ::Util::Hashing::Functions::Header::
|
||||||
|
|
||||||
u64 static inline HashFromString(String8 string);
|
u64 static inline HashFromString(String8 string);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user