From: Arran Cudbard-Bell Date: Wed, 24 Feb 2021 23:12:48 +0000 (+0000) Subject: Rbtree iterator fixes X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3b5d1e36088a6f8bb1370257d160551d768bd32e;p=thirdparty%2Ffreeradius-server.git Rbtree iterator fixes --- diff --git a/src/lib/util/rbtree.c b/src/lib/util/rbtree.c index 1dd6f7036f2..8e419001256 100644 --- a/src/lib/util/rbtree.c +++ b/src/lib/util/rbtree.c @@ -184,6 +184,16 @@ rbtree_t *_rbtree_alloc(TALLOC_CTX *ctx, return tree; } +/** Explicitly unlock an rbtree locked with an interator + * + */ +void rbtree_unlock(rbtree_t *tree) +{ + if (!tree->lock) return; + + pthread_mutex_unlock(&tree->mutex); +} + /** Rotate Node x to left * */ @@ -957,6 +967,23 @@ void *rbtree_iter_next_inorder(fr_rb_tree_iter_inorder_t *iter) return x->data; } +/** Remove the current node from the tree + * + * @note Only makes sense for in-order traversals. + * + * @param[in] iter previously initialised with #rbtree_iter_inorder_init + */ +void rbtree_iter_delete_inorder(fr_rb_tree_iter_inorder_t *iter) +{ + fr_rb_node_t *x = iter->node; + + if (unlikely(x == NIL)) return; + (void) rbtree_iter_next_inorder(iter); + iter->next = iter->node; + iter->node = NULL; + rbtree_delete_internal(iter->tree, x, true); +} + /** Initialise a pre-order iterator * * @note If iteration ends early because of a loop condition #rbtree_iter_done must be called. @@ -967,7 +994,7 @@ void *rbtree_iter_next_inorder(fr_rb_tree_iter_inorder_t *iter) * - The first node. Mutex will be held. * - NULL if the tree is empty. */ -void *rbtree_iter_init_preorder(fr_rb_tree_iter_t *iter, rbtree_t *tree) +void *rbtree_iter_init_preorder(fr_rb_tree_iter_preorder_t *iter, rbtree_t *tree) { fr_rb_node_t *x = tree->root; @@ -978,7 +1005,7 @@ void *rbtree_iter_init_preorder(fr_rb_tree_iter_t *iter, rbtree_t *tree) /* * First, the root. */ - *iter = (fr_rb_tree_iter_t){ + *iter = (fr_rb_tree_iter_preorder_t){ .tree = tree, .node = x }; @@ -995,7 +1022,7 @@ void *rbtree_iter_init_preorder(fr_rb_tree_iter_t *iter, rbtree_t *tree) * - The next node. * - NULL if no more nodes remain. */ -void *rbtree_iter_next_preorder(fr_rb_tree_iter_t *iter) +void *rbtree_iter_next_preorder(fr_rb_tree_iter_preorder_t *iter) { fr_rb_node_t *x = iter->node, *y; @@ -1051,7 +1078,7 @@ void *rbtree_iter_next_preorder(fr_rb_tree_iter_t *iter) * - The first node. Mutex will be held. * - NULL if the tree is empty. */ -void *rbtree_iter_init_postorder(fr_rb_tree_iter_t *iter, rbtree_t *tree) +void *rbtree_iter_init_postorder(fr_rb_tree_iter_postorder_t *iter, rbtree_t *tree) { fr_rb_node_t *x = tree->root; @@ -1069,7 +1096,7 @@ void *rbtree_iter_init_postorder(fr_rb_tree_iter_t *iter, rbtree_t *tree) x = x->right; } - *iter = (fr_rb_tree_iter_t){ + *iter = (fr_rb_tree_iter_postorder_t){ .tree = tree, .node = x }; @@ -1086,7 +1113,7 @@ void *rbtree_iter_init_postorder(fr_rb_tree_iter_t *iter, rbtree_t *tree) * - The next node. * - NULL if no more nodes remain. */ -void *rbtree_iter_next_postorder(fr_rb_tree_iter_t *iter) +void *rbtree_iter_next_postorder(fr_rb_tree_iter_postorder_t *iter) { fr_rb_node_t *x = iter->node, *y; @@ -1132,20 +1159,3 @@ void *rbtree_iter_next_postorder(fr_rb_tree_iter_t *iter) iter->node = x; return x->data; } - -/** Remove the current node from the tree - * - * @note Only makes sense for in-order traversals. - * - * @param[in] iter previously initialised with #rbtree_iter_inorder_init - */ -void rbtree_iter_inorder_delete(fr_rb_tree_iter_inorder_t *iter) -{ - fr_rb_node_t *x = iter->node; - - if (unlikely(x == NIL)) return; - (void) rbtree_iter_next_inorder(iter); - iter->next = iter->node; - iter->node = NULL; - rbtree_delete_internal(iter->tree, x, true); -} diff --git a/src/lib/util/rbtree.h b/src/lib/util/rbtree.h index af07c221959..63729eb26c4 100644 --- a/src/lib/util/rbtree.h +++ b/src/lib/util/rbtree.h @@ -126,6 +126,8 @@ typedef void (*fr_rb_free_t)(void *data); rbtree_t *_rbtree_alloc(TALLOC_CTX *ctx, size_t offset, char const *type, fr_rb_cmp_t compare, fr_rb_free_t node_free, int flags); +void rbtree_unlock(rbtree_t *tree); + void rbtree_node_talloc_free(void *data); bool rbtree_insert(rbtree_t *tree, void const *data); @@ -166,13 +168,6 @@ void *rbtree_node2data(rbtree_t *tree, fr_rb_node_t *node); */ int rbtree_walk(rbtree_t *tree, fr_rb_order_t order, fr_rb_walker_t compare, void *uctx); -/** Iterator structure for pre- or post-order traversal of an rbtreer - */ -typedef struct { - rbtree_t *tree; //!< Tree being iterated over. - fr_rb_node_t *node; ///< current node -} fr_rb_tree_iter_t; - /** Iterator structure for in-order traversal of an rbtree */ typedef struct { @@ -185,15 +180,29 @@ void *rbtree_iter_init_inorder(fr_rb_tree_iter_inorder_t *iter, rbtree_t *tree) void *rbtree_iter_next_inorder(fr_rb_tree_iter_inorder_t *iter) CC_HINT(nonnull); -void *rbtree_iter_init_preorder(fr_rb_tree_iter_t *iter, rbtree_t *tree) CC_HINT(nonnull); +void rbtree_iter_delete_inorder(fr_rb_tree_iter_inorder_t *iter) CC_HINT(nonnull); + +/** Iterator structure for pre-order traversal of an rbtree + */ +typedef struct { + rbtree_t *tree; //!< Tree being iterated over. + fr_rb_node_t *node; ///< current node +} fr_rb_tree_iter_preorder_t; + +void *rbtree_iter_init_preorder(fr_rb_tree_iter_preorder_t *iter, rbtree_t *tree) CC_HINT(nonnull); -void *rbtree_iter_next_preorder(fr_rb_tree_iter_t *iter) CC_HINT(nonnull); +void *rbtree_iter_next_preorder(fr_rb_tree_iter_preorder_t *iter) CC_HINT(nonnull); -void *rbtree_iter_init_postorder(fr_rb_tree_iter_t *iter, rbtree_t *tree) CC_HINT(nonnull); +/** Iterator structure for post-order traversal of an rbtree + */ +typedef struct { + rbtree_t *tree; //!< Tree being iterated over. + fr_rb_node_t *node; ///< current node +} fr_rb_tree_iter_postorder_t; -void *rbtree_iter_next_postorder(fr_rb_tree_iter_t *iter) CC_HINT(nonnull); +void *rbtree_iter_init_postorder(fr_rb_tree_iter_postorder_t *iter, rbtree_t *tree) CC_HINT(nonnull); -void rbtree_iter_inorder_delete(fr_rb_tree_iter_inorder_t *iter); +void *rbtree_iter_next_postorder(fr_rb_tree_iter_postorder_t *iter) CC_HINT(nonnull); /** Explicitly unlock the tree * @@ -203,10 +212,9 @@ void rbtree_iter_inorder_delete(fr_rb_tree_iter_inorder_t *iter); */ #define rbtree_iter_done(_iter) \ (_Generic(_iter), \ - (fr_rb_tree_iter_t *) : (void) (((fr_rb_tree_iter_t *)(_iter)->lock) ? \ - pthread_mutex_unlock((fr_rb_tree_iter_t *)(_iter)->lock) : 0), \ - (fr_rb_tree_iter_inorder_t *) : (void) (((fr_rb_tree_iter_inorder_t *)(_iter)->lock) ? \ - pthread_mutex_unlock((fr_rb_tree_iter_inorder_t *)(_iter)->lock) : 0), \ + (fr_rb_tree_iter_inorder_t *) : rbtree_unlock(((fr_rb_tree_iter_inorder_t *)(_iter))->tree), \ + (fr_rb_tree_iter_preorder_t *) : rbtree_unlock(((fr_rb_tree_iter_preorder_t *)(_iter))->tree), \ + (fr_rb_tree_iter_postorder_t *) : rbtree_unlock(((fr_rb_tree_iter_postorder_t *)(_iter))->tree) \ ) #ifdef __cplusplus diff --git a/src/lib/util/rbtree_tests.c b/src/lib/util/rbtree_tests.c index 4b2f542a523..3d849e7f697 100644 --- a/src/lib/util/rbtree_tests.c +++ b/src/lib/util/rbtree_tests.c @@ -92,10 +92,10 @@ static uint32_t post_output[] = {0, 4, 3, 144, 49, 4096, 25194, 8192, 256, 15}; static void test_rbtree_iter_preorder(void) { - rbtree_t *t; - fr_rb_test_node_t *p; - size_t i; - fr_rb_tree_iter_t iter; + rbtree_t *t; + fr_rb_test_node_t *p; + size_t i; + fr_rb_tree_iter_preorder_t iter; TEST_CASE("pre-order iterator"); /* @@ -126,10 +126,10 @@ static void test_rbtree_iter_preorder(void) static void test_rbtree_iter_postorder(void) { - rbtree_t *t; - fr_rb_test_node_t *p; - size_t i; - fr_rb_tree_iter_t iter; + rbtree_t *t; + fr_rb_test_node_t *p; + size_t i; + fr_rb_tree_iter_postorder_t iter; TEST_CASE("post-order iterator"); /* @@ -202,7 +202,7 @@ static void test_rbtree_iter_delete(void) for (p = rbtree_iter_init_inorder(&iter, t); p; p = rbtree_iter_next_inorder(&iter)) { - if (is_prime(p->num)) rbtree_iter_inorder_delete(&iter); + if (is_prime(p->num)) rbtree_iter_delete_inorder(&iter); } /*