Module Name: src Committed By: yamt Date: Mon May 25 14:54:06 UTC 2009
Modified Files: src/common/lib/libc/gen: rpst.c src/sys/sys: rpst.h Log Message: maintain parent node pointers to speed up search and node removal. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/common/lib/libc/gen/rpst.c cvs rdiff -u -r1.1 -r1.2 src/sys/sys/rpst.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/common/lib/libc/gen/rpst.c diff -u src/common/lib/libc/gen/rpst.c:1.4 src/common/lib/libc/gen/rpst.c:1.5 --- src/common/lib/libc/gen/rpst.c:1.4 Mon May 25 14:16:54 2009 +++ src/common/lib/libc/gen/rpst.c Mon May 25 14:54:06 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: rpst.c,v 1.4 2009/05/25 14:16:54 yamt Exp $ */ +/* $NetBSD: rpst.c,v 1.5 2009/05/25 14:54:06 yamt Exp $ */ /*- * Copyright (c)2009 YAMAMOTO Takashi, @@ -43,10 +43,10 @@ #include <sys/cdefs.h> #if defined(_KERNEL) -__KERNEL_RCSID(0, "$NetBSD: rpst.c,v 1.4 2009/05/25 14:16:54 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rpst.c,v 1.5 2009/05/25 14:54:06 yamt Exp $"); #include <sys/param.h> #else /* defined(_KERNEL) */ -__RCSID("$NetBSD: rpst.c,v 1.4 2009/05/25 14:16:54 yamt Exp $"); +__RCSID("$NetBSD: rpst.c,v 1.5 2009/05/25 14:54:06 yamt Exp $"); #include <assert.h> #include <stdbool.h> #include <string.h> @@ -130,6 +130,22 @@ } /* + * rpst_update_parents: update n_parent of children + */ + +static inline void +rpst_update_parents(struct rpst_node *n) +{ + int i; + + for (i = 0; i < 2; i++) { + if (n->n_children[i] != NULL) { + n->n_children[i]->n_parent = n; + } + } +} + +/* * rpst_enlarge_tree: enlarge tree so that 'index' can be stored */ @@ -144,7 +160,9 @@ rpst_remove_node(t, n); memset(&n->n_children, 0, sizeof(n->n_children)); n->n_children[0] = t->t_root; + t->t_root->n_parent = n; t->t_root = n; + n->n_parent = NULL; } t->t_height++; } @@ -157,23 +175,32 @@ static struct rpst_node * rpst_insert_node1(struct rpst_node **where, struct rpst_node *n, uint64_t mask) { + struct rpst_node *parent; struct rpst_node *cur; unsigned int idx; KASSERT((n->n_x & ((-mask) << 1)) == 0); + parent = NULL; next: cur = *where; if (cur == NULL) { + n->n_parent = parent; memset(&n->n_children, 0, sizeof(n->n_children)); *where = n; return NULL; } + KASSERT(cur->n_parent == parent); if (n->n_y == cur->n_y && n->n_x == cur->n_x) { return cur; } if (n->n_y < cur->n_y) { - /* swap cur and n */ + /* + * swap cur and n. + * note that n is not in tree. + */ memcpy(n->n_children, cur->n_children, sizeof(n->n_children)); + n->n_parent = cur->n_parent; + rpst_update_parents(n); *where = n; n = cur; cur = *where; @@ -181,6 +208,7 @@ KASSERT(*where == cur); idx = (n->n_x & mask) != 0; where = &cur->n_children[idx]; + parent = cur; KASSERT((*where) == NULL || ((((*where)->n_x & mask) != 0) == idx)); KASSERT((*where) == NULL || (*where)->n_y >= cur->n_y); mask >>= 1; @@ -207,33 +235,26 @@ * rpst_find_pptr: find a pointer to the given node. * * also, return the parent node via parentp. (NULL for the root node.) - * - * XXX is it better to simply make each nodes have a pointer to parent? */ -static struct rpst_node ** -rpst_find_pptr(struct rpst_node **where, struct rpst_node *n, uint64_t mask, +static inline struct rpst_node ** +rpst_find_pptr(struct rpst_tree *t, struct rpst_node *n, struct rpst_node **parentp) { - struct rpst_node *pn = NULL; - struct rpst_node *cur; - unsigned int idx; + struct rpst_node * const parent = n->n_parent; + unsigned int i; -next: - cur = *where; - KASSERT(cur != NULL); - if (cur == n) { - KASSERT(pn == NULL || pn->n_y <= n->n_y); - *parentp = pn; - return where; + *parentp = parent; + if (parent == NULL) { + return &t->t_root; } - idx = (n->n_x & mask) != 0; - pn = cur; - where = &cur->n_children[idx]; - KASSERT((*where) == NULL || ((((*where)->n_x & mask) != 0) == idx)); - KASSERT((*where) == NULL || (*where)->n_y >= cur->n_y); - mask >>= 1; - goto next; + for (i = 0; i < 2 - 1; i++) { + if (parent->n_children[i] == n) { + break; + } + } + KASSERT(parent->n_children[i] == n); + return &parent->n_children[i]; } /* @@ -241,22 +262,23 @@ */ static void -rpst_remove_node_at(struct rpst_node **where) +rpst_remove_node_at(struct rpst_node *parent, struct rpst_node **where, + struct rpst_node *cur) { struct rpst_node *tmp[2]; - struct rpst_node *cur; struct rpst_node *selected; - unsigned int selected_idx; + unsigned int selected_idx = 0; /* XXX gcc */ unsigned int i; - cur = *where; KASSERT(cur != NULL); + KASSERT(parent == cur->n_parent); next: selected = NULL; for (i = 0; i < 2; i++) { struct rpst_node *c; c = cur->n_children[i]; + KASSERT(c == NULL || c->n_parent == cur); if (selected == NULL || (c != NULL && c->n_y < selected->n_y)) { selected = c; selected_idx = i; @@ -265,6 +287,7 @@ /* * now we have: * + * parent * \ <- where * cur * / \ @@ -282,7 +305,11 @@ memcpy(tmp, selected->n_children, sizeof(tmp)); memcpy(selected->n_children, cur->n_children, sizeof(tmp)); memcpy(cur->n_children, tmp, sizeof(tmp)); + rpst_update_parents(cur); + rpst_update_parents(selected); + selected->n_parent = parent; /* + * parent * \ <- where * selected * / \ @@ -294,15 +321,20 @@ */ where = &selected->n_children[selected_idx]; /* + * parent * \ * selected * / \ <- where - * A selected + * A selected (*) * - * cur + * cur (**) * / \ * B C + * + * (*) this 'selected' will be overwritten in the next iteration. + * (**) cur->n_parent is bogus. */ + parent = selected; goto next; } @@ -316,9 +348,8 @@ struct rpst_node *parent; struct rpst_node **where; - where = rpst_find_pptr(&t->t_root, n, rpst_startmask(t), &parent); - KASSERT(*where == n); - rpst_remove_node_at(where); + where = rpst_find_pptr(t, n, &parent); + rpst_remove_node_at(parent, where, n); } static bool __unused @@ -432,7 +463,7 @@ } else if (idx == maxidx + 2) { /* back to the parent */ struct rpst_node **where; - where = rpst_find_pptr(&t->t_root, n, rpst_startmask(t), &next); + where = rpst_find_pptr(t, n, &next); if (next == NULL) { KASSERT(level == 0); KASSERT(t->t_root == n); @@ -455,6 +486,7 @@ idx++; goto next; } + KASSERT(next->n_parent == n); KASSERT(next->n_y >= n->n_y); level++; mask >>= 1; Index: src/sys/sys/rpst.h diff -u src/sys/sys/rpst.h:1.1 src/sys/sys/rpst.h:1.2 --- src/sys/sys/rpst.h:1.1 Tue May 19 12:39:56 2009 +++ src/sys/sys/rpst.h Mon May 25 14:54:06 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: rpst.h,v 1.1 2009/05/19 12:39:56 yamt Exp $ */ +/* $NetBSD: rpst.h,v 1.2 2009/05/25 14:54:06 yamt Exp $ */ /*- * Copyright (c)2009 YAMAMOTO Takashi, @@ -41,6 +41,7 @@ }; struct rpst_node { + struct rpst_node *n_parent; struct rpst_node *n_children[2]; uint64_t n_y; uint64_t n_x;