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
*
*/
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.
* - 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;
/*
* First, the root.
*/
- *iter = (fr_rb_tree_iter_t){
+ *iter = (fr_rb_tree_iter_preorder_t){
.tree = tree,
.node = x
};
* - 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;
* - 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;
x = x->right;
}
- *iter = (fr_rb_tree_iter_t){
+ *iter = (fr_rb_tree_iter_postorder_t){
.tree = tree,
.node = x
};
* - 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;
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);
-}
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);
*/
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 {
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
*
*/
#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
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");
/*
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");
/*
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);
}
/*