|
|
|
@ -22,6 +22,9 @@ |
|
|
|
* This is not implemented as a class because it will be used in the |
|
|
|
* process of object creation. |
|
|
|
* |
|
|
|
* The data structure is a balanced tree with size as key. |
|
|
|
* Under the size key is a list of elements of the same size. |
|
|
|
* |
|
|
|
* \author Georg Hopp |
|
|
|
* |
|
|
|
* \copyright |
|
|
|
@ -43,87 +46,721 @@ |
|
|
|
|
|
|
|
#define _GNU_SOURCE |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
#include <search.h> |
|
|
|
|
|
|
|
#include "utils/memory.h" |
|
|
|
|
|
|
|
enum rbColor {rbBlack=1, rbRed=2}; |
|
|
|
|
|
|
|
int malloccount = 0; |
|
|
|
|
|
|
|
struct memSegment { |
|
|
|
size_t size; |
|
|
|
void * ptr; |
|
|
|
|
|
|
|
// for address queue |
|
|
|
struct memSegment * next; |
|
|
|
struct memSegment * last; |
|
|
|
|
|
|
|
// for rbtree |
|
|
|
enum rbColor color; |
|
|
|
struct memSegment * parent; |
|
|
|
struct memSegment * left; |
|
|
|
struct memSegment * right; |
|
|
|
}; |
|
|
|
|
|
|
|
struct memSegment * |
|
|
|
newElement(size_t size) |
|
|
|
{ |
|
|
|
struct memSegment * element = malloc(size + sizeof(struct memSegment)); |
|
|
|
malloccount++; |
|
|
|
printf("+"); |
|
|
|
|
|
|
|
element->size = size; |
|
|
|
element->ptr = (void *)element + sizeof(struct memSegment); |
|
|
|
|
|
|
|
element->next = NULL; |
|
|
|
element->last = NULL; |
|
|
|
|
|
|
|
void * segments = NULL; |
|
|
|
element->color = rbRed; |
|
|
|
element->parent = NULL; |
|
|
|
element->left = NULL; |
|
|
|
element->right = NULL; |
|
|
|
|
|
|
|
return element; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* this will interpret any memory segment that is not smaller |
|
|
|
* than the expected size as fitting. |
|
|
|
* |
|
|
|
* @param void * size_ptr a pointer to a size_t value searched for |
|
|
|
* @param void * subject a pointer to the currently analysed tree element |
|
|
|
* find element in tree |
|
|
|
*/ |
|
|
|
static |
|
|
|
int |
|
|
|
segmentFindCmp(const void * size_ptr, const void * subject) |
|
|
|
struct memSegment * |
|
|
|
findElement(struct memSegment * tree, size_t size) |
|
|
|
{ |
|
|
|
if (*(size_t *)size_ptr > ((struct memSegment *)subject)->size) |
|
|
|
return 1; |
|
|
|
struct memSegment * fitting = NULL; |
|
|
|
|
|
|
|
while (NULL != tree) { |
|
|
|
if (tree->size == size) { |
|
|
|
fitting = tree; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
if (size > tree->size) { |
|
|
|
tree = tree->right; |
|
|
|
} else { |
|
|
|
fitting = tree; |
|
|
|
tree = tree->left; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return fitting; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* function to get specific elements needed for |
|
|
|
* rb handling, grandparent, uncle and sibbling |
|
|
|
*/ |
|
|
|
struct memSegment * |
|
|
|
grandparent(struct memSegment * node) |
|
|
|
{ |
|
|
|
if (NULL != node && NULL != node->parent) { |
|
|
|
return node->parent->parent; |
|
|
|
} |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
struct memSegment * |
|
|
|
uncle(struct memSegment * node) |
|
|
|
{ |
|
|
|
struct memSegment * gp = grandparent(node); |
|
|
|
|
|
|
|
if (NULL == gp) { |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (node->parent == gp->left) { |
|
|
|
return gp->right; |
|
|
|
} |
|
|
|
|
|
|
|
return gp->left; |
|
|
|
} |
|
|
|
|
|
|
|
struct memSegment * |
|
|
|
sibling(struct memSegment * node) |
|
|
|
{ |
|
|
|
if (NULL == node) { |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (NULL == node->parent->left || node == node->parent->left) { |
|
|
|
return node->parent->right; |
|
|
|
} else { |
|
|
|
return node->parent->left; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* tree modifications...needed for rb handling. |
|
|
|
*/ |
|
|
|
void |
|
|
|
rotateLeft(struct memSegment ** tree, struct memSegment * node) |
|
|
|
{ |
|
|
|
struct memSegment * rightChild = node->right; |
|
|
|
struct memSegment * rcLeftSub = node->right->left; |
|
|
|
|
|
|
|
rightChild->left = node; |
|
|
|
rightChild->parent = node->parent; |
|
|
|
node->right = rcLeftSub; |
|
|
|
if (NULL != rcLeftSub) { |
|
|
|
rcLeftSub->parent = node; |
|
|
|
} |
|
|
|
|
|
|
|
if (node->parent) { |
|
|
|
if (node->parent->left == node) { |
|
|
|
node->parent->left = rightChild; |
|
|
|
} else { |
|
|
|
node->parent->right = rightChild; |
|
|
|
} |
|
|
|
} else { |
|
|
|
*tree = rightChild; |
|
|
|
} |
|
|
|
|
|
|
|
node->parent = rightChild; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
rotateRight(struct memSegment ** tree, struct memSegment * node) |
|
|
|
{ |
|
|
|
struct memSegment * leftChild = node->left; |
|
|
|
struct memSegment * lcRightSub = node->left->right; |
|
|
|
|
|
|
|
leftChild->right = node; |
|
|
|
leftChild->parent = node->parent; |
|
|
|
node->left = lcRightSub; |
|
|
|
if (NULL != lcRightSub) { |
|
|
|
lcRightSub->parent = node; |
|
|
|
} |
|
|
|
|
|
|
|
if (node->parent) { |
|
|
|
if (node->parent->left == node) { |
|
|
|
node->parent->left = leftChild; |
|
|
|
} else { |
|
|
|
node->parent->right = leftChild; |
|
|
|
} |
|
|
|
} else { |
|
|
|
*tree = leftChild; |
|
|
|
} |
|
|
|
|
|
|
|
node->parent = leftChild; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
replaceNode( |
|
|
|
struct memSegment ** tree, |
|
|
|
struct memSegment * node1, |
|
|
|
struct memSegment * node2) |
|
|
|
{ |
|
|
|
if (NULL != node1->parent) { |
|
|
|
if (node1 == node1->parent->left) { |
|
|
|
node1->parent->left = node2; |
|
|
|
} else { |
|
|
|
node1->parent->right = node2; |
|
|
|
} |
|
|
|
} else { |
|
|
|
*tree = node2; |
|
|
|
} |
|
|
|
|
|
|
|
if (NULL != node2) { |
|
|
|
node2->parent = node1->parent; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* this returns exact fits....uhh.....I can't relate solely on |
|
|
|
* the size argument as then same sized segments will never |
|
|
|
* be stored. |
|
|
|
* Maybe a tree is not the best data structure to use to store |
|
|
|
* these. |
|
|
|
* Anyway, right now take the ptr into account if size if equal. |
|
|
|
* insert element in tree |
|
|
|
*/ |
|
|
|
static |
|
|
|
int |
|
|
|
segmentSearchCmp(const void * search, const void * subject) |
|
|
|
struct memSegment * |
|
|
|
insertElement(struct memSegment ** tree, struct memSegment * element) |
|
|
|
{ |
|
|
|
size_t idx = |
|
|
|
((struct memSegment *)search)->size - |
|
|
|
((struct memSegment *)subject)->size; |
|
|
|
struct memSegment * node = *tree; |
|
|
|
struct memSegment * new_node = NULL; |
|
|
|
struct memSegment * u; |
|
|
|
struct memSegment * g; |
|
|
|
|
|
|
|
if (0 == idx) { |
|
|
|
return |
|
|
|
((struct memSegment *)search)->ptr - |
|
|
|
((struct memSegment *)subject)->ptr; |
|
|
|
} |
|
|
|
element->color = rbRed; |
|
|
|
element->parent = NULL; |
|
|
|
element->left = NULL; |
|
|
|
element->right = NULL; |
|
|
|
element->next = NULL; |
|
|
|
element->last = NULL; |
|
|
|
|
|
|
|
// if tree is empty it's simple... :) |
|
|
|
if (NULL == node) { |
|
|
|
*tree = node = new_node = element; |
|
|
|
} else { |
|
|
|
// normal binary tree add.... |
|
|
|
while (element->size != node->size) { |
|
|
|
if (element->size < node->size) { |
|
|
|
if (NULL == node->left) { |
|
|
|
node->left = element; |
|
|
|
node->left->parent = node; |
|
|
|
new_node = node = node->left; |
|
|
|
break; |
|
|
|
} else { |
|
|
|
node = node->left; |
|
|
|
} |
|
|
|
} else if (element->size > node->size) { |
|
|
|
if (NULL == node->right) { |
|
|
|
node->right = element; |
|
|
|
node->right->parent = node; |
|
|
|
new_node = node = node->right; |
|
|
|
break; |
|
|
|
} else { |
|
|
|
node = node->right; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (NULL == node->next) { |
|
|
|
node->next = node->last = element; |
|
|
|
} else { |
|
|
|
node->last->next = element; |
|
|
|
node->last = element; |
|
|
|
} |
|
|
|
return element; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (NULL != new_node) { |
|
|
|
/* |
|
|
|
* handle reballancing rb style |
|
|
|
*/ |
|
|
|
while (1) { |
|
|
|
// case 1 |
|
|
|
if (node->parent == NULL) { |
|
|
|
node->color = rbBlack; |
|
|
|
// we're done.... :) |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
// case 2 |
|
|
|
if (node->parent->color == rbBlack) { |
|
|
|
// Tree is still valid ... wow, again we're done... :) |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
// case 3 |
|
|
|
u = uncle(node); |
|
|
|
g = grandparent(node); |
|
|
|
|
|
|
|
if (u != NULL && u->color == rbRed) { |
|
|
|
node->parent->color = rbBlack; |
|
|
|
u->color = rbBlack; |
|
|
|
g->color = rbRed; |
|
|
|
|
|
|
|
node = g; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// case 4 |
|
|
|
if (node == node->parent->right && node->parent == g->left) { |
|
|
|
rotateLeft(tree, node->parent); |
|
|
|
node = node->left; |
|
|
|
} else if (node == node->parent->left && node->parent == g->right) { |
|
|
|
|
|
|
|
rotateRight(tree, node->parent); |
|
|
|
node = node->right; |
|
|
|
} |
|
|
|
|
|
|
|
// case 5 |
|
|
|
g = grandparent(node); |
|
|
|
|
|
|
|
node->parent->color = rbBlack; |
|
|
|
g->color = rbRed; |
|
|
|
|
|
|
|
if (node == node->parent->left) { |
|
|
|
rotateRight(tree, g); |
|
|
|
} else { |
|
|
|
rotateLeft(tree, g); |
|
|
|
} |
|
|
|
|
|
|
|
// we're done.. |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return new_node; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* delete element from tree |
|
|
|
* here multiple functions are involved.... |
|
|
|
* ======================================================================= |
|
|
|
*/ |
|
|
|
/** |
|
|
|
* find minimum of the right subtree aka leftmost leaf of right subtree |
|
|
|
* aka left in-order successor. |
|
|
|
* We return the parent of the element in the out argument parent. |
|
|
|
* This can be NULL wenn calling. |
|
|
|
*/ |
|
|
|
struct memSegment * |
|
|
|
findInOrderSuccessor(struct memSegment * tree) |
|
|
|
{ |
|
|
|
struct memSegment * node = tree->right; |
|
|
|
|
|
|
|
while (NULL != node->left) { |
|
|
|
node = node->left; |
|
|
|
} |
|
|
|
|
|
|
|
return idx; |
|
|
|
return node; |
|
|
|
} |
|
|
|
|
|
|
|
struct memSegment * deleteOneChild(struct memSegment **, struct memSegment *); |
|
|
|
|
|
|
|
struct memSegment * |
|
|
|
deleteElement(struct memSegment ** tree, struct memSegment * element) |
|
|
|
{ |
|
|
|
struct memSegment * node = *tree; |
|
|
|
struct memSegment * del_node; |
|
|
|
struct memSegment * child; |
|
|
|
struct memSegment * s; |
|
|
|
|
|
|
|
// find the relevant node and it's parent |
|
|
|
while (NULL != node) { |
|
|
|
if (element->size < node->size) { |
|
|
|
node = node->left; |
|
|
|
} else if (element->size > node->size) { |
|
|
|
node = node->right; |
|
|
|
} else { |
|
|
|
// we know we found our tree element. |
|
|
|
if (NULL != node->next) { |
|
|
|
// last element. |
|
|
|
if (NULL != node->parent) { |
|
|
|
if (node->parent->left == node->parent) { |
|
|
|
node->parent->left = node->next; |
|
|
|
} else { |
|
|
|
node->parent->right = node->next; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (NULL != node->left) { |
|
|
|
node->left->parent = node->next; |
|
|
|
} |
|
|
|
|
|
|
|
if (NULL != node->right) { |
|
|
|
node->right->parent = node->next; |
|
|
|
} |
|
|
|
|
|
|
|
if (node->next == node->last) { |
|
|
|
node->next->next = NULL; |
|
|
|
node->next->last = NULL; |
|
|
|
} else { |
|
|
|
node->next->last = node->last; |
|
|
|
} |
|
|
|
|
|
|
|
node->next->parent = node->parent; |
|
|
|
node->next->color = node->color; |
|
|
|
node->next->left = node->left; |
|
|
|
node->next->right = node->right; |
|
|
|
|
|
|
|
return node; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// element not found |
|
|
|
if (NULL == node) { |
|
|
|
return node; |
|
|
|
} |
|
|
|
|
|
|
|
del_node = node; |
|
|
|
|
|
|
|
// now our cases follows...the first one is the same as with |
|
|
|
// simple binary search trees. Two non null children. |
|
|
|
|
|
|
|
// case 1: two children |
|
|
|
if (NULL != node->left && NULL != node->right) { |
|
|
|
struct memSegment * successor = findInOrderSuccessor(node); |
|
|
|
|
|
|
|
// this is a replacement code for simply change value and remove |
|
|
|
// successor...I can not do this here because the address of |
|
|
|
// the object is part of the information that has to be |
|
|
|
// preserved. |
|
|
|
enum rbColor tmpcolor = successor->color; |
|
|
|
struct memSegment * tmpparent = successor->parent; |
|
|
|
struct memSegment * tmpleft = successor->left; |
|
|
|
struct memSegment * tmpright = successor->right; |
|
|
|
|
|
|
|
replaceNode(tree, node, successor); |
|
|
|
|
|
|
|
successor->color = node->color; |
|
|
|
successor->left = node->left; |
|
|
|
successor->left->parent = successor; |
|
|
|
// the right one might be successor... |
|
|
|
if (node->right == successor) { |
|
|
|
successor->right = node; |
|
|
|
node->parent = successor; |
|
|
|
} else { |
|
|
|
successor->right = node->right; |
|
|
|
node->right->parent = successor; |
|
|
|
node->parent = tmpparent; |
|
|
|
tmpparent->left = node; |
|
|
|
} |
|
|
|
|
|
|
|
node->color = tmpcolor; |
|
|
|
node->left = tmpleft; |
|
|
|
node->right = tmpright; |
|
|
|
} |
|
|
|
|
|
|
|
// Precondition: n has at most one non-null child. |
|
|
|
child = (NULL == node->right) ? node->left : node->right; |
|
|
|
replaceNode(tree, node, child); |
|
|
|
|
|
|
|
// delete one child case |
|
|
|
// TODO this is overly complex as simply derived from the function... |
|
|
|
// maybe this can be simplified. Maybe not...check. |
|
|
|
if (node->color == rbBlack) { |
|
|
|
if (NULL != child && child->color == rbRed) { |
|
|
|
child->color = rbBlack; |
|
|
|
// done despite modifying tree itself if neccessary.. |
|
|
|
return del_node; |
|
|
|
} else { |
|
|
|
if (NULL != child) { |
|
|
|
node = child; |
|
|
|
} else { |
|
|
|
node->color = rbBlack; |
|
|
|
node->left = NULL; |
|
|
|
node->right = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
return del_node; |
|
|
|
} |
|
|
|
|
|
|
|
// delete and rb rebalance... |
|
|
|
while(1) { |
|
|
|
// case 1 |
|
|
|
if (NULL == node->parent) { |
|
|
|
// done again |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
// case 2 |
|
|
|
s = sibling(node); |
|
|
|
|
|
|
|
if (NULL != s && s->color == rbRed) { |
|
|
|
node->parent->color = rbRed; |
|
|
|
s->color = rbBlack; |
|
|
|
|
|
|
|
/* |
|
|
|
* detect which child we are...assumption |
|
|
|
* if we are not parent->right and parent->right is not |
|
|
|
* null we must be left, even if its set to NULL previously |
|
|
|
*/ |
|
|
|
if (NULL != node->parent->right && node != node->parent->right) { |
|
|
|
rotateLeft(tree, node->parent); |
|
|
|
} else { |
|
|
|
rotateRight(tree, node->parent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
s = sibling(node); |
|
|
|
// case 3 / 4 |
|
|
|
if (NULL == s || ((s->color == rbBlack) && |
|
|
|
(NULL == s->left || s->left->color == rbBlack) && |
|
|
|
(NULL == s->right || s->right->color == rbBlack))) { |
|
|
|
|
|
|
|
if (NULL != s) { |
|
|
|
s->color = rbRed; |
|
|
|
} |
|
|
|
|
|
|
|
if (node->parent->color == rbBlack) { |
|
|
|
// case 3 |
|
|
|
node = node->parent; |
|
|
|
continue; |
|
|
|
} else { |
|
|
|
// case 4 |
|
|
|
node->parent->color = rbBlack; |
|
|
|
// and done again... |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// case 5 |
|
|
|
if (NULL != s && s->color == rbBlack) { |
|
|
|
// this if statement is trivial, |
|
|
|
// due to case 2 (even though case 2 changed the sibling to a |
|
|
|
// sibling's child, |
|
|
|
// the sibling's child can't be red, since no red parent can |
|
|
|
// have a red child). |
|
|
|
// |
|
|
|
// the following statements just force the red to be on the |
|
|
|
// left of the left of the parent, |
|
|
|
// or right of the right, so case 6 will rotate correctly. |
|
|
|
if ((node == node->parent->left) && |
|
|
|
(NULL == s->right || s->right->color == rbBlack) && |
|
|
|
(NULL != s->left && s->left->color == rbRed)) { |
|
|
|
|
|
|
|
// this last test is trivial too due to cases 2-4. |
|
|
|
s->color = rbRed; |
|
|
|
s->left->color = rbBlack; |
|
|
|
|
|
|
|
rotateRight(tree, s); |
|
|
|
} else if ((node == node->parent->right) && |
|
|
|
(NULL == s->left || s->left->color == rbBlack) && |
|
|
|
(NULL != s->right && s->right->color == rbRed)) { |
|
|
|
// this last test is trivial too due to cases 2-4. |
|
|
|
s->color = rbRed; |
|
|
|
s->right->color = rbBlack; |
|
|
|
|
|
|
|
rotateLeft(tree, s); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
s = sibling(node); |
|
|
|
// case 6 |
|
|
|
if (NULL != s) { |
|
|
|
s->color = node->parent->color; |
|
|
|
} |
|
|
|
|
|
|
|
if (NULL != node && NULL != node->parent) { |
|
|
|
node->parent->color = rbBlack; |
|
|
|
|
|
|
|
/* |
|
|
|
* detect which child we are...assumption |
|
|
|
* if we are not parent->right and parent->right is not |
|
|
|
* null we must be left, even if its set to NULL previously |
|
|
|
*/ |
|
|
|
if (NULL != node->parent->right && node != node->parent->right) { |
|
|
|
if (NULL != s->right) { |
|
|
|
s->right->color = rbBlack; |
|
|
|
} |
|
|
|
rotateLeft(tree, node->parent); |
|
|
|
} else { |
|
|
|
if (NULL != s->left) { |
|
|
|
s->left->color = rbBlack; |
|
|
|
} |
|
|
|
rotateRight(tree, node->parent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// done... |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
//deleteOneChild(tree, node); |
|
|
|
|
|
|
|
return del_node; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
traverse(struct memSegment * tree, void (*cb)(struct memSegment *, int)) |
|
|
|
{ |
|
|
|
struct memSegment * previous = tree; |
|
|
|
struct memSegment * node = tree; |
|
|
|
int depth = 1; |
|
|
|
|
|
|
|
/* |
|
|
|
* I think this has something like O(n+log(n)) on a ballanced |
|
|
|
* tree because I have to traverse back the rightmost leaf to |
|
|
|
* the root to get a break condition. |
|
|
|
*/ |
|
|
|
while (NULL != node) { |
|
|
|
/* |
|
|
|
* If we come from the right so nothing and go to our |
|
|
|
* next parent. |
|
|
|
*/ |
|
|
|
if (previous == node->right) { |
|
|
|
previous = node; |
|
|
|
node = node->parent; |
|
|
|
depth--; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if ((NULL == node->left || previous == node->left)) { |
|
|
|
/* |
|
|
|
* If there are no more elements to the left or we |
|
|
|
* came from the left, process data. |
|
|
|
*/ |
|
|
|
cb(node, depth); |
|
|
|
previous = node; |
|
|
|
|
|
|
|
if (NULL != node->right) { |
|
|
|
node = node->right; |
|
|
|
depth++; |
|
|
|
} else { |
|
|
|
node = node->parent; |
|
|
|
depth--; |
|
|
|
} |
|
|
|
} else { |
|
|
|
/* |
|
|
|
* if there are more elements to the left go there. |
|
|
|
*/ |
|
|
|
previous = node; |
|
|
|
node = node->left; |
|
|
|
depth++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void printElement(struct memSegment * node, int depth) |
|
|
|
{ |
|
|
|
int i; |
|
|
|
|
|
|
|
printf("%s %010zu:0x%p(%02d)", |
|
|
|
(node->color==rbRed)?"R":"B", |
|
|
|
node->size, |
|
|
|
node->ptr, |
|
|
|
depth); |
|
|
|
|
|
|
|
for (i=0; i<depth; i++) printf("-"); |
|
|
|
puts(""); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct memSegment * segments = NULL; |
|
|
|
|
|
|
|
// /** |
|
|
|
// * this will interpret any memory segment that is not smaller |
|
|
|
// * than the expected size as fitting. |
|
|
|
// * |
|
|
|
// * @param void * size_ptr a pointer to a size_t value searched for |
|
|
|
// * @param void * subject a pointer to the currently analysed tree element |
|
|
|
// */ |
|
|
|
// static |
|
|
|
// int |
|
|
|
// segmentFindCmp(const void * size_ptr, const void * subject) |
|
|
|
// { |
|
|
|
// if (*(size_t *)size_ptr > ((struct memSegment *)subject)->size) |
|
|
|
// return 1; |
|
|
|
// |
|
|
|
// return 0; |
|
|
|
// } |
|
|
|
// |
|
|
|
// /** |
|
|
|
// * this returns exact fits....uhh.....I can't relate solely on |
|
|
|
// * the size argument as then same sized segments will never |
|
|
|
// * be stored. |
|
|
|
// * Maybe a tree is not the best data structure to use to store |
|
|
|
// * these. |
|
|
|
// * Anyway, right now take the ptr into account if size if equal. |
|
|
|
// */ |
|
|
|
// static |
|
|
|
// int |
|
|
|
// segmentSearchCmp(const void * search, const void * subject) |
|
|
|
// { |
|
|
|
// size_t idx = |
|
|
|
// ((struct memSegment *)search)->size - |
|
|
|
// ((struct memSegment *)subject)->size; |
|
|
|
// |
|
|
|
// if (0 == idx) { |
|
|
|
// return |
|
|
|
// ((struct memSegment *)search)->ptr - |
|
|
|
// ((struct memSegment *)subject)->ptr; |
|
|
|
// } |
|
|
|
// |
|
|
|
// return idx; |
|
|
|
// } |
|
|
|
|
|
|
|
static |
|
|
|
void |
|
|
|
segmentFree(void * segment) |
|
|
|
segmentFree(struct memSegment * segment, int depth) |
|
|
|
{ |
|
|
|
free(segment); |
|
|
|
while (NULL != segment) { |
|
|
|
struct memSegment * next = segment->next; |
|
|
|
free(segment); |
|
|
|
malloccount--; |
|
|
|
printf("-"); |
|
|
|
segment = next; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void * |
|
|
|
memMalloc(size_t size) |
|
|
|
{ |
|
|
|
struct memSegment ** seg_ptr = tfind(&size, &segments, segmentFindCmp); |
|
|
|
struct memSegment * seg; |
|
|
|
struct memSegment * seg; |
|
|
|
|
|
|
|
//printf("MALLOC of size: %zu\n", size); |
|
|
|
//traverse(segments, printElement); |
|
|
|
|
|
|
|
if (NULL == seg_ptr) { |
|
|
|
seg = (struct memSegment *)malloc(sizeof(struct memSegment) + size); |
|
|
|
seg = findElement(segments, size); |
|
|
|
|
|
|
|
seg->size = size; |
|
|
|
seg->ptr = (void *)seg + sizeof(struct memSegment); |
|
|
|
if (NULL == seg) { |
|
|
|
seg = newElement(size); |
|
|
|
//printf(" CREATE Segment: 0x%p of size: %zu\n", seg, seg->size); |
|
|
|
} else { |
|
|
|
seg = *seg_ptr; |
|
|
|
//printf(" FOUND Segment: 0x%p of size: %zu\n", seg, seg->size); |
|
|
|
// remove the found one from the tree as we use it now. |
|
|
|
tdelete((void *)seg, &segments, segmentSearchCmp); |
|
|
|
deleteElement(&segments, seg); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return seg->ptr; |
|
|
|
} |
|
|
|
|
|
|
|
@ -150,15 +787,39 @@ void |
|
|
|
memFree(void ** mem) |
|
|
|
{ |
|
|
|
if (NULL != *mem) { |
|
|
|
tsearch(*mem - sizeof(struct memSegment), &segments, segmentSearchCmp); |
|
|
|
insertElement(&segments, (struct memSegment *)(*mem - sizeof(struct memSegment))); |
|
|
|
|
|
|
|
//printf("FREE of Segment: 0x%p of size: %zu\n", |
|
|
|
// *mem - sizeof(struct memSegment), |
|
|
|
// ((struct memSegment *)(*mem - sizeof(struct memSegment)))->size); |
|
|
|
//traverse(segments, printElement); |
|
|
|
|
|
|
|
*mem = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
pre_order(struct memSegment * tree, void (*cb)(struct memSegment *, int)) |
|
|
|
{ |
|
|
|
if (NULL != tree) { |
|
|
|
if (NULL != tree->left) { |
|
|
|
pre_order(tree->left, cb); |
|
|
|
} |
|
|
|
|
|
|
|
if (NULL != tree->right) { |
|
|
|
pre_order(tree->right, cb); |
|
|
|
} |
|
|
|
|
|
|
|
cb(tree, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
memCleanup() |
|
|
|
{ |
|
|
|
tdestroy(segments, segmentFree); |
|
|
|
printf("\n"); |
|
|
|
pre_order(segments, segmentFree); |
|
|
|
printf("\nmalloccount: %d\n", malloccount); |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
|