/** * Free resources used to hold information about the tree. This * function does not free memory pointed to by the data pointer * in a node - you have to free this memory by walking thru the * tree or use the callback version of rbt_free for a specific * tree type. * @param rbt tree pointer */ void rbt_free(rbt_t *rbt, void (*callback)(void *)) { struct rbt_node *stack[48], *n; register uint8_t depth; rbt_wlock(rbt); depth = 0; n = rbt_node_ptr(rbt->root); if (n != NULL) { rbt_walk_push(n); while(depth > 0) { n = rbt_node_ptr(rbt_walk_top()->_chld[RBT_NODE_SL]); if (n != NULL) rbt_walk_push(n); else { __in: if (callback != NULL) callback((void *)&(rbt_walk_top()->_node)); n = rbt_node_ptr(rbt_walk_top()->_chld[RBT_NODE_SR]); free(rbt_walk_top()); if (n != NULL) rbt_walk_top() = n; else { if (--depth > 0) goto __in; else break; } } } } rbt_wunlock(rbt); rbt->root = NULL; rbt->size = 0; rbt->type = -1; #if defined(RBT_IMPLICIT_LOCKING) pthread_rwlock_destroy (&rbt->lock); #endif free (rbt); return; }
/* * Add new entry to the tree. If `coll' is not NULL and there is * already an entry with the same key (i.e. a collision), then * place the old data pointer at `*coll' and update it to the * new data pointer. Otherwise, if `coll' is NULL and there is a * collision, then an error is returned and no modification of * the tree is made. * * @param rbt pointer to the tree * @param key key * @param data data pointer * @param coll where to store the data pointer from an colliding entry */ int rbt_i64_add(rbt_t *rbt, int64_t key, void *data, void **coll) { struct rbt_node fake; register struct rbt_node *h[4]; register uint8_t dvec; register int64_t n_key, u_key; u_key = key; rbt_wlock(rbt); /* * Fake node */ fake._chld[RBT_NODE_SL] = NULL; fake._chld[RBT_NODE_SR] = rbt->root; rbt_node_setcolor(&fake, RBT_NODE_CB); /* * Prepare node history stack & direction history vector */ h[3] = NULL; h[2] = NULL; h[1] = &fake; h[0] = rbt->root; dvec = RBT_NODE_SR; for (;;) { if (rbt_node_ptr(h[0]) == NULL) { /* * Allocate new node aligned to sizeof(void *) bytes. * On most systems, malloc already returns aligned * memory but we want to ensure that its aligned using * posix_memalign(3). */ h[0] = rbt_i64_node_alloc (); rbt_i64_node(h[0])->key = key; rbt_i64_node(h[0])->data = data; /* * Set the new node as the child of the last node we've * visited. The last direction is the lowest bit of the * direction history vector. */ rbt_node_setptr(rbt_node_ptr(h[1])->_chld[dvec & 1], h[0]); rbt_node_setcolor(h[0], RBT_NODE_CR); /* * Since we are inserting a new red node, we need to fix * a red violation if the parent of the new node is red. */ if (rbt_node_getcolor(h[1]) == RBT_NODE_CR) { rbt_redfix(h, dvec, rbt_node_ptr(h[3])->_chld[(dvec >> 2) & 1]); } /* * Update root node and color it black */ rbt->root = fake._chld[RBT_NODE_SR]; rbt_node_setcolor(rbt->root, RBT_NODE_CB); /* * Update node counter */ ++(rbt->size); break; } else if (rbt_node_getcolor(rbt_node_ptr(h[0])->_chld[0]) == RBT_NODE_CR &&