Home | History | Annotate | Line # | Download | only in internal
      1  1.1.1.2  christos #ifndef JEMALLOC_INTERNAL_RB_H
      2  1.1.1.2  christos #define JEMALLOC_INTERNAL_RB_H
      3  1.1.1.2  christos 
      4  1.1.1.3  christos #include "jemalloc/internal/jemalloc_preamble.h"
      5  1.1.1.3  christos #include "jemalloc/internal/safety_check.h"
      6  1.1.1.3  christos 
      7      1.1  christos /*-
      8      1.1  christos  *******************************************************************************
      9      1.1  christos  *
     10      1.1  christos  * cpp macro implementation of left-leaning 2-3 red-black trees.  Parent
     11      1.1  christos  * pointers are not used, and color bits are stored in the least significant
     12      1.1  christos  * bit of right-child pointers (if RB_COMPACT is defined), thus making node
     13      1.1  christos  * linkage as compact as is possible for red-black trees.
     14      1.1  christos  *
     15      1.1  christos  * Usage:
     16      1.1  christos  *
     17      1.1  christos  *   #include <stdint.h>
     18      1.1  christos  *   #include <stdbool.h>
     19      1.1  christos  *   #define NDEBUG // (Optional, see assert(3).)
     20      1.1  christos  *   #include <assert.h>
     21      1.1  christos  *   #define RB_COMPACT // (Optional, embed color bits in right-child pointers.)
     22      1.1  christos  *   #include <rb.h>
     23      1.1  christos  *   ...
     24      1.1  christos  *
     25      1.1  christos  *******************************************************************************
     26      1.1  christos  */
     27      1.1  christos 
     28      1.1  christos #ifndef __PGI
     29  1.1.1.3  christos #	define RB_COMPACT
     30      1.1  christos #endif
     31      1.1  christos 
     32  1.1.1.2  christos /*
     33  1.1.1.2  christos  * Each node in the RB tree consumes at least 1 byte of space (for the linkage
     34  1.1.1.2  christos  * if nothing else, so there are a maximum of sizeof(void *) << 3 rb tree nodes
     35  1.1.1.2  christos  * in any process (and thus, at most sizeof(void *) << 3 nodes in any rb tree).
     36  1.1.1.2  christos  * The choice of algorithm bounds the depth of a tree to twice the binary log of
     37  1.1.1.2  christos  * the number of elements in the tree; the following bound follows.
     38  1.1.1.2  christos  */
     39  1.1.1.2  christos #define RB_MAX_DEPTH (sizeof(void *) << 4)
     40  1.1.1.2  christos 
     41  1.1.1.3  christos /* clang-format off */
     42      1.1  christos #ifdef RB_COMPACT
     43      1.1  christos /* Node structure. */
     44      1.1  christos #define rb_node(a_type)							\
     45      1.1  christos struct {								\
     46      1.1  christos     a_type *rbn_left;							\
     47      1.1  christos     a_type *rbn_right_red;						\
     48      1.1  christos }
     49      1.1  christos #else
     50      1.1  christos #define rb_node(a_type)							\
     51      1.1  christos struct {								\
     52      1.1  christos     a_type *rbn_left;							\
     53      1.1  christos     a_type *rbn_right;							\
     54      1.1  christos     bool rbn_red;							\
     55      1.1  christos }
     56      1.1  christos #endif
     57      1.1  christos 
     58      1.1  christos /* Root structure. */
     59      1.1  christos #define rb_tree(a_type)							\
     60      1.1  christos struct {								\
     61      1.1  christos     a_type *rbt_root;							\
     62      1.1  christos }
     63      1.1  christos 
     64      1.1  christos /* Left accessors. */
     65      1.1  christos #define rbtn_left_get(a_type, a_field, a_node)				\
     66      1.1  christos     ((a_node)->a_field.rbn_left)
     67      1.1  christos #define rbtn_left_set(a_type, a_field, a_node, a_left) do {		\
     68      1.1  christos     (a_node)->a_field.rbn_left = a_left;				\
     69      1.1  christos } while (0)
     70      1.1  christos 
     71      1.1  christos #ifdef RB_COMPACT
     72      1.1  christos /* Right accessors. */
     73      1.1  christos #define rbtn_right_get(a_type, a_field, a_node)				\
     74      1.1  christos     ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red)		\
     75      1.1  christos       & ((ssize_t)-2)))
     76      1.1  christos #define rbtn_right_set(a_type, a_field, a_node, a_right) do {		\
     77      1.1  christos     (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right)	\
     78      1.1  christos       | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1)));	\
     79      1.1  christos } while (0)
     80      1.1  christos 
     81      1.1  christos /* Color accessors. */
     82      1.1  christos #define rbtn_red_get(a_type, a_field, a_node)				\
     83      1.1  christos     ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red)		\
     84      1.1  christos       & ((size_t)1)))
     85      1.1  christos #define rbtn_color_set(a_type, a_field, a_node, a_red) do {		\
     86      1.1  christos     (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t)		\
     87      1.1  christos       (a_node)->a_field.rbn_right_red) & ((ssize_t)-2))			\
     88      1.1  christos       | ((ssize_t)a_red));						\
     89      1.1  christos } while (0)
     90      1.1  christos #define rbtn_red_set(a_type, a_field, a_node) do {			\
     91      1.1  christos     (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t)		\
     92      1.1  christos       (a_node)->a_field.rbn_right_red) | ((size_t)1));			\
     93      1.1  christos } while (0)
     94      1.1  christos #define rbtn_black_set(a_type, a_field, a_node) do {			\
     95      1.1  christos     (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t)		\
     96      1.1  christos       (a_node)->a_field.rbn_right_red) & ((ssize_t)-2));		\
     97      1.1  christos } while (0)
     98      1.1  christos 
     99      1.1  christos /* Node initializer. */
    100      1.1  christos #define rbt_node_new(a_type, a_field, a_rbt, a_node) do {		\
    101      1.1  christos     /* Bookkeeping bit cannot be used by node pointer. */		\
    102      1.1  christos     assert(((uintptr_t)(a_node) & 0x1) == 0);				\
    103      1.1  christos     rbtn_left_set(a_type, a_field, (a_node), NULL);	\
    104      1.1  christos     rbtn_right_set(a_type, a_field, (a_node), NULL);	\
    105      1.1  christos     rbtn_red_set(a_type, a_field, (a_node));				\
    106      1.1  christos } while (0)
    107      1.1  christos #else
    108      1.1  christos /* Right accessors. */
    109      1.1  christos #define rbtn_right_get(a_type, a_field, a_node)				\
    110      1.1  christos     ((a_node)->a_field.rbn_right)
    111      1.1  christos #define rbtn_right_set(a_type, a_field, a_node, a_right) do {		\
    112      1.1  christos     (a_node)->a_field.rbn_right = a_right;				\
    113      1.1  christos } while (0)
    114      1.1  christos 
    115      1.1  christos /* Color accessors. */
    116      1.1  christos #define rbtn_red_get(a_type, a_field, a_node)				\
    117      1.1  christos     ((a_node)->a_field.rbn_red)
    118      1.1  christos #define rbtn_color_set(a_type, a_field, a_node, a_red) do {		\
    119      1.1  christos     (a_node)->a_field.rbn_red = (a_red);				\
    120      1.1  christos } while (0)
    121      1.1  christos #define rbtn_red_set(a_type, a_field, a_node) do {			\
    122      1.1  christos     (a_node)->a_field.rbn_red = true;					\
    123      1.1  christos } while (0)
    124      1.1  christos #define rbtn_black_set(a_type, a_field, a_node) do {			\
    125      1.1  christos     (a_node)->a_field.rbn_red = false;					\
    126      1.1  christos } while (0)
    127      1.1  christos 
    128      1.1  christos /* Node initializer. */
    129      1.1  christos #define rbt_node_new(a_type, a_field, a_rbt, a_node) do {		\
    130      1.1  christos     rbtn_left_set(a_type, a_field, (a_node), NULL);	\
    131      1.1  christos     rbtn_right_set(a_type, a_field, (a_node), NULL);	\
    132      1.1  christos     rbtn_red_set(a_type, a_field, (a_node));				\
    133      1.1  christos } while (0)
    134      1.1  christos #endif
    135      1.1  christos 
    136      1.1  christos /* Tree initializer. */
    137      1.1  christos #define rb_new(a_type, a_field, a_rbt) do {				\
    138      1.1  christos     (a_rbt)->rbt_root = NULL;						\
    139      1.1  christos } while (0)
    140      1.1  christos 
    141      1.1  christos /* Internal utility macros. */
    142      1.1  christos #define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do {		\
    143      1.1  christos     (r_node) = (a_root);						\
    144      1.1  christos     if ((r_node) != NULL) {						\
    145      1.1  christos 	for (;								\
    146      1.1  christos 	  rbtn_left_get(a_type, a_field, (r_node)) != NULL;		\
    147      1.1  christos 	  (r_node) = rbtn_left_get(a_type, a_field, (r_node))) {	\
    148      1.1  christos 	}								\
    149      1.1  christos     }									\
    150      1.1  christos } while (0)
    151      1.1  christos 
    152      1.1  christos #define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do {		\
    153      1.1  christos     (r_node) = (a_root);						\
    154      1.1  christos     if ((r_node) != NULL) {						\
    155      1.1  christos 	for (; rbtn_right_get(a_type, a_field, (r_node)) != NULL;	\
    156      1.1  christos 	  (r_node) = rbtn_right_get(a_type, a_field, (r_node))) {	\
    157      1.1  christos 	}								\
    158      1.1  christos     }									\
    159      1.1  christos } while (0)
    160      1.1  christos 
    161      1.1  christos #define rbtn_rotate_left(a_type, a_field, a_node, r_node) do {		\
    162      1.1  christos     (r_node) = rbtn_right_get(a_type, a_field, (a_node));		\
    163      1.1  christos     rbtn_right_set(a_type, a_field, (a_node),				\
    164      1.1  christos       rbtn_left_get(a_type, a_field, (r_node)));			\
    165      1.1  christos     rbtn_left_set(a_type, a_field, (r_node), (a_node));			\
    166      1.1  christos } while (0)
    167      1.1  christos 
    168      1.1  christos #define rbtn_rotate_right(a_type, a_field, a_node, r_node) do {		\
    169      1.1  christos     (r_node) = rbtn_left_get(a_type, a_field, (a_node));		\
    170      1.1  christos     rbtn_left_set(a_type, a_field, (a_node),				\
    171      1.1  christos       rbtn_right_get(a_type, a_field, (r_node)));			\
    172      1.1  christos     rbtn_right_set(a_type, a_field, (r_node), (a_node));		\
    173      1.1  christos } while (0)
    174      1.1  christos 
    175  1.1.1.2  christos #define rb_summarized_only_false(...)
    176  1.1.1.2  christos #define rb_summarized_only_true(...) __VA_ARGS__
    177  1.1.1.2  christos #define rb_empty_summarize(a_node, a_lchild, a_rchild) false
    178  1.1.1.2  christos 
    179      1.1  christos /*
    180  1.1.1.2  christos  * The rb_proto() and rb_summarized_proto() macros generate function prototypes
    181  1.1.1.2  christos  * that correspond to the functions generated by an equivalently parameterized
    182  1.1.1.2  christos  * call to rb_gen() or rb_summarized_gen(), respectively.
    183      1.1  christos  */
    184      1.1  christos 
    185      1.1  christos #define rb_proto(a_attr, a_prefix, a_rbt_type, a_type)			\
    186  1.1.1.2  christos     rb_proto_impl(a_attr, a_prefix, a_rbt_type, a_type, false)
    187  1.1.1.2  christos #define rb_summarized_proto(a_attr, a_prefix, a_rbt_type, a_type)	\
    188  1.1.1.2  christos     rb_proto_impl(a_attr, a_prefix, a_rbt_type, a_type, true)
    189  1.1.1.2  christos #define rb_proto_impl(a_attr, a_prefix, a_rbt_type, a_type,		\
    190  1.1.1.2  christos     a_is_summarized)							\
    191      1.1  christos a_attr void								\
    192      1.1  christos a_prefix##new(a_rbt_type *rbtree);					\
    193      1.1  christos a_attr bool								\
    194      1.1  christos a_prefix##empty(a_rbt_type *rbtree);					\
    195      1.1  christos a_attr a_type *								\
    196      1.1  christos a_prefix##first(a_rbt_type *rbtree);					\
    197      1.1  christos a_attr a_type *								\
    198      1.1  christos a_prefix##last(a_rbt_type *rbtree);					\
    199      1.1  christos a_attr a_type *								\
    200      1.1  christos a_prefix##next(a_rbt_type *rbtree, a_type *node);			\
    201      1.1  christos a_attr a_type *								\
    202      1.1  christos a_prefix##prev(a_rbt_type *rbtree, a_type *node);			\
    203      1.1  christos a_attr a_type *								\
    204      1.1  christos a_prefix##search(a_rbt_type *rbtree, const a_type *key);		\
    205      1.1  christos a_attr a_type *								\
    206      1.1  christos a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key);		\
    207      1.1  christos a_attr a_type *								\
    208      1.1  christos a_prefix##psearch(a_rbt_type *rbtree, const a_type *key);		\
    209      1.1  christos a_attr void								\
    210      1.1  christos a_prefix##insert(a_rbt_type *rbtree, a_type *node);			\
    211      1.1  christos a_attr void								\
    212      1.1  christos a_prefix##remove(a_rbt_type *rbtree, a_type *node);			\
    213      1.1  christos a_attr a_type *								\
    214      1.1  christos a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(	\
    215      1.1  christos   a_rbt_type *, a_type *, void *), void *arg);				\
    216      1.1  christos a_attr a_type *								\
    217      1.1  christos a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,		\
    218      1.1  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg);		\
    219      1.1  christos a_attr void								\
    220      1.1  christos a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *),	\
    221  1.1.1.2  christos   void *arg);								\
    222  1.1.1.2  christos /* Extended API */							\
    223  1.1.1.2  christos rb_summarized_only_##a_is_summarized(					\
    224  1.1.1.2  christos a_attr void								\
    225  1.1.1.2  christos a_prefix##update_summaries(a_rbt_type *rbtree, a_type *node);		\
    226  1.1.1.2  christos a_attr bool								\
    227  1.1.1.2  christos a_prefix##empty_filtered(a_rbt_type *rbtree,				\
    228  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    229  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    230  1.1.1.2  christos     void *filter_ctx);							\
    231  1.1.1.2  christos a_attr a_type *								\
    232  1.1.1.2  christos a_prefix##first_filtered(a_rbt_type *rbtree,				\
    233  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    234  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    235  1.1.1.2  christos     void *filter_ctx);							\
    236  1.1.1.2  christos a_attr a_type *								\
    237  1.1.1.2  christos a_prefix##last_filtered(a_rbt_type *rbtree,				\
    238  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    239  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    240  1.1.1.2  christos     void *filter_ctx);							\
    241  1.1.1.2  christos a_attr a_type *								\
    242  1.1.1.2  christos a_prefix##next_filtered(a_rbt_type *rbtree, a_type *node,		\
    243  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    244  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    245  1.1.1.2  christos     void *filter_ctx);							\
    246  1.1.1.2  christos a_attr a_type *								\
    247  1.1.1.2  christos a_prefix##prev_filtered(a_rbt_type *rbtree, a_type *node,		\
    248  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    249  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    250  1.1.1.2  christos     void *filter_ctx);							\
    251  1.1.1.2  christos a_attr a_type *								\
    252  1.1.1.2  christos a_prefix##search_filtered(a_rbt_type *rbtree, const a_type *key,	\
    253  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    254  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    255  1.1.1.2  christos     void *filter_ctx);							\
    256  1.1.1.2  christos a_attr a_type *								\
    257  1.1.1.2  christos a_prefix##nsearch_filtered(a_rbt_type *rbtree, const a_type *key,	\
    258  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    259  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    260  1.1.1.2  christos     void *filter_ctx);							\
    261  1.1.1.2  christos a_attr a_type *								\
    262  1.1.1.2  christos a_prefix##psearch_filtered(a_rbt_type *rbtree, const a_type *key,	\
    263  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    264  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    265  1.1.1.2  christos     void *filter_ctx);							\
    266  1.1.1.2  christos a_attr a_type *								\
    267  1.1.1.2  christos a_prefix##iter_filtered(a_rbt_type *rbtree, a_type *start,		\
    268  1.1.1.2  christos     a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg,		\
    269  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    270  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    271  1.1.1.2  christos     void *filter_ctx);							\
    272  1.1.1.2  christos a_attr a_type *								\
    273  1.1.1.2  christos a_prefix##reverse_iter_filtered(a_rbt_type *rbtree, a_type *start,	\
    274  1.1.1.2  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg,		\
    275  1.1.1.2  christos     bool (*filter_node)(void *, a_type *),				\
    276  1.1.1.2  christos     bool (*filter_subtree)(void *, a_type *),				\
    277  1.1.1.2  christos     void *filter_ctx);							\
    278  1.1.1.2  christos )
    279      1.1  christos 
    280      1.1  christos /*
    281      1.1  christos  * The rb_gen() macro generates a type-specific red-black tree implementation,
    282      1.1  christos  * based on the above cpp macros.
    283      1.1  christos  * Arguments:
    284      1.1  christos  *
    285  1.1.1.2  christos  *   a_attr:
    286  1.1.1.2  christos  *     Function attribute for generated functions (ex: static).
    287  1.1.1.2  christos  *   a_prefix:
    288  1.1.1.2  christos  *     Prefix for generated functions (ex: ex_).
    289  1.1.1.2  christos  *   a_rb_type:
    290  1.1.1.2  christos  *     Type for red-black tree data structure (ex: ex_t).
    291  1.1.1.2  christos  *   a_type:
    292  1.1.1.2  christos  *     Type for red-black tree node data structure (ex: ex_node_t).
    293  1.1.1.2  christos  *   a_field:
    294  1.1.1.2  christos  *     Name of red-black tree node linkage (ex: ex_link).
    295  1.1.1.2  christos  *   a_cmp:
    296  1.1.1.2  christos  *     Node comparison function name, with the following prototype:
    297  1.1.1.2  christos  *
    298  1.1.1.2  christos  *     int a_cmp(a_type *a_node, a_type *a_other);
    299  1.1.1.2  christos  *                        ^^^^^^
    300  1.1.1.2  christos  *                        or a_key
    301  1.1.1.2  christos  *     Interpretation of comparison function return values:
    302  1.1.1.2  christos  *       -1 : a_node <  a_other
    303  1.1.1.2  christos  *        0 : a_node == a_other
    304  1.1.1.2  christos  *        1 : a_node >  a_other
    305  1.1.1.2  christos  *     In all cases, the a_node or a_key macro argument is the first argument to
    306  1.1.1.2  christos  *     the comparison function, which makes it possible to write comparison
    307  1.1.1.2  christos  *     functions that treat the first argument specially.  a_cmp must be a total
    308  1.1.1.2  christos  *     order on values inserted into the tree -- duplicates are not allowed.
    309      1.1  christos  *
    310      1.1  christos  * Assuming the following setup:
    311      1.1  christos  *
    312      1.1  christos  *   typedef struct ex_node_s ex_node_t;
    313      1.1  christos  *   struct ex_node_s {
    314      1.1  christos  *       rb_node(ex_node_t) ex_link;
    315      1.1  christos  *   };
    316      1.1  christos  *   typedef rb_tree(ex_node_t) ex_t;
    317      1.1  christos  *   rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp)
    318      1.1  christos  *
    319      1.1  christos  * The following API is generated:
    320      1.1  christos  *
    321      1.1  christos  *   static void
    322      1.1  christos  *   ex_new(ex_t *tree);
    323      1.1  christos  *       Description: Initialize a red-black tree structure.
    324      1.1  christos  *       Args:
    325      1.1  christos  *         tree: Pointer to an uninitialized red-black tree object.
    326      1.1  christos  *
    327      1.1  christos  *   static bool
    328      1.1  christos  *   ex_empty(ex_t *tree);
    329      1.1  christos  *       Description: Determine whether tree is empty.
    330      1.1  christos  *       Args:
    331      1.1  christos  *         tree: Pointer to an initialized red-black tree object.
    332      1.1  christos  *       Ret: True if tree is empty, false otherwise.
    333      1.1  christos  *
    334      1.1  christos  *   static ex_node_t *
    335      1.1  christos  *   ex_first(ex_t *tree);
    336      1.1  christos  *   static ex_node_t *
    337      1.1  christos  *   ex_last(ex_t *tree);
    338      1.1  christos  *       Description: Get the first/last node in tree.
    339      1.1  christos  *       Args:
    340      1.1  christos  *         tree: Pointer to an initialized red-black tree object.
    341      1.1  christos  *       Ret: First/last node in tree, or NULL if tree is empty.
    342      1.1  christos  *
    343      1.1  christos  *   static ex_node_t *
    344      1.1  christos  *   ex_next(ex_t *tree, ex_node_t *node);
    345      1.1  christos  *   static ex_node_t *
    346      1.1  christos  *   ex_prev(ex_t *tree, ex_node_t *node);
    347      1.1  christos  *       Description: Get node's successor/predecessor.
    348      1.1  christos  *       Args:
    349      1.1  christos  *         tree: Pointer to an initialized red-black tree object.
    350      1.1  christos  *         node: A node in tree.
    351      1.1  christos  *       Ret: node's successor/predecessor in tree, or NULL if node is
    352      1.1  christos  *            last/first.
    353      1.1  christos  *
    354      1.1  christos  *   static ex_node_t *
    355      1.1  christos  *   ex_search(ex_t *tree, const ex_node_t *key);
    356      1.1  christos  *       Description: Search for node that matches key.
    357      1.1  christos  *       Args:
    358      1.1  christos  *         tree: Pointer to an initialized red-black tree object.
    359      1.1  christos  *         key : Search key.
    360      1.1  christos  *       Ret: Node in tree that matches key, or NULL if no match.
    361      1.1  christos  *
    362      1.1  christos  *   static ex_node_t *
    363      1.1  christos  *   ex_nsearch(ex_t *tree, const ex_node_t *key);
    364      1.1  christos  *   static ex_node_t *
    365      1.1  christos  *   ex_psearch(ex_t *tree, const ex_node_t *key);
    366      1.1  christos  *       Description: Search for node that matches key.  If no match is found,
    367      1.1  christos  *                    return what would be key's successor/predecessor, were
    368      1.1  christos  *                    key in tree.
    369      1.1  christos  *       Args:
    370      1.1  christos  *         tree: Pointer to an initialized red-black tree object.
    371      1.1  christos  *         key : Search key.
    372      1.1  christos  *       Ret: Node in tree that matches key, or if no match, hypothetical node's
    373      1.1  christos  *            successor/predecessor (NULL if no successor/predecessor).
    374      1.1  christos  *
    375      1.1  christos  *   static void
    376      1.1  christos  *   ex_insert(ex_t *tree, ex_node_t *node);
    377      1.1  christos  *       Description: Insert node into tree.
    378      1.1  christos  *       Args:
    379      1.1  christos  *         tree: Pointer to an initialized red-black tree object.
    380      1.1  christos  *         node: Node to be inserted into tree.
    381      1.1  christos  *
    382      1.1  christos  *   static void
    383      1.1  christos  *   ex_remove(ex_t *tree, ex_node_t *node);
    384      1.1  christos  *       Description: Remove node from tree.
    385      1.1  christos  *       Args:
    386      1.1  christos  *         tree: Pointer to an initialized red-black tree object.
    387      1.1  christos  *         node: Node in tree to be removed.
    388      1.1  christos  *
    389      1.1  christos  *   static ex_node_t *
    390      1.1  christos  *   ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,
    391      1.1  christos  *     ex_node_t *, void *), void *arg);
    392      1.1  christos  *   static ex_node_t *
    393      1.1  christos  *   ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,
    394      1.1  christos  *     ex_node_t *, void *), void *arg);
    395      1.1  christos  *       Description: Iterate forward/backward over tree, starting at node.  If
    396      1.1  christos  *                    tree is modified, iteration must be immediately
    397      1.1  christos  *                    terminated by the callback function that causes the
    398      1.1  christos  *                    modification.
    399      1.1  christos  *       Args:
    400      1.1  christos  *         tree : Pointer to an initialized red-black tree object.
    401      1.1  christos  *         start: Node at which to start iteration, or NULL to start at
    402      1.1  christos  *                first/last node.
    403      1.1  christos  *         cb   : Callback function, which is called for each node during
    404      1.1  christos  *                iteration.  Under normal circumstances the callback function
    405      1.1  christos  *                should return NULL, which causes iteration to continue.  If a
    406      1.1  christos  *                callback function returns non-NULL, iteration is immediately
    407      1.1  christos  *                terminated and the non-NULL return value is returned by the
    408      1.1  christos  *                iterator.  This is useful for re-starting iteration after
    409      1.1  christos  *                modifying tree.
    410      1.1  christos  *         arg  : Opaque pointer passed to cb().
    411      1.1  christos  *       Ret: NULL if iteration completed, or the non-NULL callback return value
    412      1.1  christos  *            that caused termination of the iteration.
    413      1.1  christos  *
    414      1.1  christos  *   static void
    415      1.1  christos  *   ex_destroy(ex_t *tree, void (*cb)(ex_node_t *, void *), void *arg);
    416      1.1  christos  *       Description: Iterate over the tree with post-order traversal, remove
    417      1.1  christos  *                    each node, and run the callback if non-null.  This is
    418      1.1  christos  *                    used for destroying a tree without paying the cost to
    419      1.1  christos  *                    rebalance it.  The tree must not be otherwise altered
    420      1.1  christos  *                    during traversal.
    421      1.1  christos  *       Args:
    422      1.1  christos  *         tree: Pointer to an initialized red-black tree object.
    423      1.1  christos  *         cb  : Callback function, which, if non-null, is called for each node
    424      1.1  christos  *               during iteration.  There is no way to stop iteration once it
    425      1.1  christos  *               has begun.
    426      1.1  christos  *         arg : Opaque pointer passed to cb().
    427  1.1.1.2  christos  *
    428  1.1.1.2  christos  * The rb_summarized_gen() macro generates all the functions above, but has an
    429  1.1.1.2  christos  * expanded interface.  In introduces the notion of summarizing subtrees, and of
    430  1.1.1.2  christos  * filtering searches in the tree according to the information contained in
    431  1.1.1.2  christos  * those summaries.
    432  1.1.1.2  christos  * The extra macro argument is:
    433  1.1.1.2  christos  *   a_summarize:
    434  1.1.1.2  christos  *     Tree summarization function name, with the following prototype:
    435  1.1.1.2  christos  *
    436  1.1.1.2  christos  *     bool a_summarize(a_type *a_node, const a_type *a_left_child,
    437  1.1.1.2  christos  *         const a_type *a_right_child);
    438  1.1.1.2  christos  *
    439  1.1.1.2  christos  *     This function should update a_node with the summary of the subtree rooted
    440  1.1.1.2  christos  *     there, using the data contained in it and the summaries in a_left_child
    441  1.1.1.2  christos  *     and a_right_child.  One or both of them may be NULL.  When the tree
    442  1.1.1.2  christos  *     changes due to an insertion or removal, it updates the summaries of all
    443  1.1.1.2  christos  *     nodes whose subtrees have changed (always updating the summaries of
    444  1.1.1.2  christos  *     children before their parents).  If the user alters a node in the tree in
    445  1.1.1.2  christos  *     a way that may change its summary, they can call the generated
    446  1.1.1.2  christos  *     update_summaries function to bubble up the summary changes to the root.
    447  1.1.1.2  christos  *     It should return true if the summary changed (or may have changed), and
    448  1.1.1.2  christos  *     false if it didn't (which will allow the implementation to terminate
    449  1.1.1.2  christos  *     "bubbling up" the summaries early).
    450  1.1.1.2  christos  *     As the parameter names indicate, the children are ordered as they are in
    451  1.1.1.2  christos  *     the tree, a_left_child, if it is not NULL, compares less than a_node,
    452  1.1.1.2  christos  *     which in turn compares less than a_right_child (if a_right_child is not
    453  1.1.1.2  christos  *     NULL).
    454  1.1.1.2  christos  *
    455  1.1.1.2  christos  * Using the same setup as above but replacing the macro with
    456  1.1.1.2  christos  *   rb_summarized_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp,
    457  1.1.1.2  christos  *       ex_summarize)
    458  1.1.1.2  christos  *
    459  1.1.1.2  christos  * Generates all the previous functions, but adds some more:
    460  1.1.1.2  christos  *
    461  1.1.1.2  christos  *   static void
    462  1.1.1.2  christos  *   ex_update_summaries(ex_t *tree, ex_node_t *node);
    463  1.1.1.2  christos  *       Description: Recompute all summaries of ancestors of node.
    464  1.1.1.2  christos  *       Args:
    465  1.1.1.2  christos  *         tree: Pointer to an initialized red-black tree object.
    466  1.1.1.2  christos  *         node: The element of the tree whose summary may have changed.
    467  1.1.1.2  christos  *
    468  1.1.1.2  christos  * For each of ex_empty, ex_first, ex_last, ex_next, ex_prev, ex_search,
    469  1.1.1.2  christos  * ex_nsearch, ex_psearch, ex_iter, and ex_reverse_iter, an additional function
    470  1.1.1.2  christos  * is generated as well, with the suffix _filtered (e.g. ex_empty_filtered,
    471  1.1.1.2  christos  * ex_first_filtered, etc.).  These use the concept of a "filter"; a binary
    472  1.1.1.2  christos  * property some node either satisfies or does not satisfy.  Clever use of the
    473  1.1.1.2  christos  * a_summary argument to rb_summarized_gen can allow efficient computation of
    474  1.1.1.2  christos  * these predicates across whole subtrees of the tree.
    475  1.1.1.2  christos  * The extended API functions accept three additional arguments after the
    476  1.1.1.2  christos  * arguments to the corresponding non-extended equivalent.
    477  1.1.1.2  christos  *
    478  1.1.1.2  christos  * ex_fn(..., bool (*filter_node)(void *, ex_node_t *),
    479  1.1.1.2  christos  *     bool (*filter_subtree)(void *, ex_node_t *), void *filter_ctx);
    480  1.1.1.2  christos  *         filter_node    : Returns true if the node passes the filter.
    481  1.1.1.2  christos  *         filter_subtree : Returns true if some node in the subtree rooted at
    482  1.1.1.2  christos  *                          node passes the filter.
    483  1.1.1.2  christos  *         filter_ctx     : A context argument passed to the filters.
    484  1.1.1.2  christos  *
    485  1.1.1.2  christos  * For a more concrete example of summarizing and filtering, suppose we're using
    486  1.1.1.2  christos  * the red-black tree to track a set of integers:
    487  1.1.1.2  christos  *
    488  1.1.1.2  christos  * struct ex_node_s {
    489  1.1.1.2  christos  *     rb_node(ex_node_t) ex_link;
    490  1.1.1.2  christos  *     unsigned data;
    491  1.1.1.2  christos  * };
    492  1.1.1.2  christos  *
    493  1.1.1.2  christos  * Suppose, for some application-specific reason, we want to be able to quickly
    494  1.1.1.2  christos  * find numbers in the set which are divisible by large powers of 2 (say, for
    495  1.1.1.2  christos  * aligned allocation purposes).  We augment the node with a summary field:
    496  1.1.1.2  christos  *
    497  1.1.1.2  christos  * struct ex_node_s {
    498  1.1.1.2  christos  *     rb_node(ex_node_t) ex_link;
    499  1.1.1.2  christos  *     unsigned data;
    500  1.1.1.2  christos  *     unsigned max_subtree_ffs;
    501  1.1.1.2  christos  * }
    502  1.1.1.2  christos  *
    503  1.1.1.2  christos  * and define our summarization function as follows:
    504  1.1.1.2  christos  *
    505  1.1.1.2  christos  * bool
    506  1.1.1.2  christos  * ex_summarize(ex_node_t *node, const ex_node_t *lchild,
    507  1.1.1.2  christos  *   const ex_node_t *rchild) {
    508  1.1.1.2  christos  *     unsigned new_max_subtree_ffs = ffs(node->data);
    509  1.1.1.2  christos  *     if (lchild != NULL && lchild->max_subtree_ffs > new_max_subtree_ffs) {
    510  1.1.1.2  christos  *         new_max_subtree_ffs = lchild->max_subtree_ffs;
    511  1.1.1.2  christos  *     }
    512  1.1.1.2  christos  *     if (rchild != NULL && rchild->max_subtree_ffs > new_max_subtree_ffs) {
    513  1.1.1.2  christos  *         new_max_subtree_ffs = rchild->max_subtree_ffs;
    514  1.1.1.2  christos  *     }
    515  1.1.1.2  christos  *     bool changed = (node->max_subtree_ffs != new_max_subtree_ffs)
    516  1.1.1.2  christos  *     node->max_subtree_ffs = new_max_subtree_ffs;
    517  1.1.1.2  christos  *     // This could be "return true" without any correctness or big-O
    518  1.1.1.2  christos  *     // performance changes; but practically, precisely reporting summary
    519  1.1.1.2  christos  *     // changes reduces the amount of work that has to be done when "bubbling
    520  1.1.1.2  christos  *     // up" summary changes.
    521  1.1.1.2  christos  *     return changed;
    522  1.1.1.2  christos  * }
    523  1.1.1.2  christos  *
    524  1.1.1.2  christos  * We can now implement our filter functions as follows:
    525  1.1.1.2  christos  * bool
    526  1.1.1.2  christos  * ex_filter_node(void *filter_ctx, ex_node_t *node) {
    527  1.1.1.2  christos  *     unsigned required_ffs = *(unsigned *)filter_ctx;
    528  1.1.1.2  christos  *     return ffs(node->data) >= required_ffs;
    529  1.1.1.2  christos  * }
    530  1.1.1.2  christos  * bool
    531  1.1.1.2  christos  * ex_filter_subtree(void *filter_ctx, ex_node_t *node) {
    532  1.1.1.2  christos  *     unsigned required_ffs = *(unsigned *)filter_ctx;
    533  1.1.1.2  christos  *     return node->max_subtree_ffs >= required_ffs;
    534  1.1.1.2  christos  * }
    535  1.1.1.2  christos  *
    536  1.1.1.2  christos  * We can now easily search for, e.g., the smallest integer in the set that's
    537  1.1.1.2  christos  * divisible by 128:
    538  1.1.1.2  christos  * ex_node_t *
    539  1.1.1.2  christos  * find_div_128(ex_tree_t *tree) {
    540  1.1.1.2  christos  *     unsigned min_ffs = 7;
    541  1.1.1.2  christos  *     return ex_first_filtered(tree, &ex_filter_node, &ex_filter_subtree,
    542  1.1.1.2  christos  *         &min_ffs);
    543  1.1.1.2  christos  * }
    544  1.1.1.2  christos  *
    545  1.1.1.2  christos  * We could with similar ease:
    546  1.1.1.2  christos  * - Fnd the next multiple of 128 in the set that's larger than 12345 (with
    547  1.1.1.2  christos  *   ex_nsearch_filtered)
    548  1.1.1.2  christos  * - Iterate over just those multiples of 64 that are in the set (with
    549  1.1.1.2  christos  *   ex_iter_filtered)
    550  1.1.1.2  christos  * - Determine if the set contains any multiples of 1024 (with
    551  1.1.1.2  christos  *   ex_empty_filtered).
    552  1.1.1.2  christos  *
    553  1.1.1.2  christos  * Some possibly subtle API notes:
    554  1.1.1.2  christos  * - The node argument to ex_next_filtered and ex_prev_filtered need not pass
    555  1.1.1.2  christos  *   the filter; it will find the next/prev node that passes the filter.
    556  1.1.1.2  christos  * - ex_search_filtered will fail even for a node in the tree, if that node does
    557  1.1.1.2  christos  *   not pass the filter.  ex_psearch_filtered and ex_nsearch_filtered behave
    558  1.1.1.2  christos  *   similarly; they may return a node larger/smaller than the key, even if a
    559  1.1.1.2  christos  *   node equivalent to the key is in the tree (but does not pass the filter).
    560  1.1.1.2  christos  * - Similarly, if the start argument to a filtered iteration function does not
    561  1.1.1.2  christos  *   pass the filter, the callback won't be invoked on it.
    562  1.1.1.2  christos  *
    563  1.1.1.2  christos  * These should make sense after a moment's reflection; each post-condition is
    564  1.1.1.2  christos  * the same as with the unfiltered version, with the added constraint that the
    565  1.1.1.2  christos  * returned node must pass the filter.
    566      1.1  christos  */
    567  1.1.1.3  christos JEMALLOC_ALWAYS_INLINE void
    568  1.1.1.3  christos rb_remove_safety_checks(const void *nodep, const char *function_name) {
    569  1.1.1.3  christos 	if (!config_opt_safety_checks) {
    570  1.1.1.3  christos 		return;
    571  1.1.1.3  christos 	}
    572  1.1.1.3  christos 	if (unlikely(nodep == NULL)) {
    573  1.1.1.3  christos 		safety_check_fail(
    574  1.1.1.3  christos 		    "<jemalloc>: Invalid deallocation detected in %s: "
    575  1.1.1.3  christos 		    "attempting to remove node from tree but node was "
    576  1.1.1.3  christos 		    "not found. Possibly caused by double free bugs.",
    577  1.1.1.3  christos 		    function_name);
    578  1.1.1.3  christos         }
    579  1.1.1.3  christos }
    580  1.1.1.3  christos 
    581      1.1  christos #define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp)	\
    582  1.1.1.2  christos     rb_gen_impl(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp,	\
    583  1.1.1.2  christos 	rb_empty_summarize, false)
    584  1.1.1.2  christos #define rb_summarized_gen(a_attr, a_prefix, a_rbt_type, a_type,		\
    585  1.1.1.2  christos     a_field, a_cmp, a_summarize)					\
    586  1.1.1.2  christos     rb_gen_impl(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp,	\
    587  1.1.1.2  christos 	a_summarize, true)
    588  1.1.1.2  christos 
    589  1.1.1.2  christos #define rb_gen_impl(a_attr, a_prefix, a_rbt_type, a_type,		\
    590  1.1.1.2  christos     a_field, a_cmp, a_summarize, a_is_summarized)			\
    591  1.1.1.2  christos typedef struct {							\
    592  1.1.1.2  christos     a_type *node;							\
    593  1.1.1.2  christos     int cmp;								\
    594  1.1.1.2  christos } a_prefix##path_entry_t;						\
    595  1.1.1.2  christos static inline void							\
    596  1.1.1.2  christos a_prefix##summarize_range(a_prefix##path_entry_t *rfirst,		\
    597  1.1.1.2  christos     a_prefix##path_entry_t *rlast) {					\
    598  1.1.1.2  christos     while ((uintptr_t)rlast >= (uintptr_t)rfirst) {			\
    599  1.1.1.2  christos 	a_type *node = rlast->node;					\
    600  1.1.1.2  christos 	/* Avoid a warning when a_summarize is rb_empty_summarize. */	\
    601  1.1.1.2  christos 	(void)node;							\
    602  1.1.1.2  christos 	bool changed = a_summarize(node, rbtn_left_get(a_type, a_field,	\
    603  1.1.1.2  christos 	    node), rbtn_right_get(a_type, a_field, node));		\
    604  1.1.1.2  christos 	if (!changed) {							\
    605  1.1.1.2  christos 		break;							\
    606  1.1.1.2  christos 	}								\
    607  1.1.1.2  christos 	rlast--;							\
    608  1.1.1.2  christos     }									\
    609  1.1.1.2  christos }									\
    610  1.1.1.2  christos /* On the remove pathways, we sometimes swap the node being removed   */\
    611  1.1.1.2  christos /* and its first successor; in such cases we need to do two range     */\
    612  1.1.1.2  christos /* updates; one from the node to its (former) swapped successor, the  */\
    613  1.1.1.2  christos /* next from that successor to the root (with either allowed to       */\
    614  1.1.1.2  christos /* bail out early if appropriate.                                     */\
    615  1.1.1.2  christos static inline void							\
    616  1.1.1.2  christos a_prefix##summarize_swapped_range(a_prefix##path_entry_t *rfirst,	\
    617  1.1.1.2  christos     a_prefix##path_entry_t *rlast, a_prefix##path_entry_t *swap_loc) {	\
    618  1.1.1.2  christos 	if (swap_loc == NULL || rlast <= swap_loc) {			\
    619  1.1.1.2  christos 		a_prefix##summarize_range(rfirst, rlast);		\
    620  1.1.1.2  christos 	} else {							\
    621  1.1.1.2  christos 		a_prefix##summarize_range(swap_loc + 1, rlast);		\
    622  1.1.1.2  christos 		(void)a_summarize(swap_loc->node,			\
    623  1.1.1.2  christos 		    rbtn_left_get(a_type, a_field, swap_loc->node),	\
    624  1.1.1.2  christos 		    rbtn_right_get(a_type, a_field, swap_loc->node));	\
    625  1.1.1.2  christos 		a_prefix##summarize_range(rfirst, swap_loc - 1);	\
    626  1.1.1.2  christos 	}								\
    627  1.1.1.2  christos }									\
    628      1.1  christos a_attr void								\
    629      1.1  christos a_prefix##new(a_rbt_type *rbtree) {					\
    630      1.1  christos     rb_new(a_type, a_field, rbtree);					\
    631      1.1  christos }									\
    632      1.1  christos a_attr bool								\
    633      1.1  christos a_prefix##empty(a_rbt_type *rbtree) {					\
    634      1.1  christos     return (rbtree->rbt_root == NULL);					\
    635      1.1  christos }									\
    636      1.1  christos a_attr a_type *								\
    637      1.1  christos a_prefix##first(a_rbt_type *rbtree) {					\
    638      1.1  christos     a_type *ret;							\
    639      1.1  christos     rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret);		\
    640      1.1  christos     return ret;								\
    641      1.1  christos }									\
    642      1.1  christos a_attr a_type *								\
    643      1.1  christos a_prefix##last(a_rbt_type *rbtree) {					\
    644      1.1  christos     a_type *ret;							\
    645      1.1  christos     rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret);		\
    646      1.1  christos     return ret;								\
    647      1.1  christos }									\
    648      1.1  christos a_attr a_type *								\
    649      1.1  christos a_prefix##next(a_rbt_type *rbtree, a_type *node) {			\
    650      1.1  christos     a_type *ret;							\
    651      1.1  christos     if (rbtn_right_get(a_type, a_field, node) != NULL) {		\
    652      1.1  christos 	rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type,	\
    653      1.1  christos 	  a_field, node), ret);						\
    654      1.1  christos     } else {								\
    655      1.1  christos 	a_type *tnode = rbtree->rbt_root;				\
    656      1.1  christos 	assert(tnode != NULL);						\
    657      1.1  christos 	ret = NULL;							\
    658      1.1  christos 	while (true) {							\
    659      1.1  christos 	    int cmp = (a_cmp)(node, tnode);				\
    660      1.1  christos 	    if (cmp < 0) {						\
    661      1.1  christos 		ret = tnode;						\
    662      1.1  christos 		tnode = rbtn_left_get(a_type, a_field, tnode);		\
    663      1.1  christos 	    } else if (cmp > 0) {					\
    664      1.1  christos 		tnode = rbtn_right_get(a_type, a_field, tnode);		\
    665      1.1  christos 	    } else {							\
    666      1.1  christos 		break;							\
    667      1.1  christos 	    }								\
    668      1.1  christos 	    assert(tnode != NULL);					\
    669      1.1  christos 	}								\
    670      1.1  christos     }									\
    671      1.1  christos     return ret;								\
    672      1.1  christos }									\
    673      1.1  christos a_attr a_type *								\
    674      1.1  christos a_prefix##prev(a_rbt_type *rbtree, a_type *node) {			\
    675      1.1  christos     a_type *ret;							\
    676      1.1  christos     if (rbtn_left_get(a_type, a_field, node) != NULL) {			\
    677      1.1  christos 	rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type,	\
    678      1.1  christos 	  a_field, node), ret);						\
    679      1.1  christos     } else {								\
    680      1.1  christos 	a_type *tnode = rbtree->rbt_root;				\
    681      1.1  christos 	assert(tnode != NULL);						\
    682      1.1  christos 	ret = NULL;							\
    683      1.1  christos 	while (true) {							\
    684      1.1  christos 	    int cmp = (a_cmp)(node, tnode);				\
    685      1.1  christos 	    if (cmp < 0) {						\
    686      1.1  christos 		tnode = rbtn_left_get(a_type, a_field, tnode);		\
    687      1.1  christos 	    } else if (cmp > 0) {					\
    688      1.1  christos 		ret = tnode;						\
    689      1.1  christos 		tnode = rbtn_right_get(a_type, a_field, tnode);		\
    690      1.1  christos 	    } else {							\
    691      1.1  christos 		break;							\
    692      1.1  christos 	    }								\
    693      1.1  christos 	    assert(tnode != NULL);					\
    694      1.1  christos 	}								\
    695      1.1  christos     }									\
    696      1.1  christos     return ret;								\
    697      1.1  christos }									\
    698      1.1  christos a_attr a_type *								\
    699      1.1  christos a_prefix##search(a_rbt_type *rbtree, const a_type *key) {		\
    700      1.1  christos     a_type *ret;							\
    701      1.1  christos     int cmp;								\
    702      1.1  christos     ret = rbtree->rbt_root;						\
    703      1.1  christos     while (ret != NULL							\
    704      1.1  christos       && (cmp = (a_cmp)(key, ret)) != 0) {				\
    705      1.1  christos 	if (cmp < 0) {							\
    706      1.1  christos 	    ret = rbtn_left_get(a_type, a_field, ret);			\
    707      1.1  christos 	} else {							\
    708      1.1  christos 	    ret = rbtn_right_get(a_type, a_field, ret);			\
    709      1.1  christos 	}								\
    710      1.1  christos     }									\
    711      1.1  christos     return ret;								\
    712      1.1  christos }									\
    713      1.1  christos a_attr a_type *								\
    714      1.1  christos a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) {		\
    715      1.1  christos     a_type *ret;							\
    716      1.1  christos     a_type *tnode = rbtree->rbt_root;					\
    717      1.1  christos     ret = NULL;								\
    718      1.1  christos     while (tnode != NULL) {						\
    719      1.1  christos 	int cmp = (a_cmp)(key, tnode);					\
    720      1.1  christos 	if (cmp < 0) {							\
    721      1.1  christos 	    ret = tnode;						\
    722      1.1  christos 	    tnode = rbtn_left_get(a_type, a_field, tnode);		\
    723      1.1  christos 	} else if (cmp > 0) {						\
    724      1.1  christos 	    tnode = rbtn_right_get(a_type, a_field, tnode);		\
    725      1.1  christos 	} else {							\
    726      1.1  christos 	    ret = tnode;						\
    727      1.1  christos 	    break;							\
    728      1.1  christos 	}								\
    729      1.1  christos     }									\
    730      1.1  christos     return ret;								\
    731      1.1  christos }									\
    732      1.1  christos a_attr a_type *								\
    733      1.1  christos a_prefix##psearch(a_rbt_type *rbtree, const a_type *key) {		\
    734      1.1  christos     a_type *ret;							\
    735      1.1  christos     a_type *tnode = rbtree->rbt_root;					\
    736      1.1  christos     ret = NULL;								\
    737      1.1  christos     while (tnode != NULL) {						\
    738      1.1  christos 	int cmp = (a_cmp)(key, tnode);					\
    739      1.1  christos 	if (cmp < 0) {							\
    740      1.1  christos 	    tnode = rbtn_left_get(a_type, a_field, tnode);		\
    741      1.1  christos 	} else if (cmp > 0) {						\
    742      1.1  christos 	    ret = tnode;						\
    743      1.1  christos 	    tnode = rbtn_right_get(a_type, a_field, tnode);		\
    744      1.1  christos 	} else {							\
    745      1.1  christos 	    ret = tnode;						\
    746      1.1  christos 	    break;							\
    747      1.1  christos 	}								\
    748      1.1  christos     }									\
    749      1.1  christos     return ret;								\
    750      1.1  christos }									\
    751      1.1  christos a_attr void								\
    752      1.1  christos a_prefix##insert(a_rbt_type *rbtree, a_type *node) {			\
    753  1.1.1.2  christos     a_prefix##path_entry_t path[RB_MAX_DEPTH];			\
    754  1.1.1.2  christos     a_prefix##path_entry_t *pathp;					\
    755      1.1  christos     rbt_node_new(a_type, a_field, rbtree, node);			\
    756      1.1  christos     /* Wind. */								\
    757      1.1  christos     path->node = rbtree->rbt_root;					\
    758      1.1  christos     for (pathp = path; pathp->node != NULL; pathp++) {			\
    759      1.1  christos 	int cmp = pathp->cmp = a_cmp(node, pathp->node);		\
    760      1.1  christos 	assert(cmp != 0);						\
    761      1.1  christos 	if (cmp < 0) {							\
    762      1.1  christos 	    pathp[1].node = rbtn_left_get(a_type, a_field,		\
    763      1.1  christos 	      pathp->node);						\
    764      1.1  christos 	} else {							\
    765      1.1  christos 	    pathp[1].node = rbtn_right_get(a_type, a_field,		\
    766      1.1  christos 	      pathp->node);						\
    767      1.1  christos 	}								\
    768      1.1  christos     }									\
    769      1.1  christos     pathp->node = node;							\
    770  1.1.1.2  christos     /* A loop invariant we maintain is that all nodes with            */\
    771  1.1.1.2  christos     /* out-of-date summaries live in path[0], path[1], ..., *pathp.   */\
    772  1.1.1.2  christos     /* To maintain this, we have to summarize node, since we          */\
    773  1.1.1.2  christos     /* decrement pathp before the first iteration.                    */\
    774  1.1.1.2  christos     assert(rbtn_left_get(a_type, a_field, node) == NULL);		\
    775  1.1.1.2  christos     assert(rbtn_right_get(a_type, a_field, node) == NULL);		\
    776  1.1.1.2  christos     (void)a_summarize(node, NULL, NULL);				\
    777      1.1  christos     /* Unwind. */							\
    778      1.1  christos     for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {	\
    779      1.1  christos 	a_type *cnode = pathp->node;					\
    780      1.1  christos 	if (pathp->cmp < 0) {						\
    781      1.1  christos 	    a_type *left = pathp[1].node;				\
    782      1.1  christos 	    rbtn_left_set(a_type, a_field, cnode, left);		\
    783      1.1  christos 	    if (rbtn_red_get(a_type, a_field, left)) {			\
    784      1.1  christos 		a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
    785      1.1  christos 		if (leftleft != NULL && rbtn_red_get(a_type, a_field,	\
    786      1.1  christos 		  leftleft)) {						\
    787      1.1  christos 		    /* Fix up 4-node. */				\
    788      1.1  christos 		    a_type *tnode;					\
    789      1.1  christos 		    rbtn_black_set(a_type, a_field, leftleft);		\
    790      1.1  christos 		    rbtn_rotate_right(a_type, a_field, cnode, tnode);	\
    791  1.1.1.2  christos 		    (void)a_summarize(cnode,				\
    792  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, cnode),		\
    793  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, cnode));	\
    794      1.1  christos 		    cnode = tnode;					\
    795      1.1  christos 		}							\
    796      1.1  christos 	    } else {							\
    797  1.1.1.2  christos 		a_prefix##summarize_range(path, pathp);			\
    798      1.1  christos 		return;							\
    799      1.1  christos 	    }								\
    800      1.1  christos 	} else {							\
    801      1.1  christos 	    a_type *right = pathp[1].node;				\
    802      1.1  christos 	    rbtn_right_set(a_type, a_field, cnode, right);		\
    803      1.1  christos 	    if (rbtn_red_get(a_type, a_field, right)) {			\
    804      1.1  christos 		a_type *left = rbtn_left_get(a_type, a_field, cnode);	\
    805      1.1  christos 		if (left != NULL && rbtn_red_get(a_type, a_field,	\
    806      1.1  christos 		  left)) {						\
    807      1.1  christos 		    /* Split 4-node. */					\
    808      1.1  christos 		    rbtn_black_set(a_type, a_field, left);		\
    809      1.1  christos 		    rbtn_black_set(a_type, a_field, right);		\
    810      1.1  christos 		    rbtn_red_set(a_type, a_field, cnode);		\
    811      1.1  christos 		} else {						\
    812      1.1  christos 		    /* Lean left. */					\
    813      1.1  christos 		    a_type *tnode;					\
    814      1.1  christos 		    bool tred = rbtn_red_get(a_type, a_field, cnode);	\
    815      1.1  christos 		    rbtn_rotate_left(a_type, a_field, cnode, tnode);	\
    816      1.1  christos 		    rbtn_color_set(a_type, a_field, tnode, tred);	\
    817      1.1  christos 		    rbtn_red_set(a_type, a_field, cnode);		\
    818  1.1.1.2  christos 		    (void)a_summarize(cnode,				\
    819  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, cnode),		\
    820  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, cnode));	\
    821      1.1  christos 		    cnode = tnode;					\
    822      1.1  christos 		}							\
    823      1.1  christos 	    } else {							\
    824  1.1.1.2  christos 		a_prefix##summarize_range(path, pathp);			\
    825      1.1  christos 		return;							\
    826      1.1  christos 	    }								\
    827      1.1  christos 	}								\
    828      1.1  christos 	pathp->node = cnode;						\
    829  1.1.1.2  christos 	(void)a_summarize(cnode,					\
    830  1.1.1.2  christos 	    rbtn_left_get(a_type, a_field, cnode),			\
    831  1.1.1.2  christos 	    rbtn_right_get(a_type, a_field, cnode));			\
    832      1.1  christos     }									\
    833      1.1  christos     /* Set root, and make it black. */					\
    834      1.1  christos     rbtree->rbt_root = path->node;					\
    835      1.1  christos     rbtn_black_set(a_type, a_field, rbtree->rbt_root);			\
    836      1.1  christos }									\
    837      1.1  christos a_attr void								\
    838      1.1  christos a_prefix##remove(a_rbt_type *rbtree, a_type *node) {			\
    839  1.1.1.2  christos     a_prefix##path_entry_t path[RB_MAX_DEPTH];				\
    840  1.1.1.2  christos     a_prefix##path_entry_t *pathp;					\
    841  1.1.1.2  christos     a_prefix##path_entry_t *nodep;					\
    842  1.1.1.2  christos     a_prefix##path_entry_t *swap_loc;					\
    843  1.1.1.2  christos     /* This is a "real" sentinel -- NULL means we didn't swap the     */\
    844  1.1.1.2  christos     /* node to be pruned with one of its successors, and so           */\
    845  1.1.1.2  christos     /* summarization can terminate early whenever some summary        */\
    846  1.1.1.2  christos     /* doesn't change.                                                */\
    847  1.1.1.2  christos     swap_loc = NULL;							\
    848  1.1.1.2  christos     /* This is just to silence a compiler warning. */			\
    849  1.1.1.2  christos     nodep = NULL;							\
    850      1.1  christos     /* Wind. */								\
    851      1.1  christos     path->node = rbtree->rbt_root;					\
    852      1.1  christos     for (pathp = path; pathp->node != NULL; pathp++) {			\
    853      1.1  christos 	int cmp = pathp->cmp = a_cmp(node, pathp->node);		\
    854      1.1  christos 	if (cmp < 0) {							\
    855      1.1  christos 	    pathp[1].node = rbtn_left_get(a_type, a_field,		\
    856      1.1  christos 	      pathp->node);						\
    857      1.1  christos 	} else {							\
    858      1.1  christos 	    pathp[1].node = rbtn_right_get(a_type, a_field,		\
    859      1.1  christos 	      pathp->node);						\
    860      1.1  christos 	    if (cmp == 0) {						\
    861      1.1  christos 	        /* Find node's successor, in preparation for swap. */	\
    862      1.1  christos 		pathp->cmp = 1;						\
    863      1.1  christos 		nodep = pathp;						\
    864      1.1  christos 		for (pathp++; pathp->node != NULL; pathp++) {		\
    865      1.1  christos 		    pathp->cmp = -1;					\
    866      1.1  christos 		    pathp[1].node = rbtn_left_get(a_type, a_field,	\
    867      1.1  christos 		      pathp->node);					\
    868      1.1  christos 		}							\
    869      1.1  christos 		break;							\
    870      1.1  christos 	    }								\
    871      1.1  christos 	}								\
    872      1.1  christos     }									\
    873  1.1.1.3  christos     rb_remove_safety_checks(nodep, __func__);				\
    874  1.1.1.3  christos     assert(nodep != NULL);                                              \
    875      1.1  christos     assert(nodep->node == node);					\
    876      1.1  christos     pathp--;								\
    877      1.1  christos     if (pathp->node != node) {						\
    878      1.1  christos 	/* Swap node with its successor. */				\
    879  1.1.1.2  christos 	swap_loc = nodep;						\
    880      1.1  christos 	bool tred = rbtn_red_get(a_type, a_field, pathp->node);		\
    881      1.1  christos 	rbtn_color_set(a_type, a_field, pathp->node,			\
    882      1.1  christos 	  rbtn_red_get(a_type, a_field, node));				\
    883      1.1  christos 	rbtn_left_set(a_type, a_field, pathp->node,			\
    884      1.1  christos 	  rbtn_left_get(a_type, a_field, node));			\
    885      1.1  christos 	/* If node's successor is its right child, the following code */\
    886      1.1  christos 	/* will do the wrong thing for the right child pointer.       */\
    887      1.1  christos 	/* However, it doesn't matter, because the pointer will be    */\
    888      1.1  christos 	/* properly set when the successor is pruned.                 */\
    889      1.1  christos 	rbtn_right_set(a_type, a_field, pathp->node,			\
    890      1.1  christos 	  rbtn_right_get(a_type, a_field, node));			\
    891      1.1  christos 	rbtn_color_set(a_type, a_field, node, tred);			\
    892      1.1  christos 	/* The pruned leaf node's child pointers are never accessed   */\
    893      1.1  christos 	/* again, so don't bother setting them to nil.                */\
    894      1.1  christos 	nodep->node = pathp->node;					\
    895      1.1  christos 	pathp->node = node;						\
    896      1.1  christos 	if (nodep == path) {						\
    897      1.1  christos 	    rbtree->rbt_root = nodep->node;				\
    898      1.1  christos 	} else {							\
    899      1.1  christos 	    if (nodep[-1].cmp < 0) {					\
    900      1.1  christos 		rbtn_left_set(a_type, a_field, nodep[-1].node,		\
    901      1.1  christos 		  nodep->node);						\
    902      1.1  christos 	    } else {							\
    903      1.1  christos 		rbtn_right_set(a_type, a_field, nodep[-1].node,		\
    904      1.1  christos 		  nodep->node);						\
    905      1.1  christos 	    }								\
    906      1.1  christos 	}								\
    907      1.1  christos     } else {								\
    908      1.1  christos 	a_type *left = rbtn_left_get(a_type, a_field, node);		\
    909      1.1  christos 	if (left != NULL) {						\
    910      1.1  christos 	    /* node has no successor, but it has a left child.        */\
    911      1.1  christos 	    /* Splice node out, without losing the left child.        */\
    912      1.1  christos 	    assert(!rbtn_red_get(a_type, a_field, node));		\
    913      1.1  christos 	    assert(rbtn_red_get(a_type, a_field, left));		\
    914      1.1  christos 	    rbtn_black_set(a_type, a_field, left);			\
    915      1.1  christos 	    if (pathp == path) {					\
    916      1.1  christos 		rbtree->rbt_root = left;				\
    917  1.1.1.2  christos 		/* Nothing to summarize -- the subtree rooted at the  */\
    918  1.1.1.2  christos 		/* node's left child hasn't changed, and it's now the */\
    919  1.1.1.2  christos 		/* root.					      */\
    920      1.1  christos 	    } else {							\
    921      1.1  christos 		if (pathp[-1].cmp < 0) {				\
    922      1.1  christos 		    rbtn_left_set(a_type, a_field, pathp[-1].node,	\
    923      1.1  christos 		      left);						\
    924      1.1  christos 		} else {						\
    925      1.1  christos 		    rbtn_right_set(a_type, a_field, pathp[-1].node,	\
    926      1.1  christos 		      left);						\
    927      1.1  christos 		}							\
    928  1.1.1.2  christos 		a_prefix##summarize_swapped_range(path, &pathp[-1],	\
    929  1.1.1.2  christos 		    swap_loc);						\
    930      1.1  christos 	    }								\
    931      1.1  christos 	    return;							\
    932      1.1  christos 	} else if (pathp == path) {					\
    933      1.1  christos 	    /* The tree only contained one node. */			\
    934      1.1  christos 	    rbtree->rbt_root = NULL;					\
    935      1.1  christos 	    return;							\
    936      1.1  christos 	}								\
    937      1.1  christos     }									\
    938  1.1.1.2  christos     /* We've now established the invariant that the node has no right */\
    939  1.1.1.2  christos     /* child (well, morally; we didn't bother nulling it out if we    */\
    940  1.1.1.2  christos     /* swapped it with its successor), and that the only nodes with   */\
    941  1.1.1.2  christos     /* out-of-date summaries live in path[0], path[1], ..., pathp[-1].*/\
    942      1.1  christos     if (rbtn_red_get(a_type, a_field, pathp->node)) {			\
    943      1.1  christos 	/* Prune red node, which requires no fixup. */			\
    944      1.1  christos 	assert(pathp[-1].cmp < 0);					\
    945      1.1  christos 	rbtn_left_set(a_type, a_field, pathp[-1].node, NULL);		\
    946  1.1.1.2  christos 	a_prefix##summarize_swapped_range(path, &pathp[-1], swap_loc);	\
    947      1.1  christos 	return;								\
    948      1.1  christos     }									\
    949      1.1  christos     /* The node to be pruned is black, so unwind until balance is     */\
    950      1.1  christos     /* restored.                                                      */\
    951      1.1  christos     pathp->node = NULL;							\
    952      1.1  christos     for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {	\
    953      1.1  christos 	assert(pathp->cmp != 0);					\
    954      1.1  christos 	if (pathp->cmp < 0) {						\
    955      1.1  christos 	    rbtn_left_set(a_type, a_field, pathp->node,			\
    956      1.1  christos 	      pathp[1].node);						\
    957      1.1  christos 	    if (rbtn_red_get(a_type, a_field, pathp->node)) {		\
    958      1.1  christos 		a_type *right = rbtn_right_get(a_type, a_field,		\
    959      1.1  christos 		  pathp->node);						\
    960      1.1  christos 		a_type *rightleft = rbtn_left_get(a_type, a_field,	\
    961      1.1  christos 		  right);						\
    962      1.1  christos 		a_type *tnode;						\
    963      1.1  christos 		if (rightleft != NULL && rbtn_red_get(a_type, a_field,	\
    964      1.1  christos 		  rightleft)) {						\
    965      1.1  christos 		    /* In the following diagrams, ||, //, and \\      */\
    966      1.1  christos 		    /* indicate the path to the removed node.         */\
    967      1.1  christos 		    /*                                                */\
    968      1.1  christos 		    /*      ||                                        */\
    969      1.1  christos 		    /*    pathp(r)                                    */\
    970      1.1  christos 		    /*  //        \                                   */\
    971      1.1  christos 		    /* (b)        (b)                                 */\
    972      1.1  christos 		    /*           /                                    */\
    973      1.1  christos 		    /*          (r)                                   */\
    974      1.1  christos 		    /*                                                */\
    975      1.1  christos 		    rbtn_black_set(a_type, a_field, pathp->node);	\
    976      1.1  christos 		    rbtn_rotate_right(a_type, a_field, right, tnode);	\
    977      1.1  christos 		    rbtn_right_set(a_type, a_field, pathp->node, tnode);\
    978      1.1  christos 		    rbtn_rotate_left(a_type, a_field, pathp->node,	\
    979      1.1  christos 		      tnode);						\
    980  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
    981  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
    982  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
    983  1.1.1.2  christos 		    (void)a_summarize(right,				\
    984  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, right),		\
    985  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, right));	\
    986      1.1  christos 		} else {						\
    987      1.1  christos 		    /*      ||                                        */\
    988      1.1  christos 		    /*    pathp(r)                                    */\
    989      1.1  christos 		    /*  //        \                                   */\
    990      1.1  christos 		    /* (b)        (b)                                 */\
    991      1.1  christos 		    /*           /                                    */\
    992      1.1  christos 		    /*          (b)                                   */\
    993      1.1  christos 		    /*                                                */\
    994      1.1  christos 		    rbtn_rotate_left(a_type, a_field, pathp->node,	\
    995      1.1  christos 		      tnode);						\
    996  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
    997  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
    998  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
    999      1.1  christos 		}							\
   1000  1.1.1.2  christos 		(void)a_summarize(tnode, rbtn_left_get(a_type, a_field,	\
   1001  1.1.1.2  christos 		    tnode), rbtn_right_get(a_type, a_field, tnode));	\
   1002      1.1  christos 		/* Balance restored, but rotation modified subtree    */\
   1003      1.1  christos 		/* root.                                              */\
   1004      1.1  christos 		assert((uintptr_t)pathp > (uintptr_t)path);		\
   1005      1.1  christos 		if (pathp[-1].cmp < 0) {				\
   1006      1.1  christos 		    rbtn_left_set(a_type, a_field, pathp[-1].node,	\
   1007      1.1  christos 		      tnode);						\
   1008      1.1  christos 		} else {						\
   1009      1.1  christos 		    rbtn_right_set(a_type, a_field, pathp[-1].node,	\
   1010      1.1  christos 		      tnode);						\
   1011      1.1  christos 		}							\
   1012  1.1.1.2  christos 		a_prefix##summarize_swapped_range(path, &pathp[-1],	\
   1013  1.1.1.2  christos 		    swap_loc);						\
   1014      1.1  christos 		return;							\
   1015      1.1  christos 	    } else {							\
   1016      1.1  christos 		a_type *right = rbtn_right_get(a_type, a_field,		\
   1017      1.1  christos 		  pathp->node);						\
   1018      1.1  christos 		a_type *rightleft = rbtn_left_get(a_type, a_field,	\
   1019      1.1  christos 		  right);						\
   1020      1.1  christos 		if (rightleft != NULL && rbtn_red_get(a_type, a_field,	\
   1021      1.1  christos 		  rightleft)) {						\
   1022      1.1  christos 		    /*      ||                                        */\
   1023      1.1  christos 		    /*    pathp(b)                                    */\
   1024      1.1  christos 		    /*  //        \                                   */\
   1025      1.1  christos 		    /* (b)        (b)                                 */\
   1026      1.1  christos 		    /*           /                                    */\
   1027      1.1  christos 		    /*          (r)                                   */\
   1028      1.1  christos 		    a_type *tnode;					\
   1029      1.1  christos 		    rbtn_black_set(a_type, a_field, rightleft);		\
   1030      1.1  christos 		    rbtn_rotate_right(a_type, a_field, right, tnode);	\
   1031      1.1  christos 		    rbtn_right_set(a_type, a_field, pathp->node, tnode);\
   1032      1.1  christos 		    rbtn_rotate_left(a_type, a_field, pathp->node,	\
   1033      1.1  christos 		      tnode);						\
   1034  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
   1035  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
   1036  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
   1037  1.1.1.2  christos 		    (void)a_summarize(right,				\
   1038  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, right),		\
   1039  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, right));	\
   1040  1.1.1.2  christos 		    (void)a_summarize(tnode,				\
   1041  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, tnode),		\
   1042  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, tnode));	\
   1043      1.1  christos 		    /* Balance restored, but rotation modified        */\
   1044      1.1  christos 		    /* subtree root, which may actually be the tree   */\
   1045      1.1  christos 		    /* root.                                          */\
   1046      1.1  christos 		    if (pathp == path) {				\
   1047      1.1  christos 			/* Set root. */					\
   1048      1.1  christos 			rbtree->rbt_root = tnode;			\
   1049      1.1  christos 		    } else {						\
   1050      1.1  christos 			if (pathp[-1].cmp < 0) {			\
   1051      1.1  christos 			    rbtn_left_set(a_type, a_field,		\
   1052      1.1  christos 			      pathp[-1].node, tnode);			\
   1053      1.1  christos 			} else {					\
   1054      1.1  christos 			    rbtn_right_set(a_type, a_field,		\
   1055      1.1  christos 			      pathp[-1].node, tnode);			\
   1056      1.1  christos 			}						\
   1057  1.1.1.2  christos 			a_prefix##summarize_swapped_range(path,		\
   1058  1.1.1.2  christos 			    &pathp[-1], swap_loc);			\
   1059      1.1  christos 		    }							\
   1060      1.1  christos 		    return;						\
   1061      1.1  christos 		} else {						\
   1062      1.1  christos 		    /*      ||                                        */\
   1063      1.1  christos 		    /*    pathp(b)                                    */\
   1064      1.1  christos 		    /*  //        \                                   */\
   1065      1.1  christos 		    /* (b)        (b)                                 */\
   1066      1.1  christos 		    /*           /                                    */\
   1067      1.1  christos 		    /*          (b)                                   */\
   1068      1.1  christos 		    a_type *tnode;					\
   1069      1.1  christos 		    rbtn_red_set(a_type, a_field, pathp->node);		\
   1070      1.1  christos 		    rbtn_rotate_left(a_type, a_field, pathp->node,	\
   1071      1.1  christos 		      tnode);						\
   1072  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
   1073  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
   1074  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
   1075  1.1.1.2  christos 		    (void)a_summarize(tnode,				\
   1076  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, tnode),		\
   1077  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, tnode));	\
   1078      1.1  christos 		    pathp->node = tnode;				\
   1079      1.1  christos 		}							\
   1080      1.1  christos 	    }								\
   1081      1.1  christos 	} else {							\
   1082      1.1  christos 	    a_type *left;						\
   1083      1.1  christos 	    rbtn_right_set(a_type, a_field, pathp->node,		\
   1084      1.1  christos 	      pathp[1].node);						\
   1085      1.1  christos 	    left = rbtn_left_get(a_type, a_field, pathp->node);		\
   1086      1.1  christos 	    if (rbtn_red_get(a_type, a_field, left)) {			\
   1087      1.1  christos 		a_type *tnode;						\
   1088      1.1  christos 		a_type *leftright = rbtn_right_get(a_type, a_field,	\
   1089      1.1  christos 		  left);						\
   1090      1.1  christos 		a_type *leftrightleft = rbtn_left_get(a_type, a_field,	\
   1091      1.1  christos 		  leftright);						\
   1092      1.1  christos 		if (leftrightleft != NULL && rbtn_red_get(a_type,	\
   1093      1.1  christos 		  a_field, leftrightleft)) {				\
   1094      1.1  christos 		    /*      ||                                        */\
   1095      1.1  christos 		    /*    pathp(b)                                    */\
   1096      1.1  christos 		    /*   /        \\                                  */\
   1097      1.1  christos 		    /* (r)        (b)                                 */\
   1098      1.1  christos 		    /*   \                                            */\
   1099      1.1  christos 		    /*   (b)                                          */\
   1100      1.1  christos 		    /*   /                                            */\
   1101      1.1  christos 		    /* (r)                                            */\
   1102      1.1  christos 		    a_type *unode;					\
   1103      1.1  christos 		    rbtn_black_set(a_type, a_field, leftrightleft);	\
   1104      1.1  christos 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
   1105      1.1  christos 		      unode);						\
   1106      1.1  christos 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
   1107      1.1  christos 		      tnode);						\
   1108      1.1  christos 		    rbtn_right_set(a_type, a_field, unode, tnode);	\
   1109      1.1  christos 		    rbtn_rotate_left(a_type, a_field, unode, tnode);	\
   1110  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
   1111  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
   1112  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
   1113  1.1.1.2  christos 		    (void)a_summarize(unode,				\
   1114  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, unode),		\
   1115  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, unode));	\
   1116      1.1  christos 		} else {						\
   1117      1.1  christos 		    /*      ||                                        */\
   1118      1.1  christos 		    /*    pathp(b)                                    */\
   1119      1.1  christos 		    /*   /        \\                                  */\
   1120      1.1  christos 		    /* (r)        (b)                                 */\
   1121      1.1  christos 		    /*   \                                            */\
   1122      1.1  christos 		    /*   (b)                                          */\
   1123      1.1  christos 		    /*   /                                            */\
   1124      1.1  christos 		    /* (b)                                            */\
   1125      1.1  christos 		    assert(leftright != NULL);				\
   1126      1.1  christos 		    rbtn_red_set(a_type, a_field, leftright);		\
   1127      1.1  christos 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
   1128      1.1  christos 		      tnode);						\
   1129      1.1  christos 		    rbtn_black_set(a_type, a_field, tnode);		\
   1130  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
   1131  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
   1132  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
   1133      1.1  christos 		}							\
   1134  1.1.1.2  christos 		(void)a_summarize(tnode,				\
   1135  1.1.1.2  christos 		    rbtn_left_get(a_type, a_field, tnode),		\
   1136  1.1.1.2  christos 		    rbtn_right_get(a_type, a_field, tnode));		\
   1137      1.1  christos 		/* Balance restored, but rotation modified subtree    */\
   1138      1.1  christos 		/* root, which may actually be the tree root.         */\
   1139      1.1  christos 		if (pathp == path) {					\
   1140      1.1  christos 		    /* Set root. */					\
   1141      1.1  christos 		    rbtree->rbt_root = tnode;				\
   1142      1.1  christos 		} else {						\
   1143      1.1  christos 		    if (pathp[-1].cmp < 0) {				\
   1144      1.1  christos 			rbtn_left_set(a_type, a_field, pathp[-1].node,	\
   1145      1.1  christos 			  tnode);					\
   1146      1.1  christos 		    } else {						\
   1147      1.1  christos 			rbtn_right_set(a_type, a_field, pathp[-1].node,	\
   1148      1.1  christos 			  tnode);					\
   1149      1.1  christos 		    }							\
   1150  1.1.1.2  christos 		    a_prefix##summarize_swapped_range(path, &pathp[-1],	\
   1151  1.1.1.2  christos 			swap_loc);					\
   1152      1.1  christos 		}							\
   1153      1.1  christos 		return;							\
   1154      1.1  christos 	    } else if (rbtn_red_get(a_type, a_field, pathp->node)) {	\
   1155      1.1  christos 		a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
   1156      1.1  christos 		if (leftleft != NULL && rbtn_red_get(a_type, a_field,	\
   1157      1.1  christos 		  leftleft)) {						\
   1158      1.1  christos 		    /*        ||                                      */\
   1159      1.1  christos 		    /*      pathp(r)                                  */\
   1160      1.1  christos 		    /*     /        \\                                */\
   1161      1.1  christos 		    /*   (b)        (b)                               */\
   1162      1.1  christos 		    /*   /                                            */\
   1163      1.1  christos 		    /* (r)                                            */\
   1164      1.1  christos 		    a_type *tnode;					\
   1165      1.1  christos 		    rbtn_black_set(a_type, a_field, pathp->node);	\
   1166      1.1  christos 		    rbtn_red_set(a_type, a_field, left);		\
   1167      1.1  christos 		    rbtn_black_set(a_type, a_field, leftleft);		\
   1168      1.1  christos 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
   1169      1.1  christos 		      tnode);						\
   1170  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
   1171  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
   1172  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
   1173  1.1.1.2  christos 		    (void)a_summarize(tnode,				\
   1174  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, tnode),		\
   1175  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, tnode));	\
   1176      1.1  christos 		    /* Balance restored, but rotation modified        */\
   1177      1.1  christos 		    /* subtree root.                                  */\
   1178      1.1  christos 		    assert((uintptr_t)pathp > (uintptr_t)path);		\
   1179      1.1  christos 		    if (pathp[-1].cmp < 0) {				\
   1180      1.1  christos 			rbtn_left_set(a_type, a_field, pathp[-1].node,	\
   1181      1.1  christos 			  tnode);					\
   1182      1.1  christos 		    } else {						\
   1183      1.1  christos 			rbtn_right_set(a_type, a_field, pathp[-1].node,	\
   1184      1.1  christos 			  tnode);					\
   1185      1.1  christos 		    }							\
   1186  1.1.1.2  christos 		    a_prefix##summarize_swapped_range(path, &pathp[-1],	\
   1187  1.1.1.2  christos 			swap_loc);					\
   1188      1.1  christos 		    return;						\
   1189      1.1  christos 		} else {						\
   1190      1.1  christos 		    /*        ||                                      */\
   1191      1.1  christos 		    /*      pathp(r)                                  */\
   1192      1.1  christos 		    /*     /        \\                                */\
   1193      1.1  christos 		    /*   (b)        (b)                               */\
   1194      1.1  christos 		    /*   /                                            */\
   1195      1.1  christos 		    /* (b)                                            */\
   1196      1.1  christos 		    rbtn_red_set(a_type, a_field, left);		\
   1197      1.1  christos 		    rbtn_black_set(a_type, a_field, pathp->node);	\
   1198      1.1  christos 		    /* Balance restored. */				\
   1199  1.1.1.2  christos 		    a_prefix##summarize_swapped_range(path, pathp,	\
   1200  1.1.1.2  christos 			swap_loc);					\
   1201      1.1  christos 		    return;						\
   1202      1.1  christos 		}							\
   1203      1.1  christos 	    } else {							\
   1204      1.1  christos 		a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
   1205      1.1  christos 		if (leftleft != NULL && rbtn_red_get(a_type, a_field,	\
   1206      1.1  christos 		  leftleft)) {						\
   1207      1.1  christos 		    /*               ||                               */\
   1208      1.1  christos 		    /*             pathp(b)                           */\
   1209      1.1  christos 		    /*            /        \\                         */\
   1210      1.1  christos 		    /*          (b)        (b)                        */\
   1211      1.1  christos 		    /*          /                                     */\
   1212      1.1  christos 		    /*        (r)                                     */\
   1213      1.1  christos 		    a_type *tnode;					\
   1214      1.1  christos 		    rbtn_black_set(a_type, a_field, leftleft);		\
   1215      1.1  christos 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
   1216      1.1  christos 		      tnode);						\
   1217  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
   1218  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
   1219  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
   1220  1.1.1.2  christos 		    (void)a_summarize(tnode,				\
   1221  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, tnode),		\
   1222  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, tnode));	\
   1223      1.1  christos 		    /* Balance restored, but rotation modified        */\
   1224      1.1  christos 		    /* subtree root, which may actually be the tree   */\
   1225      1.1  christos 		    /* root.                                          */\
   1226      1.1  christos 		    if (pathp == path) {				\
   1227      1.1  christos 			/* Set root. */					\
   1228      1.1  christos 			rbtree->rbt_root = tnode;			\
   1229      1.1  christos 		    } else {						\
   1230      1.1  christos 			if (pathp[-1].cmp < 0) {			\
   1231      1.1  christos 			    rbtn_left_set(a_type, a_field,		\
   1232      1.1  christos 			      pathp[-1].node, tnode);			\
   1233      1.1  christos 			} else {					\
   1234      1.1  christos 			    rbtn_right_set(a_type, a_field,		\
   1235      1.1  christos 			      pathp[-1].node, tnode);			\
   1236      1.1  christos 			}						\
   1237  1.1.1.2  christos 		        a_prefix##summarize_swapped_range(path,		\
   1238  1.1.1.2  christos 			    &pathp[-1], swap_loc);			\
   1239      1.1  christos 		    }							\
   1240      1.1  christos 		    return;						\
   1241      1.1  christos 		} else {						\
   1242      1.1  christos 		    /*               ||                               */\
   1243      1.1  christos 		    /*             pathp(b)                           */\
   1244      1.1  christos 		    /*            /        \\                         */\
   1245      1.1  christos 		    /*          (b)        (b)                        */\
   1246      1.1  christos 		    /*          /                                     */\
   1247      1.1  christos 		    /*        (b)                                     */\
   1248      1.1  christos 		    rbtn_red_set(a_type, a_field, left);		\
   1249  1.1.1.2  christos 		    (void)a_summarize(pathp->node,			\
   1250  1.1.1.2  christos 			rbtn_left_get(a_type, a_field, pathp->node),	\
   1251  1.1.1.2  christos 			rbtn_right_get(a_type, a_field, pathp->node));	\
   1252      1.1  christos 		}							\
   1253      1.1  christos 	    }								\
   1254      1.1  christos 	}								\
   1255      1.1  christos     }									\
   1256      1.1  christos     /* Set root. */							\
   1257      1.1  christos     rbtree->rbt_root = path->node;					\
   1258      1.1  christos     assert(!rbtn_red_get(a_type, a_field, rbtree->rbt_root));		\
   1259      1.1  christos }									\
   1260      1.1  christos a_attr a_type *								\
   1261      1.1  christos a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node,		\
   1262      1.1  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {		\
   1263      1.1  christos     if (node == NULL) {							\
   1264      1.1  christos 	return NULL;							\
   1265      1.1  christos     } else {								\
   1266      1.1  christos 	a_type *ret;							\
   1267      1.1  christos 	if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type,	\
   1268      1.1  christos 	  a_field, node), cb, arg)) != NULL || (ret = cb(rbtree, node,	\
   1269      1.1  christos 	  arg)) != NULL) {						\
   1270      1.1  christos 	    return ret;							\
   1271      1.1  christos 	}								\
   1272      1.1  christos 	return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,	\
   1273      1.1  christos 	  a_field, node), cb, arg);					\
   1274      1.1  christos     }									\
   1275      1.1  christos }									\
   1276      1.1  christos a_attr a_type *								\
   1277      1.1  christos a_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node,	\
   1278      1.1  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {		\
   1279      1.1  christos     int cmp = a_cmp(start, node);					\
   1280      1.1  christos     if (cmp < 0) {							\
   1281      1.1  christos 	a_type *ret;							\
   1282      1.1  christos 	if ((ret = a_prefix##iter_start(rbtree, start,			\
   1283      1.1  christos 	  rbtn_left_get(a_type, a_field, node), cb, arg)) != NULL ||	\
   1284      1.1  christos 	  (ret = cb(rbtree, node, arg)) != NULL) {			\
   1285      1.1  christos 	    return ret;							\
   1286      1.1  christos 	}								\
   1287      1.1  christos 	return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,	\
   1288      1.1  christos 	  a_field, node), cb, arg);					\
   1289      1.1  christos     } else if (cmp > 0) {						\
   1290      1.1  christos 	return a_prefix##iter_start(rbtree, start,			\
   1291      1.1  christos 	  rbtn_right_get(a_type, a_field, node), cb, arg);		\
   1292      1.1  christos     } else {								\
   1293      1.1  christos 	a_type *ret;							\
   1294      1.1  christos 	if ((ret = cb(rbtree, node, arg)) != NULL) {			\
   1295      1.1  christos 	    return ret;							\
   1296      1.1  christos 	}								\
   1297      1.1  christos 	return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,	\
   1298      1.1  christos 	  a_field, node), cb, arg);					\
   1299      1.1  christos     }									\
   1300      1.1  christos }									\
   1301      1.1  christos a_attr a_type *								\
   1302      1.1  christos a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(	\
   1303      1.1  christos   a_rbt_type *, a_type *, void *), void *arg) {				\
   1304      1.1  christos     a_type *ret;							\
   1305      1.1  christos     if (start != NULL) {						\
   1306      1.1  christos 	ret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root,	\
   1307      1.1  christos 	  cb, arg);							\
   1308      1.1  christos     } else {								\
   1309      1.1  christos 	ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\
   1310      1.1  christos     }									\
   1311      1.1  christos     return ret;								\
   1312      1.1  christos }									\
   1313      1.1  christos a_attr a_type *								\
   1314      1.1  christos a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node,	\
   1315      1.1  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {		\
   1316      1.1  christos     if (node == NULL) {							\
   1317      1.1  christos 	return NULL;							\
   1318      1.1  christos     } else {								\
   1319      1.1  christos 	a_type *ret;							\
   1320      1.1  christos 	if ((ret = a_prefix##reverse_iter_recurse(rbtree,		\
   1321      1.1  christos 	  rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL ||	\
   1322      1.1  christos 	  (ret = cb(rbtree, node, arg)) != NULL) {			\
   1323      1.1  christos 	    return ret;							\
   1324      1.1  christos 	}								\
   1325      1.1  christos 	return a_prefix##reverse_iter_recurse(rbtree,			\
   1326      1.1  christos 	  rbtn_left_get(a_type, a_field, node), cb, arg);		\
   1327      1.1  christos     }									\
   1328      1.1  christos }									\
   1329      1.1  christos a_attr a_type *								\
   1330      1.1  christos a_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start,		\
   1331      1.1  christos   a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *),		\
   1332      1.1  christos   void *arg) {								\
   1333      1.1  christos     int cmp = a_cmp(start, node);					\
   1334      1.1  christos     if (cmp > 0) {							\
   1335      1.1  christos 	a_type *ret;							\
   1336      1.1  christos 	if ((ret = a_prefix##reverse_iter_start(rbtree, start,		\
   1337      1.1  christos 	  rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL ||	\
   1338      1.1  christos 	  (ret = cb(rbtree, node, arg)) != NULL) {			\
   1339      1.1  christos 	    return ret;							\
   1340      1.1  christos 	}								\
   1341      1.1  christos 	return a_prefix##reverse_iter_recurse(rbtree,			\
   1342      1.1  christos 	  rbtn_left_get(a_type, a_field, node), cb, arg);		\
   1343      1.1  christos     } else if (cmp < 0) {						\
   1344      1.1  christos 	return a_prefix##reverse_iter_start(rbtree, start,		\
   1345      1.1  christos 	  rbtn_left_get(a_type, a_field, node), cb, arg);		\
   1346      1.1  christos     } else {								\
   1347      1.1  christos 	a_type *ret;							\
   1348      1.1  christos 	if ((ret = cb(rbtree, node, arg)) != NULL) {			\
   1349      1.1  christos 	    return ret;							\
   1350      1.1  christos 	}								\
   1351      1.1  christos 	return a_prefix##reverse_iter_recurse(rbtree,			\
   1352      1.1  christos 	  rbtn_left_get(a_type, a_field, node), cb, arg);		\
   1353      1.1  christos     }									\
   1354      1.1  christos }									\
   1355      1.1  christos a_attr a_type *								\
   1356      1.1  christos a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,		\
   1357      1.1  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {		\
   1358      1.1  christos     a_type *ret;							\
   1359      1.1  christos     if (start != NULL) {						\
   1360      1.1  christos 	ret = a_prefix##reverse_iter_start(rbtree, start,		\
   1361      1.1  christos 	  rbtree->rbt_root, cb, arg);					\
   1362      1.1  christos     } else {								\
   1363      1.1  christos 	ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root,	\
   1364      1.1  christos 	  cb, arg);							\
   1365      1.1  christos     }									\
   1366      1.1  christos     return ret;								\
   1367      1.1  christos }									\
   1368      1.1  christos a_attr void								\
   1369      1.1  christos a_prefix##destroy_recurse(a_rbt_type *rbtree, a_type *node, void (*cb)(	\
   1370      1.1  christos   a_type *, void *), void *arg) {					\
   1371      1.1  christos     if (node == NULL) {							\
   1372      1.1  christos 	return;								\
   1373      1.1  christos     }									\
   1374      1.1  christos     a_prefix##destroy_recurse(rbtree, rbtn_left_get(a_type, a_field,	\
   1375      1.1  christos       node), cb, arg);							\
   1376      1.1  christos     rbtn_left_set(a_type, a_field, (node), NULL);			\
   1377      1.1  christos     a_prefix##destroy_recurse(rbtree, rbtn_right_get(a_type, a_field,	\
   1378      1.1  christos       node), cb, arg);							\
   1379      1.1  christos     rbtn_right_set(a_type, a_field, (node), NULL);			\
   1380      1.1  christos     if (cb) {								\
   1381      1.1  christos 	cb(node, arg);							\
   1382      1.1  christos     }									\
   1383      1.1  christos }									\
   1384      1.1  christos a_attr void								\
   1385      1.1  christos a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *),	\
   1386      1.1  christos   void *arg) {								\
   1387      1.1  christos     a_prefix##destroy_recurse(rbtree, rbtree->rbt_root, cb, arg);	\
   1388      1.1  christos     rbtree->rbt_root = NULL;						\
   1389  1.1.1.2  christos }									\
   1390  1.1.1.2  christos /* BEGIN SUMMARIZED-ONLY IMPLEMENTATION */				\
   1391  1.1.1.2  christos rb_summarized_only_##a_is_summarized(					\
   1392  1.1.1.2  christos static inline a_prefix##path_entry_t *					\
   1393  1.1.1.2  christos a_prefix##wind(a_rbt_type *rbtree,					\
   1394  1.1.1.2  christos     a_prefix##path_entry_t path[RB_MAX_DEPTH], a_type *node) {		\
   1395  1.1.1.2  christos     a_prefix##path_entry_t *pathp;					\
   1396  1.1.1.2  christos     path->node = rbtree->rbt_root;					\
   1397  1.1.1.2  christos     for (pathp = path; ; pathp++) {					\
   1398  1.1.1.2  christos 	assert((size_t)(pathp - path) < RB_MAX_DEPTH);			\
   1399  1.1.1.2  christos 	pathp->cmp = a_cmp(node, pathp->node);				\
   1400  1.1.1.2  christos 	if (pathp->cmp < 0) {						\
   1401  1.1.1.2  christos 	    pathp[1].node = rbtn_left_get(a_type, a_field,		\
   1402  1.1.1.2  christos 		pathp->node);						\
   1403  1.1.1.2  christos 	} else if (pathp->cmp == 0) {					\
   1404  1.1.1.2  christos 	    return pathp;						\
   1405  1.1.1.2  christos 	} else {							\
   1406  1.1.1.2  christos 	    pathp[1].node = rbtn_right_get(a_type, a_field,		\
   1407  1.1.1.2  christos 		pathp->node);						\
   1408  1.1.1.2  christos 	}								\
   1409  1.1.1.2  christos     }									\
   1410  1.1.1.2  christos     unreachable();							\
   1411  1.1.1.2  christos }									\
   1412  1.1.1.2  christos a_attr void								\
   1413  1.1.1.2  christos a_prefix##update_summaries(a_rbt_type *rbtree, a_type *node) {		\
   1414  1.1.1.2  christos     a_prefix##path_entry_t path[RB_MAX_DEPTH];				\
   1415  1.1.1.2  christos     a_prefix##path_entry_t *pathp = a_prefix##wind(rbtree, path, node);	\
   1416  1.1.1.2  christos     a_prefix##summarize_range(path, pathp);				\
   1417  1.1.1.2  christos }									\
   1418  1.1.1.2  christos a_attr bool								\
   1419  1.1.1.2  christos a_prefix##empty_filtered(a_rbt_type *rbtree,				\
   1420  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1421  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1422  1.1.1.2  christos   void *filter_ctx) {							\
   1423  1.1.1.2  christos     a_type *node = rbtree->rbt_root;					\
   1424  1.1.1.2  christos     return node == NULL || !filter_subtree(filter_ctx, node);		\
   1425  1.1.1.2  christos }									\
   1426  1.1.1.2  christos static inline a_type *							\
   1427  1.1.1.2  christos a_prefix##first_filtered_from_node(a_type *node,			\
   1428  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1429  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1430  1.1.1.2  christos   void *filter_ctx) {							\
   1431  1.1.1.2  christos     assert(node != NULL && filter_subtree(filter_ctx, node));		\
   1432  1.1.1.2  christos     while (true) {							\
   1433  1.1.1.2  christos 	a_type *left = rbtn_left_get(a_type, a_field, node);		\
   1434  1.1.1.2  christos 	a_type *right = rbtn_right_get(a_type, a_field, node);		\
   1435  1.1.1.2  christos 	if (left != NULL && filter_subtree(filter_ctx, left)) {		\
   1436  1.1.1.2  christos 	    node = left;						\
   1437  1.1.1.2  christos 	} else if (filter_node(filter_ctx, node)) {			\
   1438  1.1.1.2  christos 	    return node;						\
   1439  1.1.1.2  christos 	} else {							\
   1440  1.1.1.2  christos 		assert(right != NULL					\
   1441  1.1.1.2  christos 		    && filter_subtree(filter_ctx, right));		\
   1442  1.1.1.2  christos 		node = right;						\
   1443  1.1.1.2  christos 	}								\
   1444  1.1.1.2  christos     }									\
   1445  1.1.1.2  christos     unreachable();							\
   1446  1.1.1.2  christos }									\
   1447  1.1.1.2  christos a_attr a_type *								\
   1448  1.1.1.2  christos a_prefix##first_filtered(a_rbt_type *rbtree,				\
   1449  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1450  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1451  1.1.1.2  christos   void *filter_ctx) {							\
   1452  1.1.1.2  christos     a_type *node = rbtree->rbt_root;					\
   1453  1.1.1.2  christos     if (node == NULL || !filter_subtree(filter_ctx, node)) {		\
   1454  1.1.1.2  christos 	return NULL;							\
   1455  1.1.1.2  christos     }									\
   1456  1.1.1.2  christos     return a_prefix##first_filtered_from_node(node, filter_node,	\
   1457  1.1.1.2  christos 	filter_subtree, filter_ctx);					\
   1458  1.1.1.2  christos }									\
   1459  1.1.1.2  christos static inline a_type *							\
   1460  1.1.1.2  christos a_prefix##last_filtered_from_node(a_type *node,				\
   1461  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1462  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1463  1.1.1.2  christos   void *filter_ctx) {							\
   1464  1.1.1.2  christos     assert(node != NULL && filter_subtree(filter_ctx, node));		\
   1465  1.1.1.2  christos     while (true) {							\
   1466  1.1.1.2  christos 	a_type *left = rbtn_left_get(a_type, a_field, node);		\
   1467  1.1.1.2  christos 	a_type *right = rbtn_right_get(a_type, a_field, node);		\
   1468  1.1.1.2  christos 	if (right != NULL && filter_subtree(filter_ctx, right)) {	\
   1469  1.1.1.2  christos 	    node = right;						\
   1470  1.1.1.2  christos 	} else if (filter_node(filter_ctx, node)) {			\
   1471  1.1.1.2  christos 	    return node;						\
   1472  1.1.1.2  christos 	} else {							\
   1473  1.1.1.2  christos 		assert(left != NULL					\
   1474  1.1.1.2  christos 		    && filter_subtree(filter_ctx, left));		\
   1475  1.1.1.2  christos 		node = left;						\
   1476  1.1.1.2  christos 	}								\
   1477  1.1.1.2  christos     }									\
   1478  1.1.1.2  christos     unreachable();							\
   1479  1.1.1.2  christos }									\
   1480  1.1.1.2  christos a_attr a_type *								\
   1481  1.1.1.2  christos a_prefix##last_filtered(a_rbt_type *rbtree,				\
   1482  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1483  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1484  1.1.1.2  christos   void *filter_ctx) {							\
   1485  1.1.1.2  christos     a_type *node = rbtree->rbt_root;					\
   1486  1.1.1.2  christos     if (node == NULL || !filter_subtree(filter_ctx, node)) {		\
   1487  1.1.1.2  christos 	return NULL;							\
   1488  1.1.1.2  christos     }									\
   1489  1.1.1.2  christos     return a_prefix##last_filtered_from_node(node, filter_node,		\
   1490  1.1.1.2  christos 	filter_subtree, filter_ctx);					\
   1491  1.1.1.2  christos }									\
   1492  1.1.1.2  christos /* Internal implementation function.  Search for a node comparing     */\
   1493  1.1.1.2  christos /* equal to key matching the filter.  If such a node is in the tree,  */\
   1494  1.1.1.2  christos /* return it.  Additionally, the caller has the option to ask for     */\
   1495  1.1.1.2  christos /* bounds on the next / prev node in the tree passing the filter.     */\
   1496  1.1.1.2  christos /* If nextbound is true, then this function will do one of the        */\
   1497  1.1.1.2  christos /* following:                                                         */\
   1498  1.1.1.2  christos /* - Fill in *nextbound_node with the smallest node in the tree       */\
   1499  1.1.1.2  christos /*   greater than key passing the filter, and NULL-out                */\
   1500  1.1.1.2  christos /*   *nextbound_subtree.                                              */\
   1501  1.1.1.2  christos /* - Fill in *nextbound_subtree with a parent of that node which is   */\
   1502  1.1.1.2  christos /*   not a parent of the searched-for node, and NULL-out              */\
   1503  1.1.1.2  christos /*   *nextbound_node.                                                 */\
   1504  1.1.1.2  christos /* - NULL-out both *nextbound_node and *nextbound_subtree, in which   */\
   1505  1.1.1.2  christos /*   case no node greater than key but passing the filter is in the   */\
   1506  1.1.1.2  christos /*   tree.                                                            */\
   1507  1.1.1.2  christos /* The prevbound case is similar.  If the caller knows that key is in */\
   1508  1.1.1.2  christos /* the tree and that the subtree rooted at key does not contain a     */\
   1509  1.1.1.2  christos /* node satisfying the bound being searched for, then they can pass   */\
   1510  1.1.1.2  christos /* false for include_subtree, in which case we won't bother searching */\
   1511  1.1.1.2  christos /* there (risking a cache miss).                                      */\
   1512  1.1.1.2  christos /*                                                                    */\
   1513  1.1.1.2  christos /* This API is unfortunately complex; but the logic for filtered      */\
   1514  1.1.1.2  christos /* searches is very subtle, and otherwise we would have to repeat it  */\
   1515  1.1.1.2  christos /* multiple times for filtered search, nsearch, psearch, next, and    */\
   1516  1.1.1.2  christos /* prev.                                                              */\
   1517  1.1.1.2  christos static inline a_type *							\
   1518  1.1.1.2  christos a_prefix##search_with_filter_bounds(a_rbt_type *rbtree,			\
   1519  1.1.1.2  christos   const a_type *key,							\
   1520  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1521  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1522  1.1.1.2  christos   void *filter_ctx,							\
   1523  1.1.1.2  christos   bool include_subtree,							\
   1524  1.1.1.2  christos   bool nextbound, a_type **nextbound_node, a_type **nextbound_subtree,	\
   1525  1.1.1.2  christos   bool prevbound, a_type **prevbound_node, a_type **prevbound_subtree) {\
   1526  1.1.1.2  christos     if (nextbound) {							\
   1527  1.1.1.2  christos 	    *nextbound_node = NULL;					\
   1528  1.1.1.2  christos 	    *nextbound_subtree = NULL;					\
   1529  1.1.1.2  christos     }									\
   1530  1.1.1.2  christos     if (prevbound) {							\
   1531  1.1.1.2  christos 	    *prevbound_node = NULL;					\
   1532  1.1.1.2  christos 	    *prevbound_subtree = NULL;					\
   1533  1.1.1.2  christos     }									\
   1534  1.1.1.2  christos     a_type *tnode = rbtree->rbt_root;					\
   1535  1.1.1.2  christos     while (tnode != NULL && filter_subtree(filter_ctx, tnode)) {	\
   1536  1.1.1.2  christos 	int cmp = a_cmp(key, tnode);					\
   1537  1.1.1.2  christos 	a_type *tleft = rbtn_left_get(a_type, a_field, tnode);		\
   1538  1.1.1.2  christos 	a_type *tright = rbtn_right_get(a_type, a_field, tnode);	\
   1539  1.1.1.2  christos 	if (cmp < 0) {							\
   1540  1.1.1.2  christos 	    if (nextbound) {						\
   1541  1.1.1.2  christos 		if (filter_node(filter_ctx, tnode)) {			\
   1542  1.1.1.2  christos 		    *nextbound_node = tnode;				\
   1543  1.1.1.2  christos 		    *nextbound_subtree = NULL;				\
   1544  1.1.1.2  christos 		} else if (tright != NULL && filter_subtree(		\
   1545  1.1.1.2  christos 		    filter_ctx, tright)) {				\
   1546  1.1.1.2  christos 		    *nextbound_node = NULL;				\
   1547  1.1.1.2  christos 		    *nextbound_subtree = tright;			\
   1548  1.1.1.2  christos 		}							\
   1549  1.1.1.2  christos 	    }								\
   1550  1.1.1.2  christos 	    tnode = tleft;						\
   1551  1.1.1.2  christos 	} else if (cmp > 0) {						\
   1552  1.1.1.2  christos 	    if (prevbound) {						\
   1553  1.1.1.2  christos 		if (filter_node(filter_ctx, tnode)) {			\
   1554  1.1.1.2  christos 		    *prevbound_node = tnode;				\
   1555  1.1.1.2  christos 		    *prevbound_subtree = NULL;				\
   1556  1.1.1.2  christos 		} else if (tleft != NULL && filter_subtree(		\
   1557  1.1.1.2  christos 		    filter_ctx, tleft)) {				\
   1558  1.1.1.2  christos 		    *prevbound_node = NULL;				\
   1559  1.1.1.2  christos 		    *prevbound_subtree = tleft;				\
   1560  1.1.1.2  christos 		}							\
   1561  1.1.1.2  christos 	    }								\
   1562  1.1.1.2  christos 	    tnode = tright;						\
   1563  1.1.1.2  christos 	} else {							\
   1564  1.1.1.2  christos 	    if (filter_node(filter_ctx, tnode)) {			\
   1565  1.1.1.2  christos 		return tnode;						\
   1566  1.1.1.2  christos 	    }								\
   1567  1.1.1.2  christos 	    if (include_subtree) {					\
   1568  1.1.1.2  christos 		if (prevbound && tleft != NULL && filter_subtree(	\
   1569  1.1.1.2  christos 		    filter_ctx, tleft)) {				\
   1570  1.1.1.2  christos 		    *prevbound_node = NULL;				\
   1571  1.1.1.2  christos 		    *prevbound_subtree = tleft;				\
   1572  1.1.1.2  christos 		}							\
   1573  1.1.1.2  christos 		if (nextbound && tright != NULL && filter_subtree(	\
   1574  1.1.1.2  christos 		    filter_ctx, tright)) {				\
   1575  1.1.1.2  christos 		    *nextbound_node = NULL;				\
   1576  1.1.1.2  christos 		    *nextbound_subtree = tright;			\
   1577  1.1.1.2  christos 		}							\
   1578  1.1.1.2  christos 	    }								\
   1579  1.1.1.2  christos 	    return NULL;						\
   1580  1.1.1.2  christos 	}								\
   1581  1.1.1.2  christos     }									\
   1582  1.1.1.2  christos     return NULL;							\
   1583  1.1.1.2  christos }									\
   1584  1.1.1.2  christos a_attr a_type *								\
   1585  1.1.1.2  christos a_prefix##next_filtered(a_rbt_type *rbtree, a_type *node,		\
   1586  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1587  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1588  1.1.1.2  christos   void *filter_ctx) {							\
   1589  1.1.1.2  christos     a_type *nright = rbtn_right_get(a_type, a_field, node);		\
   1590  1.1.1.2  christos     if (nright != NULL && filter_subtree(filter_ctx, nright)) {		\
   1591  1.1.1.2  christos 	return a_prefix##first_filtered_from_node(nright, filter_node,	\
   1592  1.1.1.2  christos 	    filter_subtree, filter_ctx);				\
   1593  1.1.1.2  christos     }									\
   1594  1.1.1.2  christos     a_type *node_candidate;						\
   1595  1.1.1.2  christos     a_type *subtree_candidate;						\
   1596  1.1.1.2  christos     a_type *search_result = a_prefix##search_with_filter_bounds(	\
   1597  1.1.1.2  christos 	rbtree, node, filter_node, filter_subtree, filter_ctx,		\
   1598  1.1.1.2  christos 	/* include_subtree */ false,					\
   1599  1.1.1.2  christos 	/* nextbound */ true, &node_candidate, &subtree_candidate,	\
   1600  1.1.1.2  christos 	/* prevbound */ false, NULL, NULL);				\
   1601  1.1.1.2  christos     assert(node == search_result					\
   1602  1.1.1.2  christos 	|| !filter_node(filter_ctx, node));				\
   1603  1.1.1.2  christos     if (node_candidate != NULL) {					\
   1604  1.1.1.2  christos 	return node_candidate;						\
   1605  1.1.1.2  christos     }									\
   1606  1.1.1.2  christos     if (subtree_candidate != NULL) {					\
   1607  1.1.1.2  christos 	return a_prefix##first_filtered_from_node(			\
   1608  1.1.1.2  christos 	    subtree_candidate, filter_node, filter_subtree,		\
   1609  1.1.1.2  christos 	    filter_ctx);						\
   1610  1.1.1.2  christos     }									\
   1611  1.1.1.2  christos     return NULL;							\
   1612  1.1.1.2  christos }									\
   1613  1.1.1.2  christos a_attr a_type *								\
   1614  1.1.1.2  christos a_prefix##prev_filtered(a_rbt_type *rbtree, a_type *node,		\
   1615  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1616  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1617  1.1.1.2  christos   void *filter_ctx) {							\
   1618  1.1.1.2  christos     a_type *nleft = rbtn_left_get(a_type, a_field, node);		\
   1619  1.1.1.2  christos     if (nleft != NULL && filter_subtree(filter_ctx, nleft)) {		\
   1620  1.1.1.2  christos 	return a_prefix##last_filtered_from_node(nleft, filter_node,	\
   1621  1.1.1.2  christos 	    filter_subtree, filter_ctx);				\
   1622  1.1.1.2  christos     }									\
   1623  1.1.1.2  christos     a_type *node_candidate;						\
   1624  1.1.1.2  christos     a_type *subtree_candidate;						\
   1625  1.1.1.2  christos     a_type *search_result = a_prefix##search_with_filter_bounds(	\
   1626  1.1.1.2  christos 	rbtree, node, filter_node, filter_subtree, filter_ctx,		\
   1627  1.1.1.2  christos 	/* include_subtree */ false,					\
   1628  1.1.1.2  christos 	/* nextbound */ false, NULL, NULL,				\
   1629  1.1.1.2  christos 	/* prevbound */ true, &node_candidate, &subtree_candidate);	\
   1630  1.1.1.2  christos     assert(node == search_result					\
   1631  1.1.1.2  christos 	|| !filter_node(filter_ctx, node));				\
   1632  1.1.1.2  christos     if (node_candidate != NULL) {					\
   1633  1.1.1.2  christos 	return node_candidate;						\
   1634  1.1.1.2  christos     }									\
   1635  1.1.1.2  christos     if (subtree_candidate != NULL) {					\
   1636  1.1.1.2  christos 	return a_prefix##last_filtered_from_node(			\
   1637  1.1.1.2  christos 	    subtree_candidate, filter_node, filter_subtree,		\
   1638  1.1.1.2  christos 	    filter_ctx);						\
   1639  1.1.1.2  christos     }									\
   1640  1.1.1.2  christos     return NULL;							\
   1641  1.1.1.2  christos }									\
   1642  1.1.1.2  christos a_attr a_type *								\
   1643  1.1.1.2  christos a_prefix##search_filtered(a_rbt_type *rbtree, const a_type *key,	\
   1644  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1645  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1646  1.1.1.2  christos   void *filter_ctx) {							\
   1647  1.1.1.2  christos     a_type *result = a_prefix##search_with_filter_bounds(rbtree, key,	\
   1648  1.1.1.2  christos 	filter_node, filter_subtree, filter_ctx,			\
   1649  1.1.1.2  christos 	/* include_subtree */ false,					\
   1650  1.1.1.2  christos 	/* nextbound */ false, NULL, NULL,				\
   1651  1.1.1.2  christos 	/* prevbound */ false, NULL, NULL);				\
   1652  1.1.1.2  christos     return result;							\
   1653  1.1.1.2  christos }									\
   1654  1.1.1.2  christos a_attr a_type *								\
   1655  1.1.1.2  christos a_prefix##nsearch_filtered(a_rbt_type *rbtree, const a_type *key,	\
   1656  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1657  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1658  1.1.1.2  christos   void *filter_ctx) {							\
   1659  1.1.1.2  christos     a_type *node_candidate;						\
   1660  1.1.1.2  christos     a_type *subtree_candidate;						\
   1661  1.1.1.2  christos     a_type *result = a_prefix##search_with_filter_bounds(rbtree, key,	\
   1662  1.1.1.2  christos 	filter_node, filter_subtree, filter_ctx,			\
   1663  1.1.1.2  christos 	/* include_subtree */ true,					\
   1664  1.1.1.2  christos 	/* nextbound */ true, &node_candidate, &subtree_candidate,	\
   1665  1.1.1.2  christos 	/* prevbound */ false, NULL, NULL);				\
   1666  1.1.1.2  christos     if (result != NULL) {						\
   1667  1.1.1.2  christos 	return result;							\
   1668  1.1.1.2  christos     }									\
   1669  1.1.1.2  christos     if (node_candidate != NULL) {					\
   1670  1.1.1.2  christos 	return node_candidate;						\
   1671  1.1.1.2  christos     }									\
   1672  1.1.1.2  christos     if (subtree_candidate != NULL) {					\
   1673  1.1.1.2  christos 	return a_prefix##first_filtered_from_node(			\
   1674  1.1.1.2  christos 	    subtree_candidate, filter_node, filter_subtree,		\
   1675  1.1.1.2  christos 	    filter_ctx);						\
   1676  1.1.1.2  christos     }									\
   1677  1.1.1.2  christos     return NULL;							\
   1678  1.1.1.2  christos }									\
   1679  1.1.1.2  christos a_attr a_type *								\
   1680  1.1.1.2  christos a_prefix##psearch_filtered(a_rbt_type *rbtree, const a_type *key,	\
   1681  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1682  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1683  1.1.1.2  christos   void *filter_ctx) {							\
   1684  1.1.1.2  christos     a_type *node_candidate;						\
   1685  1.1.1.2  christos     a_type *subtree_candidate;						\
   1686  1.1.1.2  christos     a_type *result = a_prefix##search_with_filter_bounds(rbtree, key,	\
   1687  1.1.1.2  christos 	filter_node, filter_subtree, filter_ctx,			\
   1688  1.1.1.2  christos 	/* include_subtree */ true,					\
   1689  1.1.1.2  christos 	/* nextbound */ false, NULL, NULL,				\
   1690  1.1.1.2  christos 	/* prevbound */ true, &node_candidate, &subtree_candidate);	\
   1691  1.1.1.2  christos     if (result != NULL) {						\
   1692  1.1.1.2  christos 	return result;							\
   1693  1.1.1.2  christos     }									\
   1694  1.1.1.2  christos     if (node_candidate != NULL) {					\
   1695  1.1.1.2  christos 	return node_candidate;						\
   1696  1.1.1.2  christos     }									\
   1697  1.1.1.2  christos     if (subtree_candidate != NULL) {					\
   1698  1.1.1.2  christos 	return a_prefix##last_filtered_from_node(			\
   1699  1.1.1.2  christos 	    subtree_candidate, filter_node, filter_subtree,		\
   1700  1.1.1.2  christos 	    filter_ctx);						\
   1701  1.1.1.2  christos     }									\
   1702  1.1.1.2  christos     return NULL;							\
   1703  1.1.1.2  christos }									\
   1704  1.1.1.2  christos a_attr a_type *								\
   1705  1.1.1.2  christos a_prefix##iter_recurse_filtered(a_rbt_type *rbtree, a_type *node,	\
   1706  1.1.1.2  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg,		\
   1707  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1708  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1709  1.1.1.2  christos   void *filter_ctx) {							\
   1710  1.1.1.2  christos     if (node == NULL || !filter_subtree(filter_ctx, node)) {		\
   1711  1.1.1.2  christos 	return NULL;							\
   1712  1.1.1.2  christos     }									\
   1713  1.1.1.2  christos     a_type *ret;							\
   1714  1.1.1.2  christos     a_type *left = rbtn_left_get(a_type, a_field, node);		\
   1715  1.1.1.2  christos     a_type *right = rbtn_right_get(a_type, a_field, node);		\
   1716  1.1.1.2  christos     ret = a_prefix##iter_recurse_filtered(rbtree, left, cb, arg,	\
   1717  1.1.1.2  christos       filter_node, filter_subtree, filter_ctx);				\
   1718  1.1.1.2  christos     if (ret != NULL) {							\
   1719  1.1.1.2  christos 	return ret;							\
   1720  1.1.1.2  christos     }									\
   1721  1.1.1.2  christos     if (filter_node(filter_ctx, node)) {				\
   1722  1.1.1.2  christos 	ret = cb(rbtree, node, arg);					\
   1723  1.1.1.2  christos     }									\
   1724  1.1.1.2  christos     if (ret != NULL) {							\
   1725  1.1.1.2  christos 	return ret;							\
   1726  1.1.1.2  christos     }									\
   1727  1.1.1.2  christos     return a_prefix##iter_recurse_filtered(rbtree, right, cb, arg,	\
   1728  1.1.1.2  christos       filter_node, filter_subtree, filter_ctx);				\
   1729  1.1.1.2  christos }									\
   1730  1.1.1.2  christos a_attr a_type *								\
   1731  1.1.1.2  christos a_prefix##iter_start_filtered(a_rbt_type *rbtree, a_type *start,	\
   1732  1.1.1.2  christos   a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *),		\
   1733  1.1.1.2  christos   void *arg, bool (*filter_node)(void *, a_type *),			\
   1734  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1735  1.1.1.2  christos   void *filter_ctx) {							\
   1736  1.1.1.2  christos     if (!filter_subtree(filter_ctx, node)) {				\
   1737  1.1.1.2  christos 	return NULL;							\
   1738  1.1.1.2  christos     }									\
   1739  1.1.1.2  christos     int cmp = a_cmp(start, node);					\
   1740  1.1.1.2  christos     a_type *ret;							\
   1741  1.1.1.2  christos     a_type *left = rbtn_left_get(a_type, a_field, node);		\
   1742  1.1.1.2  christos     a_type *right = rbtn_right_get(a_type, a_field, node);		\
   1743  1.1.1.2  christos     if (cmp < 0) {							\
   1744  1.1.1.2  christos 	ret = a_prefix##iter_start_filtered(rbtree, start, left, cb,	\
   1745  1.1.1.2  christos 	    arg, filter_node, filter_subtree, filter_ctx);		\
   1746  1.1.1.2  christos 	if (ret != NULL) {						\
   1747  1.1.1.2  christos 	    return ret;							\
   1748  1.1.1.2  christos 	}								\
   1749  1.1.1.2  christos 	if (filter_node(filter_ctx, node)) {				\
   1750  1.1.1.2  christos 	    ret = cb(rbtree, node, arg);				\
   1751  1.1.1.2  christos 	    if (ret != NULL) {						\
   1752  1.1.1.2  christos 		return ret;						\
   1753  1.1.1.2  christos 	    }								\
   1754  1.1.1.2  christos 	}								\
   1755  1.1.1.2  christos 	return a_prefix##iter_recurse_filtered(rbtree, right, cb, arg,	\
   1756  1.1.1.2  christos 	    filter_node, filter_subtree, filter_ctx);			\
   1757  1.1.1.2  christos     } else if (cmp > 0) {						\
   1758  1.1.1.2  christos 	return a_prefix##iter_start_filtered(rbtree, start, right,	\
   1759  1.1.1.2  christos 	  cb, arg, filter_node, filter_subtree, filter_ctx);		\
   1760  1.1.1.2  christos     } else {								\
   1761  1.1.1.2  christos 	if (filter_node(filter_ctx, node)) {				\
   1762  1.1.1.2  christos 	    ret = cb(rbtree, node, arg);				\
   1763  1.1.1.2  christos 	    if (ret != NULL) {						\
   1764  1.1.1.2  christos 		return ret;						\
   1765  1.1.1.2  christos 	    }								\
   1766  1.1.1.2  christos 	}								\
   1767  1.1.1.2  christos 	return a_prefix##iter_recurse_filtered(rbtree, right, cb, arg,	\
   1768  1.1.1.2  christos 	  filter_node, filter_subtree, filter_ctx);			\
   1769  1.1.1.2  christos     }									\
   1770  1.1.1.2  christos }									\
   1771  1.1.1.2  christos a_attr a_type *								\
   1772  1.1.1.2  christos a_prefix##iter_filtered(a_rbt_type *rbtree, a_type *start,		\
   1773  1.1.1.2  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg,		\
   1774  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1775  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1776  1.1.1.2  christos   void *filter_ctx) {							\
   1777  1.1.1.2  christos     a_type *ret;							\
   1778  1.1.1.2  christos     if (start != NULL) {						\
   1779  1.1.1.2  christos 	ret = a_prefix##iter_start_filtered(rbtree, start,		\
   1780  1.1.1.2  christos 	    rbtree->rbt_root, cb, arg, filter_node, filter_subtree,	\
   1781  1.1.1.2  christos 	    filter_ctx);						\
   1782  1.1.1.2  christos     } else {								\
   1783  1.1.1.2  christos 	ret = a_prefix##iter_recurse_filtered(rbtree, rbtree->rbt_root,	\
   1784  1.1.1.2  christos 	    cb, arg, filter_node, filter_subtree, filter_ctx);		\
   1785  1.1.1.2  christos     }									\
   1786  1.1.1.2  christos     return ret;								\
   1787  1.1.1.2  christos }									\
   1788  1.1.1.2  christos a_attr a_type *								\
   1789  1.1.1.2  christos a_prefix##reverse_iter_recurse_filtered(a_rbt_type *rbtree,		\
   1790  1.1.1.2  christos   a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *),		\
   1791  1.1.1.2  christos   void *arg,								\
   1792  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1793  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1794  1.1.1.2  christos   void *filter_ctx) {							\
   1795  1.1.1.2  christos     if (node == NULL || !filter_subtree(filter_ctx, node)) {		\
   1796  1.1.1.2  christos 	return NULL;							\
   1797  1.1.1.2  christos     }									\
   1798  1.1.1.2  christos     a_type *ret;							\
   1799  1.1.1.2  christos     a_type *left = rbtn_left_get(a_type, a_field, node);		\
   1800  1.1.1.2  christos     a_type *right = rbtn_right_get(a_type, a_field, node);		\
   1801  1.1.1.2  christos     ret = a_prefix##reverse_iter_recurse_filtered(rbtree, right, cb,	\
   1802  1.1.1.2  christos 	arg, filter_node, filter_subtree, filter_ctx);			\
   1803  1.1.1.2  christos     if (ret != NULL) {							\
   1804  1.1.1.2  christos 	return ret;							\
   1805  1.1.1.2  christos     }									\
   1806  1.1.1.2  christos     if (filter_node(filter_ctx, node)) {				\
   1807  1.1.1.2  christos 	ret = cb(rbtree, node, arg);					\
   1808  1.1.1.2  christos     }									\
   1809  1.1.1.2  christos     if (ret != NULL) {							\
   1810  1.1.1.2  christos 	return ret;							\
   1811  1.1.1.2  christos     }									\
   1812  1.1.1.2  christos     return a_prefix##reverse_iter_recurse_filtered(rbtree, left, cb,	\
   1813  1.1.1.2  christos       arg, filter_node, filter_subtree, filter_ctx);			\
   1814  1.1.1.2  christos }									\
   1815  1.1.1.2  christos a_attr a_type *								\
   1816  1.1.1.2  christos a_prefix##reverse_iter_start_filtered(a_rbt_type *rbtree, a_type *start,\
   1817  1.1.1.2  christos   a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *),		\
   1818  1.1.1.2  christos   void *arg, bool (*filter_node)(void *, a_type *),			\
   1819  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1820  1.1.1.2  christos   void *filter_ctx) {							\
   1821  1.1.1.2  christos     if (!filter_subtree(filter_ctx, node)) {				\
   1822  1.1.1.2  christos 	return NULL;							\
   1823  1.1.1.2  christos     }									\
   1824  1.1.1.2  christos     int cmp = a_cmp(start, node);					\
   1825  1.1.1.2  christos     a_type *ret;							\
   1826  1.1.1.2  christos     a_type *left = rbtn_left_get(a_type, a_field, node);		\
   1827  1.1.1.2  christos     a_type *right = rbtn_right_get(a_type, a_field, node);		\
   1828  1.1.1.2  christos     if (cmp > 0) {							\
   1829  1.1.1.2  christos 	ret = a_prefix##reverse_iter_start_filtered(rbtree, start,	\
   1830  1.1.1.2  christos 	    right, cb, arg, filter_node, filter_subtree, filter_ctx);	\
   1831  1.1.1.2  christos 	if (ret != NULL) {						\
   1832  1.1.1.2  christos 	    return ret;							\
   1833  1.1.1.2  christos 	}								\
   1834  1.1.1.2  christos 	if (filter_node(filter_ctx, node)) {				\
   1835  1.1.1.2  christos 	    ret = cb(rbtree, node, arg);				\
   1836  1.1.1.2  christos 	    if (ret != NULL) {						\
   1837  1.1.1.2  christos 		return ret;						\
   1838  1.1.1.2  christos 	    }								\
   1839  1.1.1.2  christos 	}								\
   1840  1.1.1.2  christos 	return a_prefix##reverse_iter_recurse_filtered(rbtree, left, cb,\
   1841  1.1.1.2  christos 	    arg, filter_node, filter_subtree, filter_ctx);		\
   1842  1.1.1.2  christos     } else if (cmp < 0) {						\
   1843  1.1.1.2  christos 	return a_prefix##reverse_iter_start_filtered(rbtree, start,	\
   1844  1.1.1.2  christos 	  left, cb, arg, filter_node, filter_subtree, filter_ctx);	\
   1845  1.1.1.2  christos     } else {								\
   1846  1.1.1.2  christos 	if (filter_node(filter_ctx, node)) {				\
   1847  1.1.1.2  christos 	    ret = cb(rbtree, node, arg);				\
   1848  1.1.1.2  christos 	    if (ret != NULL) {						\
   1849  1.1.1.2  christos 		return ret;						\
   1850  1.1.1.2  christos 	    }								\
   1851  1.1.1.2  christos 	}								\
   1852  1.1.1.2  christos 	return a_prefix##reverse_iter_recurse_filtered(rbtree, left, cb,\
   1853  1.1.1.2  christos 	  arg, filter_node, filter_subtree, filter_ctx);		\
   1854  1.1.1.2  christos     }									\
   1855  1.1.1.2  christos }									\
   1856  1.1.1.2  christos a_attr a_type *								\
   1857  1.1.1.2  christos a_prefix##reverse_iter_filtered(a_rbt_type *rbtree, a_type *start,	\
   1858  1.1.1.2  christos   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg,		\
   1859  1.1.1.2  christos   bool (*filter_node)(void *, a_type *),				\
   1860  1.1.1.2  christos   bool (*filter_subtree)(void *, a_type *),				\
   1861  1.1.1.2  christos   void *filter_ctx) {							\
   1862  1.1.1.2  christos     a_type *ret;							\
   1863  1.1.1.2  christos     if (start != NULL) {						\
   1864  1.1.1.2  christos 	ret = a_prefix##reverse_iter_start_filtered(rbtree, start,	\
   1865  1.1.1.2  christos 	    rbtree->rbt_root, cb, arg, filter_node, filter_subtree,	\
   1866  1.1.1.2  christos 	    filter_ctx);						\
   1867  1.1.1.2  christos     } else {								\
   1868  1.1.1.2  christos 	ret = a_prefix##reverse_iter_recurse_filtered(rbtree,		\
   1869  1.1.1.2  christos 	    rbtree->rbt_root, cb, arg, filter_node, filter_subtree,	\
   1870  1.1.1.2  christos 	    filter_ctx);						\
   1871  1.1.1.2  christos     }									\
   1872  1.1.1.2  christos     return ret;								\
   1873  1.1.1.2  christos }									\
   1874  1.1.1.2  christos ) /* end rb_summarized_only */
   1875  1.1.1.3  christos /* clang-format on */
   1876      1.1  christos 
   1877  1.1.1.2  christos #endif /* JEMALLOC_INTERNAL_RB_H */
   1878