]>
git.proxmox.com Git - rustc.git/blob - src/jemalloc/include/jemalloc/internal/rb.h
2 *******************************************************************************
4 * cpp macro implementation of left-leaning 2-3 red-black trees. Parent
5 * pointers are not used, and color bits are stored in the least significant
6 * bit of right-child pointers (if RB_COMPACT is defined), thus making node
7 * linkage as compact as is possible for red-black trees.
12 * #include <stdbool.h>
13 * #define NDEBUG // (Optional, see assert(3).)
15 * #define RB_COMPACT // (Optional, embed color bits in right-child pointers.)
19 *******************************************************************************
27 #define rb_node(a_type) \
30 a_type *rbn_right_red; \
33 #define rb_node(a_type) \
42 #define rb_tree(a_type) \
48 #define rbtn_left_get(a_type, a_field, a_node) \
49 ((a_node)->a_field.rbn_left)
50 #define rbtn_left_set(a_type, a_field, a_node, a_left) do { \
51 (a_node)->a_field.rbn_left = a_left; \
55 /* Right accessors. */
56 #define rbtn_right_get(a_type, a_field, a_node) \
57 ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red) \
59 #define rbtn_right_set(a_type, a_field, a_node, a_right) do { \
60 (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right) \
61 | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1))); \
64 /* Color accessors. */
65 #define rbtn_red_get(a_type, a_field, a_node) \
66 ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red) \
68 #define rbtn_color_set(a_type, a_field, a_node, a_red) do { \
69 (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t) \
70 (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)) \
71 | ((ssize_t)a_red)); \
73 #define rbtn_red_set(a_type, a_field, a_node) do { \
74 (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) \
75 (a_node)->a_field.rbn_right_red) | ((size_t)1)); \
77 #define rbtn_black_set(a_type, a_field, a_node) do { \
78 (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t) \
79 (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)); \
82 /* Node initializer. */
83 #define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
84 /* Bookkeeping bit cannot be used by node pointer. */ \
85 assert(((uintptr_t)(a_node) & 0x1) == 0); \
86 rbtn_left_set(a_type, a_field, (a_node), NULL); \
87 rbtn_right_set(a_type, a_field, (a_node), NULL); \
88 rbtn_red_set(a_type, a_field, (a_node)); \
91 /* Right accessors. */
92 #define rbtn_right_get(a_type, a_field, a_node) \
93 ((a_node)->a_field.rbn_right)
94 #define rbtn_right_set(a_type, a_field, a_node, a_right) do { \
95 (a_node)->a_field.rbn_right = a_right; \
98 /* Color accessors. */
99 #define rbtn_red_get(a_type, a_field, a_node) \
100 ((a_node)->a_field.rbn_red)
101 #define rbtn_color_set(a_type, a_field, a_node, a_red) do { \
102 (a_node)->a_field.rbn_red = (a_red); \
104 #define rbtn_red_set(a_type, a_field, a_node) do { \
105 (a_node)->a_field.rbn_red = true; \
107 #define rbtn_black_set(a_type, a_field, a_node) do { \
108 (a_node)->a_field.rbn_red = false; \
111 /* Node initializer. */
112 #define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
113 rbtn_left_set(a_type, a_field, (a_node), NULL); \
114 rbtn_right_set(a_type, a_field, (a_node), NULL); \
115 rbtn_red_set(a_type, a_field, (a_node)); \
119 /* Tree initializer. */
120 #define rb_new(a_type, a_field, a_rbt) do { \
121 (a_rbt)->rbt_root = NULL; \
124 /* Internal utility macros. */
125 #define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do { \
126 (r_node) = (a_root); \
127 if ((r_node) != NULL) { \
129 rbtn_left_get(a_type, a_field, (r_node)) != NULL; \
130 (r_node) = rbtn_left_get(a_type, a_field, (r_node))) { \
135 #define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do { \
136 (r_node) = (a_root); \
137 if ((r_node) != NULL) { \
138 for (; rbtn_right_get(a_type, a_field, (r_node)) != NULL; \
139 (r_node) = rbtn_right_get(a_type, a_field, (r_node))) { \
144 #define rbtn_rotate_left(a_type, a_field, a_node, r_node) do { \
145 (r_node) = rbtn_right_get(a_type, a_field, (a_node)); \
146 rbtn_right_set(a_type, a_field, (a_node), \
147 rbtn_left_get(a_type, a_field, (r_node))); \
148 rbtn_left_set(a_type, a_field, (r_node), (a_node)); \
151 #define rbtn_rotate_right(a_type, a_field, a_node, r_node) do { \
152 (r_node) = rbtn_left_get(a_type, a_field, (a_node)); \
153 rbtn_left_set(a_type, a_field, (a_node), \
154 rbtn_right_get(a_type, a_field, (r_node))); \
155 rbtn_right_set(a_type, a_field, (r_node), (a_node)); \
159 * The rb_proto() macro generates function prototypes that correspond to the
160 * functions generated by an equivalently parameterized call to rb_gen().
163 #define rb_proto(a_attr, a_prefix, a_rbt_type, a_type) \
165 a_prefix##new(a_rbt_type *rbtree); \
167 a_prefix##empty(a_rbt_type *rbtree); \
169 a_prefix##first(a_rbt_type *rbtree); \
171 a_prefix##last(a_rbt_type *rbtree); \
173 a_prefix##next(a_rbt_type *rbtree, a_type *node); \
175 a_prefix##prev(a_rbt_type *rbtree, a_type *node); \
177 a_prefix##search(a_rbt_type *rbtree, const a_type *key); \
179 a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key); \
181 a_prefix##psearch(a_rbt_type *rbtree, const a_type *key); \
183 a_prefix##insert(a_rbt_type *rbtree, a_type *node); \
185 a_prefix##remove(a_rbt_type *rbtree, a_type *node); \
187 a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \
188 a_rbt_type *, a_type *, void *), void *arg); \
190 a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \
191 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg); \
193 a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \
197 * The rb_gen() macro generates a type-specific red-black tree implementation,
198 * based on the above cpp macros.
202 * a_attr : Function attribute for generated functions (ex: static).
203 * a_prefix : Prefix for generated functions (ex: ex_).
204 * a_rb_type : Type for red-black tree data structure (ex: ex_t).
205 * a_type : Type for red-black tree node data structure (ex: ex_node_t).
206 * a_field : Name of red-black tree node linkage (ex: ex_link).
207 * a_cmp : Node comparison function name, with the following prototype:
208 * int (a_cmp *)(a_type *a_node, a_type *a_other);
211 * Interpretation of comparison function return values:
212 * -1 : a_node < a_other
213 * 0 : a_node == a_other
214 * 1 : a_node > a_other
215 * In all cases, the a_node or a_key macro argument is the first
216 * argument to the comparison function, which makes it possible
217 * to write comparison functions that treat the first argument
220 * Assuming the following setup:
222 * typedef struct ex_node_s ex_node_t;
224 * rb_node(ex_node_t) ex_link;
226 * typedef rb_tree(ex_node_t) ex_t;
227 * rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp)
229 * The following API is generated:
232 * ex_new(ex_t *tree);
233 * Description: Initialize a red-black tree structure.
235 * tree: Pointer to an uninitialized red-black tree object.
238 * ex_empty(ex_t *tree);
239 * Description: Determine whether tree is empty.
241 * tree: Pointer to an initialized red-black tree object.
242 * Ret: True if tree is empty, false otherwise.
245 * ex_first(ex_t *tree);
247 * ex_last(ex_t *tree);
248 * Description: Get the first/last node in tree.
250 * tree: Pointer to an initialized red-black tree object.
251 * Ret: First/last node in tree, or NULL if tree is empty.
254 * ex_next(ex_t *tree, ex_node_t *node);
256 * ex_prev(ex_t *tree, ex_node_t *node);
257 * Description: Get node's successor/predecessor.
259 * tree: Pointer to an initialized red-black tree object.
260 * node: A node in tree.
261 * Ret: node's successor/predecessor in tree, or NULL if node is
265 * ex_search(ex_t *tree, const ex_node_t *key);
266 * Description: Search for node that matches key.
268 * tree: Pointer to an initialized red-black tree object.
270 * Ret: Node in tree that matches key, or NULL if no match.
273 * ex_nsearch(ex_t *tree, const ex_node_t *key);
275 * ex_psearch(ex_t *tree, const ex_node_t *key);
276 * Description: Search for node that matches key. If no match is found,
277 * return what would be key's successor/predecessor, were
280 * tree: Pointer to an initialized red-black tree object.
282 * Ret: Node in tree that matches key, or if no match, hypothetical node's
283 * successor/predecessor (NULL if no successor/predecessor).
286 * ex_insert(ex_t *tree, ex_node_t *node);
287 * Description: Insert node into tree.
289 * tree: Pointer to an initialized red-black tree object.
290 * node: Node to be inserted into tree.
293 * ex_remove(ex_t *tree, ex_node_t *node);
294 * Description: Remove node from tree.
296 * tree: Pointer to an initialized red-black tree object.
297 * node: Node in tree to be removed.
300 * ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,
301 * ex_node_t *, void *), void *arg);
303 * ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,
304 * ex_node_t *, void *), void *arg);
305 * Description: Iterate forward/backward over tree, starting at node. If
306 * tree is modified, iteration must be immediately
307 * terminated by the callback function that causes the
310 * tree : Pointer to an initialized red-black tree object.
311 * start: Node at which to start iteration, or NULL to start at
313 * cb : Callback function, which is called for each node during
314 * iteration. Under normal circumstances the callback function
315 * should return NULL, which causes iteration to continue. If a
316 * callback function returns non-NULL, iteration is immediately
317 * terminated and the non-NULL return value is returned by the
318 * iterator. This is useful for re-starting iteration after
320 * arg : Opaque pointer passed to cb().
321 * Ret: NULL if iteration completed, or the non-NULL callback return value
322 * that caused termination of the iteration.
325 * ex_destroy(ex_t *tree, void (*cb)(ex_node_t *, void *), void *arg);
326 * Description: Iterate over the tree with post-order traversal, remove
327 * each node, and run the callback if non-null. This is
328 * used for destroying a tree without paying the cost to
329 * rebalance it. The tree must not be otherwise altered
332 * tree: Pointer to an initialized red-black tree object.
333 * cb : Callback function, which, if non-null, is called for each node
334 * during iteration. There is no way to stop iteration once it
336 * arg : Opaque pointer passed to cb().
338 #define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \
340 a_prefix##new(a_rbt_type *rbtree) { \
341 rb_new(a_type, a_field, rbtree); \
344 a_prefix##empty(a_rbt_type *rbtree) { \
345 return (rbtree->rbt_root == NULL); \
348 a_prefix##first(a_rbt_type *rbtree) { \
350 rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
354 a_prefix##last(a_rbt_type *rbtree) { \
356 rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
360 a_prefix##next(a_rbt_type *rbtree, a_type *node) { \
362 if (rbtn_right_get(a_type, a_field, node) != NULL) { \
363 rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type, \
364 a_field, node), ret); \
366 a_type *tnode = rbtree->rbt_root; \
367 assert(tnode != NULL); \
370 int cmp = (a_cmp)(node, tnode); \
373 tnode = rbtn_left_get(a_type, a_field, tnode); \
374 } else if (cmp > 0) { \
375 tnode = rbtn_right_get(a_type, a_field, tnode); \
379 assert(tnode != NULL); \
385 a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \
387 if (rbtn_left_get(a_type, a_field, node) != NULL) { \
388 rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type, \
389 a_field, node), ret); \
391 a_type *tnode = rbtree->rbt_root; \
392 assert(tnode != NULL); \
395 int cmp = (a_cmp)(node, tnode); \
397 tnode = rbtn_left_get(a_type, a_field, tnode); \
398 } else if (cmp > 0) { \
400 tnode = rbtn_right_get(a_type, a_field, tnode); \
404 assert(tnode != NULL); \
410 a_prefix##search(a_rbt_type *rbtree, const a_type *key) { \
413 ret = rbtree->rbt_root; \
415 && (cmp = (a_cmp)(key, ret)) != 0) { \
417 ret = rbtn_left_get(a_type, a_field, ret); \
419 ret = rbtn_right_get(a_type, a_field, ret); \
425 a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) { \
427 a_type *tnode = rbtree->rbt_root; \
429 while (tnode != NULL) { \
430 int cmp = (a_cmp)(key, tnode); \
433 tnode = rbtn_left_get(a_type, a_field, tnode); \
434 } else if (cmp > 0) { \
435 tnode = rbtn_right_get(a_type, a_field, tnode); \
444 a_prefix##psearch(a_rbt_type *rbtree, const a_type *key) { \
446 a_type *tnode = rbtree->rbt_root; \
448 while (tnode != NULL) { \
449 int cmp = (a_cmp)(key, tnode); \
451 tnode = rbtn_left_get(a_type, a_field, tnode); \
452 } else if (cmp > 0) { \
454 tnode = rbtn_right_get(a_type, a_field, tnode); \
463 a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \
467 } path[sizeof(void *) << 4], *pathp; \
468 rbt_node_new(a_type, a_field, rbtree, node); \
470 path->node = rbtree->rbt_root; \
471 for (pathp = path; pathp->node != NULL; pathp++) { \
472 int cmp = pathp->cmp = a_cmp(node, pathp->node); \
475 pathp[1].node = rbtn_left_get(a_type, a_field, \
478 pathp[1].node = rbtn_right_get(a_type, a_field, \
482 pathp->node = node; \
484 for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \
485 a_type *cnode = pathp->node; \
486 if (pathp->cmp < 0) { \
487 a_type *left = pathp[1].node; \
488 rbtn_left_set(a_type, a_field, cnode, left); \
489 if (rbtn_red_get(a_type, a_field, left)) { \
490 a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
491 if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
493 /* Fix up 4-node. */ \
495 rbtn_black_set(a_type, a_field, leftleft); \
496 rbtn_rotate_right(a_type, a_field, cnode, tnode); \
503 a_type *right = pathp[1].node; \
504 rbtn_right_set(a_type, a_field, cnode, right); \
505 if (rbtn_red_get(a_type, a_field, right)) { \
506 a_type *left = rbtn_left_get(a_type, a_field, cnode); \
507 if (left != NULL && rbtn_red_get(a_type, a_field, \
509 /* Split 4-node. */ \
510 rbtn_black_set(a_type, a_field, left); \
511 rbtn_black_set(a_type, a_field, right); \
512 rbtn_red_set(a_type, a_field, cnode); \
516 bool tred = rbtn_red_get(a_type, a_field, cnode); \
517 rbtn_rotate_left(a_type, a_field, cnode, tnode); \
518 rbtn_color_set(a_type, a_field, tnode, tred); \
519 rbtn_red_set(a_type, a_field, cnode); \
526 pathp->node = cnode; \
528 /* Set root, and make it black. */ \
529 rbtree->rbt_root = path->node; \
530 rbtn_black_set(a_type, a_field, rbtree->rbt_root); \
533 a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
537 } *pathp, *nodep, path[sizeof(void *) << 4]; \
539 nodep = NULL; /* Silence compiler warning. */ \
540 path->node = rbtree->rbt_root; \
541 for (pathp = path; pathp->node != NULL; pathp++) { \
542 int cmp = pathp->cmp = a_cmp(node, pathp->node); \
544 pathp[1].node = rbtn_left_get(a_type, a_field, \
547 pathp[1].node = rbtn_right_get(a_type, a_field, \
550 /* Find node's successor, in preparation for swap. */ \
553 for (pathp++; pathp->node != NULL; \
556 pathp[1].node = rbtn_left_get(a_type, a_field, \
563 assert(nodep->node == node); \
565 if (pathp->node != node) { \
566 /* Swap node with its successor. */ \
567 bool tred = rbtn_red_get(a_type, a_field, pathp->node); \
568 rbtn_color_set(a_type, a_field, pathp->node, \
569 rbtn_red_get(a_type, a_field, node)); \
570 rbtn_left_set(a_type, a_field, pathp->node, \
571 rbtn_left_get(a_type, a_field, node)); \
572 /* If node's successor is its right child, the following code */\
573 /* will do the wrong thing for the right child pointer. */\
574 /* However, it doesn't matter, because the pointer will be */\
575 /* properly set when the successor is pruned. */\
576 rbtn_right_set(a_type, a_field, pathp->node, \
577 rbtn_right_get(a_type, a_field, node)); \
578 rbtn_color_set(a_type, a_field, node, tred); \
579 /* The pruned leaf node's child pointers are never accessed */\
580 /* again, so don't bother setting them to nil. */\
581 nodep->node = pathp->node; \
582 pathp->node = node; \
583 if (nodep == path) { \
584 rbtree->rbt_root = nodep->node; \
586 if (nodep[-1].cmp < 0) { \
587 rbtn_left_set(a_type, a_field, nodep[-1].node, \
590 rbtn_right_set(a_type, a_field, nodep[-1].node, \
595 a_type *left = rbtn_left_get(a_type, a_field, node); \
596 if (left != NULL) { \
597 /* node has no successor, but it has a left child. */\
598 /* Splice node out, without losing the left child. */\
599 assert(!rbtn_red_get(a_type, a_field, node)); \
600 assert(rbtn_red_get(a_type, a_field, left)); \
601 rbtn_black_set(a_type, a_field, left); \
602 if (pathp == path) { \
603 rbtree->rbt_root = left; \
605 if (pathp[-1].cmp < 0) { \
606 rbtn_left_set(a_type, a_field, pathp[-1].node, \
609 rbtn_right_set(a_type, a_field, pathp[-1].node, \
614 } else if (pathp == path) { \
615 /* The tree only contained one node. */ \
616 rbtree->rbt_root = NULL; \
620 if (rbtn_red_get(a_type, a_field, pathp->node)) { \
621 /* Prune red node, which requires no fixup. */ \
622 assert(pathp[-1].cmp < 0); \
623 rbtn_left_set(a_type, a_field, pathp[-1].node, NULL); \
626 /* The node to be pruned is black, so unwind until balance is */\
628 pathp->node = NULL; \
629 for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \
630 assert(pathp->cmp != 0); \
631 if (pathp->cmp < 0) { \
632 rbtn_left_set(a_type, a_field, pathp->node, \
634 if (rbtn_red_get(a_type, a_field, pathp->node)) { \
635 a_type *right = rbtn_right_get(a_type, a_field, \
637 a_type *rightleft = rbtn_left_get(a_type, a_field, \
640 if (rightleft != NULL && rbtn_red_get(a_type, a_field, \
642 /* In the following diagrams, ||, //, and \\ */\
643 /* indicate the path to the removed node. */\
652 rbtn_black_set(a_type, a_field, pathp->node); \
653 rbtn_rotate_right(a_type, a_field, right, tnode); \
654 rbtn_right_set(a_type, a_field, pathp->node, tnode);\
655 rbtn_rotate_left(a_type, a_field, pathp->node, \
665 rbtn_rotate_left(a_type, a_field, pathp->node, \
668 /* Balance restored, but rotation modified subtree */\
670 assert((uintptr_t)pathp > (uintptr_t)path); \
671 if (pathp[-1].cmp < 0) { \
672 rbtn_left_set(a_type, a_field, pathp[-1].node, \
675 rbtn_right_set(a_type, a_field, pathp[-1].node, \
680 a_type *right = rbtn_right_get(a_type, a_field, \
682 a_type *rightleft = rbtn_left_get(a_type, a_field, \
684 if (rightleft != NULL && rbtn_red_get(a_type, a_field, \
693 rbtn_black_set(a_type, a_field, rightleft); \
694 rbtn_rotate_right(a_type, a_field, right, tnode); \
695 rbtn_right_set(a_type, a_field, pathp->node, tnode);\
696 rbtn_rotate_left(a_type, a_field, pathp->node, \
698 /* Balance restored, but rotation modified */\
699 /* subtree root, which may actually be the tree */\
701 if (pathp == path) { \
703 rbtree->rbt_root = tnode; \
705 if (pathp[-1].cmp < 0) { \
706 rbtn_left_set(a_type, a_field, \
707 pathp[-1].node, tnode); \
709 rbtn_right_set(a_type, a_field, \
710 pathp[-1].node, tnode); \
722 rbtn_red_set(a_type, a_field, pathp->node); \
723 rbtn_rotate_left(a_type, a_field, pathp->node, \
725 pathp->node = tnode; \
730 rbtn_right_set(a_type, a_field, pathp->node, \
732 left = rbtn_left_get(a_type, a_field, pathp->node); \
733 if (rbtn_red_get(a_type, a_field, left)) { \
735 a_type *leftright = rbtn_right_get(a_type, a_field, \
737 a_type *leftrightleft = rbtn_left_get(a_type, a_field, \
739 if (leftrightleft != NULL && rbtn_red_get(a_type, \
740 a_field, leftrightleft)) { \
750 rbtn_black_set(a_type, a_field, leftrightleft); \
751 rbtn_rotate_right(a_type, a_field, pathp->node, \
753 rbtn_rotate_right(a_type, a_field, pathp->node, \
755 rbtn_right_set(a_type, a_field, unode, tnode); \
756 rbtn_rotate_left(a_type, a_field, unode, tnode); \
766 assert(leftright != NULL); \
767 rbtn_red_set(a_type, a_field, leftright); \
768 rbtn_rotate_right(a_type, a_field, pathp->node, \
770 rbtn_black_set(a_type, a_field, tnode); \
772 /* Balance restored, but rotation modified subtree */\
773 /* root, which may actually be the tree root. */\
774 if (pathp == path) { \
776 rbtree->rbt_root = tnode; \
778 if (pathp[-1].cmp < 0) { \
779 rbtn_left_set(a_type, a_field, pathp[-1].node, \
782 rbtn_right_set(a_type, a_field, pathp[-1].node, \
787 } else if (rbtn_red_get(a_type, a_field, pathp->node)) { \
788 a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
789 if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
798 rbtn_black_set(a_type, a_field, pathp->node); \
799 rbtn_red_set(a_type, a_field, left); \
800 rbtn_black_set(a_type, a_field, leftleft); \
801 rbtn_rotate_right(a_type, a_field, pathp->node, \
803 /* Balance restored, but rotation modified */\
805 assert((uintptr_t)pathp > (uintptr_t)path); \
806 if (pathp[-1].cmp < 0) { \
807 rbtn_left_set(a_type, a_field, pathp[-1].node, \
810 rbtn_right_set(a_type, a_field, pathp[-1].node, \
821 rbtn_red_set(a_type, a_field, left); \
822 rbtn_black_set(a_type, a_field, pathp->node); \
823 /* Balance restored. */ \
827 a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
828 if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
837 rbtn_black_set(a_type, a_field, leftleft); \
838 rbtn_rotate_right(a_type, a_field, pathp->node, \
840 /* Balance restored, but rotation modified */\
841 /* subtree root, which may actually be the tree */\
843 if (pathp == path) { \
845 rbtree->rbt_root = tnode; \
847 if (pathp[-1].cmp < 0) { \
848 rbtn_left_set(a_type, a_field, \
849 pathp[-1].node, tnode); \
851 rbtn_right_set(a_type, a_field, \
852 pathp[-1].node, tnode); \
863 rbtn_red_set(a_type, a_field, left); \
869 rbtree->rbt_root = path->node; \
870 assert(!rbtn_red_get(a_type, a_field, rbtree->rbt_root)); \
873 a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node, \
874 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
875 if (node == NULL) { \
879 if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type, \
880 a_field, node), cb, arg)) != NULL || (ret = cb(rbtree, node, \
884 return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
885 a_field, node), cb, arg)); \
889 a_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node, \
890 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
891 int cmp = a_cmp(start, node); \
894 if ((ret = a_prefix##iter_start(rbtree, start, \
895 rbtn_left_get(a_type, a_field, node), cb, arg)) != NULL || \
896 (ret = cb(rbtree, node, arg)) != NULL) { \
899 return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
900 a_field, node), cb, arg)); \
901 } else if (cmp > 0) { \
902 return (a_prefix##iter_start(rbtree, start, \
903 rbtn_right_get(a_type, a_field, node), cb, arg)); \
906 if ((ret = cb(rbtree, node, arg)) != NULL) { \
909 return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
910 a_field, node), cb, arg)); \
914 a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \
915 a_rbt_type *, a_type *, void *), void *arg) { \
917 if (start != NULL) { \
918 ret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root, \
921 ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\
926 a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node, \
927 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
928 if (node == NULL) { \
932 if ((ret = a_prefix##reverse_iter_recurse(rbtree, \
933 rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL || \
934 (ret = cb(rbtree, node, arg)) != NULL) { \
937 return (a_prefix##reverse_iter_recurse(rbtree, \
938 rbtn_left_get(a_type, a_field, node), cb, arg)); \
942 a_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start, \
943 a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *), \
945 int cmp = a_cmp(start, node); \
948 if ((ret = a_prefix##reverse_iter_start(rbtree, start, \
949 rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL || \
950 (ret = cb(rbtree, node, arg)) != NULL) { \
953 return (a_prefix##reverse_iter_recurse(rbtree, \
954 rbtn_left_get(a_type, a_field, node), cb, arg)); \
955 } else if (cmp < 0) { \
956 return (a_prefix##reverse_iter_start(rbtree, start, \
957 rbtn_left_get(a_type, a_field, node), cb, arg)); \
960 if ((ret = cb(rbtree, node, arg)) != NULL) { \
963 return (a_prefix##reverse_iter_recurse(rbtree, \
964 rbtn_left_get(a_type, a_field, node), cb, arg)); \
968 a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \
969 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
971 if (start != NULL) { \
972 ret = a_prefix##reverse_iter_start(rbtree, start, \
973 rbtree->rbt_root, cb, arg); \
975 ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root, \
981 a_prefix##destroy_recurse(a_rbt_type *rbtree, a_type *node, void (*cb)( \
982 a_type *, void *), void *arg) { \
983 if (node == NULL) { \
986 a_prefix##destroy_recurse(rbtree, rbtn_left_get(a_type, a_field, \
988 rbtn_left_set(a_type, a_field, (node), NULL); \
989 a_prefix##destroy_recurse(rbtree, rbtn_right_get(a_type, a_field, \
991 rbtn_right_set(a_type, a_field, (node), NULL); \
997 a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \
999 a_prefix##destroy_recurse(rbtree, rbtree->rbt_root, cb, arg); \
1000 rbtree->rbt_root = NULL; \