Index: share/man/man3/tree.3 =================================================================== --- share/man/man3/tree.3 +++ share/man/man3/tree.3 @@ -100,6 +100,7 @@ .Nm RB_REMOVE , .Nm RB_REINSERT , .Nm RB_AUGMENT +.Nm RB_UPDATE_AUGMENT .Nd "implementations of splay and rank-balanced (wavl) trees" .Sh SYNOPSIS .In sys/tree.h @@ -196,6 +197,8 @@ .Fn RB_REINSERT NAME "RB_HEAD *head" "struct TYPE *elm" .Ft "void" .Fn RB_AUGMENT NAME "struct TYPE *elm" +.Ft "void" +.Fn RB_UPDATE_AUGMENT NAME "struct TYPE *elm" .Sh DESCRIPTION These macros define data structures for different types of trees: splay trees and rank-balanced (wavl) trees. @@ -598,6 +601,17 @@ bottom of the tree up to the top. It is typically used to maintain some associative accumulation of tree elements, such as sums, minima, maxima, and the like. +.Pp +The +.Fn RB_UPDATE_AUGMENT +macro updates augmentation data of the element +.Fa elm +and its ancestors in the tree. +If RB_AUGMENT is defined by the RB user, then when an element in the +tree is changed, without changing the order of items in the tree, +invoking this function on that element restores consistency of the +augmentation state of the tree as if the element had been removed and +inserted again. .Sh EXAMPLES The following example demonstrates how to declare a rank-balanced tree holding integers. Index: sys/sys/tree.h =================================================================== --- sys/sys/tree.h +++ sys/sys/tree.h @@ -371,6 +371,14 @@ #define RB_AUGMENT(x) break #endif +#define RB_UPDATE_AUGMENT(elm, field) do { \ + __typeof(elm) tmp = elm; \ + do \ + RB_AUGMENT(tmp); \ + while ((tmp = RB_PARENT(tmp, field)) != NULL); \ + \ +} while (/*CONSTCOND*/ 0) + #define RB_SWAP_CHILD(head, out, in, field) do { \ if (RB_PARENT(out, field) == NULL) \ RB_ROOT(head) = (in); \ @@ -678,11 +686,9 @@ RB_SWAP_CHILD(head, old, elm, field); \ if (child != NULL) \ RB_SET_PARENT(child, parent, field); \ - if (parent != NULL) \ + if (parent != NULL) { \ name##_RB_REMOVE_COLOR(head, parent, child); \ - while (parent != NULL) { \ - RB_AUGMENT(parent); \ - parent = RB_PARENT(parent, field); \ + RB_UPDATE_AUGMENT(parent, field); \ } \ return (old); \ } @@ -714,10 +720,7 @@ else \ RB_RIGHT(parent, field) = elm; \ name##_RB_INSERT_COLOR(head, elm); \ - while (elm != NULL) { \ - RB_AUGMENT(elm); \ - elm = RB_PARENT(elm, field); \ - } \ + RB_UPDATE_AUGMENT(elm, field); \ return (NULL); \ }