]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Rbtree iterator fixes
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 24 Feb 2021 23:12:48 +0000 (23:12 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 24 Feb 2021 23:12:48 +0000 (23:12 +0000)
src/lib/util/rbtree.c
src/lib/util/rbtree.h
src/lib/util/rbtree_tests.c

index 1dd6f7036f21e8d0da2f6cefb65a3b29ef2539bf..8e419001256fa66344e2e8d8779623d822b1aa4e 100644 (file)
@@ -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);
-}
index af07c221959a74951fc5f431bd38343b5db3cb41..63729eb26c4085471620749a07bbd9d61ba6b000 100644 (file)
@@ -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
index 4b2f542a5230e69fdad35271ed0ffe8688132937..3d849e7f69772890b4878835058f4ed011474e71 100644 (file)
@@ -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_      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);
        }
 
        /*