diff --git a/qpkg/Makefile b/qpkg/Makefile index 78932c0..5a20d33 100644 --- a/qpkg/Makefile +++ b/qpkg/Makefile @@ -2,7 +2,7 @@ CFLAGS = -Wall -Wshadow -Wmissing-prototypes -g -O # -O, so that we get data flow analysis, which helps to find more bugs #LDFLAGS=-pg -OBJS = gobble.o id.o prereq.o qpkg.o +OBJS = gobble.o id.o prereq.o qpkg.o jrb.o OBJS_rbtest = rbtest.o jrb.o all: qpkg rbtest diff --git a/qpkg/TODO b/qpkg/TODO index 8fc24e2..1a6e33f 100644 --- a/qpkg/TODO +++ b/qpkg/TODO @@ -8,6 +8,10 @@ So the tree is clearly degenerated. + Update: after switching to red-black trees, we get only 1497604 calls + to comp_id. This is 130% of the "good case" estimate above. Insertion + of a new node is currently done with two lookup, so we'll get rid of + some more lookups after further optimization. - check whether introducing a new package would cause a conflict diff --git a/qpkg/id.c b/qpkg/id.c index 54a6cc3..e625805 100644 --- a/qpkg/id.c +++ b/qpkg/id.c @@ -4,9 +4,6 @@ #include "id.h" -#define NODE2ID(n) ((struct id *) n) - - static struct id *free_id = NULL; @@ -28,39 +25,15 @@ struct tree *make_tree(int (*comp)(const struct id *a, const struct id *b)) tree = alloc_type(struct tree); tree->comp = comp; - tree->root = NULL; + tree->root = make_jrb(); return tree; } -static struct node *add_node(struct tree *tree, struct node *node) -{ - struct node **p, *last; - int cmp; - - p = &tree->root; - last = NULL; - while (*p) { - last = *p; - cmp = tree->comp(NODE2ID(node), NODE2ID(*p)); - if (cmp < 0) - p = &(*p)->left; - else if (cmp > 0) - p = &(*p)->right; - else - return *p; - } - *p = node; - node->up = last; - node->left = node->right = NULL; - return NULL; -} - - struct id *make_id(struct tree *tree, const char *s, size_t len) { struct id *id; - struct node *node; + struct jrb *node; if (!free_id) free_id = alloc_type(struct id); @@ -68,9 +41,10 @@ struct id *make_id(struct tree *tree, const char *s, size_t len) id->s = s; id->len = len; id->value = NULL; - node = add_node(tree, &id->node); + node = jrb_find(tree->root, id, tree->comp); if (node) - return NODE2ID(node); + return node->key; + id->jrb = jrb_insert(tree->root, id, NULL, tree->comp); free_id = NULL; return id; } @@ -82,48 +56,26 @@ const struct id *find_id(const struct tree *tree, const char *s, size_t len) .s = s, .len = len }; - const struct node *n = tree->root; - int cmp; + struct jrb *node; - while (n) { - cmp = tree->comp(&id, NODE2ID(n)); - if (cmp < 0) - n = n->left; - else if (cmp > 0) - n = n->right; - else - return NODE2ID(n); - } - return NULL; + node = jrb_find(tree->root, &id, tree->comp); + return node ? node->key : NULL; } const struct id *first_id(const struct tree *tree) { - const struct node *n = tree->root; + struct jrb *node; - if (!n) - return NULL; - while (n->left) - n = n->left; - return NODE2ID(n); + node = jrb_first(tree->root); + return node ? node->key : NULL; } const struct id *next_id(const struct id *id) { - const struct node *n = &id->node; + struct jrb *next; - if (n->right) { - n = n->right; - while (n->left) - n = n->left; - return NODE2ID(n); - } - while (n->up) { - if (n == n->up->left) - return NODE2ID(n->up); - n = n->up; - } - return NULL; + next = jrb_next(id->jrb); + return next ? next->key : NULL; } diff --git a/qpkg/id.h b/qpkg/id.h index b13738f..a4ab86a 100644 --- a/qpkg/id.h +++ b/qpkg/id.h @@ -3,25 +3,18 @@ #include +#include "jrb.h" + struct id; -/* - * @@@ basic binary trees are not a good choice. should use rb. - * To ease future migration, we separate the node structure from the rest. - */ - -struct node { - struct node *up, *left, *right; -}; - struct tree { int (*comp)(const struct id *a, const struct id *b); - struct node *root; + struct jrb *root; }; struct id { - struct node node; + struct jrb *jrb; const char *s; size_t len; void *value;