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