For the case when RB_REMOVE requires a nontrivial

search to find the node to replace the one being removed, restructure to first
remove the replacement node and correct the parent pointers around it, and then
let the all-cases code at the end deal with the parent of the deleted node,
making it point to the replacement node. This removes one or two conditional
branches.

Reviewed by:	markj
Tested by:	pho
Differential Revision:	https://reviews.freebsd.org/D24845
This commit is contained in:
dougm 2020-05-21 05:34:02 +00:00 committed by Sebastian Huber
parent 1256d090ad
commit 9db2b54571
1 changed files with 24 additions and 28 deletions

View File

@ -562,48 +562,44 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
attr struct type * \ attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \ name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \ { \
struct type *child, *parent, *old = elm; \ struct type *child, *parent, *parent_old, *old = elm; \
int color; \ int color; \
if (RB_LEFT(elm, field) == NULL) \ parent_old = parent = RB_PARENT(elm, field); \
child = RB_RIGHT(elm, field); \ color = RB_COLOR(elm, field); \
else if (RB_RIGHT(elm, field) == NULL) \ if (RB_LEFT(elm, field) == NULL) { \
child = RB_LEFT(elm, field); \ elm = child = RB_RIGHT(elm, field); \
else { \ if (elm != NULL) \
RB_PARENT(elm, field) = parent; \
} else if (RB_RIGHT(elm, field) == NULL) { \
elm = child = RB_LEFT(elm, field); \
RB_PARENT(elm, field) = parent; \
} else { \
elm = RB_RIGHT(old, field); \ elm = RB_RIGHT(old, field); \
if ((child = RB_LEFT(elm, field)) == NULL) { \ if ((child = RB_LEFT(elm, field)) == NULL) { \
child = RB_RIGHT(elm, field); \ child = RB_RIGHT(elm, field); \
RB_RIGHT(old, field) = child; \ RB_RIGHT(old, field) = child; \
RB_PARENT(elm, field) = elm; \ parent = elm; \
} else { \ } else { \
do \ do \
elm = child; \ elm = child; \
while ((child = RB_LEFT(elm, field)) != NULL); \ while ((child = RB_LEFT(elm, field)) != NULL); \
child = RB_RIGHT(elm, field); \ child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
RB_LEFT(parent, field) = child; \
if (child != NULL) \
RB_PARENT(child, field) = parent; \
RB_PARENT(RB_RIGHT(old, field), field) = elm; \ RB_PARENT(RB_RIGHT(old, field), field) = elm; \
} \ } \
RB_PARENT(RB_LEFT(old, field), field) = elm; \ RB_PARENT(RB_LEFT(old, field), field) = elm; \
parent = RB_PARENT(old, field); \ color = RB_COLOR(elm, field); \
if (parent != NULL) { \ elm->field = old->field; \
if (RB_LEFT(parent, field) == old) \
RB_LEFT(parent, field) = elm; \
else \
RB_RIGHT(parent, field) = elm; \
} else \
RB_ROOT(head) = elm; \
} \ } \
parent = RB_PARENT(elm, field); \ if (parent_old == NULL) \
color = RB_COLOR(elm, field); \ RB_ROOT(head) = elm; \
if (child != NULL) \ else if (RB_LEFT(parent_old, field) == old) \
RB_PARENT(child, field) = parent; \ RB_LEFT(parent_old, field) = elm; \
if (parent != NULL) { \ else \
if (RB_LEFT(parent, field) == elm) \ RB_RIGHT(parent_old, field) = elm; \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
} else \
RB_ROOT(head) = child; \
if (elm != old) \
(elm)->field = (old)->field; \
if (color == RB_BLACK) \ if (color == RB_BLACK) \
name##_RB_REMOVE_COLOR(head, parent, child); \ name##_RB_REMOVE_COLOR(head, parent, child); \
while (parent != NULL) { \ while (parent != NULL) { \