1.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $ 2.\" 3.\" Copyright 2002 Niels Provos <provos@citi.umich.edu> 4.\" Copyright 2018-2019 Netflix, Inc. 5.\" All rights reserved. 6.\" 7.\" Redistribution and use in source and binary forms, with or without 8.\" modification, are permitted provided that the following conditions 9.\" are met: 10.\" 1. Redistributions of source code must retain the above copyright 11.\" notice, this list of conditions and the following disclaimer. 12.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" notice, this list of conditions and the following disclaimer in the 14.\" documentation and/or other materials provided with the distribution. 15.\" 3. All advertising materials mentioning features or use of this software 16.\" must display the following acknowledgement: 17.\" This product includes software developed by Niels Provos. 18.\" 4. The name of the author may not be used to endorse or promote products 19.\" derived from this software without specific prior written permission. 20.\" 21.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31.\" 32.\" $FreeBSD$ 33.\" 34.Dd October 14, 2019 35.Dt ARB 3 36.Os 37.Sh NAME 38.Nm ARB_PROTOTYPE , 39.Nm ARB_PROTOTYPE_STATIC , 40.Nm ARB_PROTOTYPE_INSERT , 41.Nm ARB_PROTOTYPE_INSERT_COLOR , 42.Nm ARB_PROTOTYPE_REMOVE , 43.Nm ARB_PROTOTYPE_REMOVE_COLOR , 44.Nm ARB_PROTOTYPE_FIND , 45.Nm ARB_PROTOTYPE_NFIND , 46.Nm ARB_PROTOTYPE_NEXT , 47.Nm ARB_PROTOTYPE_PREV , 48.Nm ARB_PROTOTYPE_MINMAX , 49.Nm ARB_PROTOTYPE_REINSERT , 50.Nm ARB_GENERATE , 51.Nm ARB_GENERATE_STATIC , 52.Nm ARB_GENERATE_INSERT , 53.Nm ARB_GENERATE_INSERT_COLOR , 54.Nm ARB_GENERATE_REMOVE , 55.Nm ARB_GENERATE_REMOVE_COLOR , 56.Nm ARB_GENERATE_FIND , 57.Nm ARB_GENERATE_NFIND , 58.Nm ARB_GENERATE_NEXT , 59.Nm ARB_GENERATE_PREV , 60.Nm ARB_GENERATE_MINMAX , 61.Nm ARB_GENERATE_REINSERT , 62.Nm ARB8_ENTRY , 63.Nm ARB16_ENTRY , 64.Nm ARB32_ENTRY , 65.Nm ARB8_HEAD , 66.Nm ARB16_HEAD , 67.Nm ARB32_HEAD , 68.Nm ARB_ALLOCSIZE , 69.Nm ARB_INITIALIZER , 70.Nm ARB_ROOT , 71.Nm ARB_EMPTY , 72.Nm ARB_FULL , 73.Nm ARB_CURNODES , 74.Nm ARB_MAXNODES , 75.Nm ARB_NEXT , 76.Nm ARB_PREV , 77.Nm ARB_MIN , 78.Nm ARB_MAX , 79.Nm ARB_FIND , 80.Nm ARB_NFIND , 81.Nm ARB_LEFT , 82.Nm ARB_LEFTIDX , 83.Nm ARB_RIGHT , 84.Nm ARB_RIGHTIDX , 85.Nm ARB_PARENT , 86.Nm ARB_PARENTIDX , 87.Nm ARB_GETFREE , 88.Nm ARB_FREEIDX , 89.Nm ARB_FOREACH , 90.Nm ARB_FOREACH_FROM , 91.Nm ARB_FOREACH_SAFE , 92.Nm ARB_FOREACH_REVERSE , 93.Nm ARB_FOREACH_REVERSE_FROM , 94.Nm ARB_FOREACH_REVERSE_SAFE , 95.Nm ARB_INIT , 96.Nm ARB_INSERT , 97.Nm ARB_REMOVE , 98.Nm ARB_REINSERT , 99.Nm ARB_RESET_TREE 100.Nd "array-based red-black trees" 101.Sh SYNOPSIS 102.In sys/arb.h 103.Fn ARB_PROTOTYPE NAME TYPE FIELD CMP 104.Fn ARB_PROTOTYPE_STATIC NAME TYPE FIELD CMP 105.Fn ARB_PROTOTYPE_INSERT NAME TYPE ATTR 106.Fn ARB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR 107.Fn ARB_PROTOTYPE_REMOVE NAME TYPE ATTR 108.Fn ARB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR 109.Fn ARB_PROTOTYPE_FIND NAME TYPE ATTR 110.Fn ARB_PROTOTYPE_NFIND NAME TYPE ATTR 111.Fn ARB_PROTOTYPE_NEXT NAME TYPE ATTR 112.Fn ARB_PROTOTYPE_PREV NAME TYPE ATTR 113.Fn ARB_PROTOTYPE_MINMAX NAME TYPE ATTR 114.Fn ARB_PROTOTYPE_REINSERT NAME TYPE ATTR 115.Fn ARB_GENERATE NAME TYPE FIELD CMP 116.Fn ARB_GENERATE_STATIC NAME TYPE FIELD CMP 117.Fn ARB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR 118.Fn ARB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR 119.Fn ARB_GENERATE_REMOVE NAME TYPE FIELD ATTR 120.Fn ARB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR 121.Fn ARB_GENERATE_FIND NAME TYPE FIELD CMP ATTR 122.Fn ARB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR 123.Fn ARB_GENERATE_NEXT NAME TYPE FIELD ATTR 124.Fn ARB_GENERATE_PREV NAME TYPE FIELD ATTR 125.Fn ARB_GENERATE_MINMAX NAME TYPE FIELD ATTR 126.Fn ARB_GENERATE_REINSERT NAME TYPE FIELD CMP ATTR 127.Fn ARB<8|16|32>_ENTRY 128.Fn ARB<8|16|32>_HEAD HEADNAME TYPE 129.Ft "size_t" 130.Fn ARB_ALLOCSIZE "ARB_HEAD *head" "int<8|16|32>_t maxnodes" "struct TYPE *elm" 131.Fn ARB_INITIALIZER "ARB_HEAD *head" "int<8|16|32>_t maxnodes" 132.Ft "struct TYPE *" 133.Fn ARB_ROOT "ARB_HEAD *head" 134.Ft "bool" 135.Fn ARB_EMPTY "ARB_HEAD *head" 136.Ft "bool" 137.Fn ARB_FULL "ARB_HEAD *head" 138.Ft "int<8|16|32>_t" 139.Fn ARB_CURNODES "ARB_HEAD *head" 140.Ft "int<8|16|32>_t" 141.Fn ARB_MAXNODES "ARB_HEAD *head" 142.Ft "struct TYPE *" 143.Fn ARB_NEXT NAME "ARB_HEAD *head" "struct TYPE *elm" 144.Ft "struct TYPE *" 145.Fn ARB_PREV NAME "ARB_HEAD *head" "struct TYPE *elm" 146.Ft "struct TYPE *" 147.Fn ARB_MIN NAME "ARB_HEAD *head" 148.Ft "struct TYPE *" 149.Fn ARB_MAX NAME "ARB_HEAD *head" 150.Ft "struct TYPE *" 151.Fn ARB_FIND NAME "ARB_HEAD *head" "struct TYPE *elm" 152.Ft "struct TYPE *" 153.Fn ARB_NFIND NAME "ARB_HEAD *head" "struct TYPE *elm" 154.Ft "struct TYPE *" 155.Fn ARB_LEFT "struct TYPE *elm" "ARB_ENTRY NAME" 156.Ft "int<8|16|32>_t" 157.Fn ARB_LEFTIDX "struct TYPE *elm" "ARB_ENTRY NAME" 158.Ft "struct TYPE *" 159.Fn ARB_RIGHT "struct TYPE *elm" "ARB_ENTRY NAME" 160.Ft "int<8|16|32>_t" 161.Fn ARB_RIGHTIDX "struct TYPE *elm" "ARB_ENTRY NAME" 162.Ft "struct TYPE *" 163.Fn ARB_PARENT "struct TYPE *elm" "ARB_ENTRY NAME" 164.Ft "int<8|16|32>_t" 165.Fn ARB_PARENTIDX "struct TYPE *elm" "ARB_ENTRY NAME" 166.Ft "struct TYPE *" 167.Fn ARB_GETFREE "ARB_HEAD *head" "FIELD" 168.Ft "int<8|16|32>_t" 169.Fn ARB_FREEIDX "ARB_HEAD *head" 170.Fn ARB_FOREACH VARNAME NAME "ARB_HEAD *head" 171.Fn ARB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME" 172.Fn ARB_FOREACH_SAFE "VARNAME" "NAME" "ARB_HEAD *head" "TEMP_VARNAME" 173.Fn ARB_FOREACH_REVERSE VARNAME NAME "ARB_HEAD *head" 174.Fn ARB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME" 175.Fn ARB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "ARB_HEAD *head" "TEMP_VARNAME" 176.Ft void 177.Fn ARB_INIT "struct TYPE *elm" "FIELD" "ARB_HEAD *head" "int<8|16|32>_t maxnodes" 178.Ft "struct TYPE *" 179.Fn ARB_INSERT NAME "ARB_HEAD *head" "struct TYPE *elm" 180.Ft "struct TYPE *" 181.Fn ARB_REMOVE NAME "ARB_HEAD *head" "struct TYPE *elm" 182.Ft "struct TYPE *" 183.Fn ARB_REINSERT NAME "ARB_HEAD *head" "struct TYPE *elm" 184.Ft void 185.Fn ARB_RESET_TREE "ARB_HEAD *head" NAME "int<8|16|32>_t maxnodes" 186.Sh DESCRIPTION 187These macros define data structures for and array-based red-black trees. 188They use a single, continuous chunk of memory, and are useful 189e.g., when the tree needs to be transferred between userspace and kernel. 190.Pp 191In the macro definitions, 192.Fa TYPE 193is the name tag of a user defined structure that must contain a field of type 194.Vt ARB_ENTRY , 195named 196.Fa ENTRYNAME . 197The argument 198.Fa HEADNAME 199is the name tag of a user defined structure that must be declared 200using the 201.Fn ARB_HEAD 202macro. 203The argument 204.Fa NAME 205has to be a unique name prefix for every tree that is defined. 206.Pp 207The function prototypes are declared with 208.Fn ARB_PROTOTYPE , 209or 210.Fn ARB_PROTOTYPE_STATIC . 211The function bodies are generated with 212.Fn ARB_GENERATE , 213or 214.Fn ARB_GENERATE_STATIC . 215See the examples below for further explanation of how these macros are used. 216.Pp 217A red-black tree is a binary search tree with the node color as an 218extra attribute. 219It fulfills a set of conditions: 220.Bl -enum -offset indent 221.It 222Every search path from the root to a leaf consists of the same number of 223black nodes. 224.It 225Each red node (except for the root) has a black parent. 226.It 227Each leaf node is black. 228.El 229.Pp 230Every operation on a red-black tree is bounded as 231.Fn O "lg n" . 232The maximum height of a red-black tree is 233.Fn 2lg "n + 1" . 234.Pp 235.Fn ARB_* 236trees require entries to be allocated as an array, and uses array 237indices to link entries together. 238The maximum number of 239.Fn ARB_* 240tree entries is therefore constrained by the minimum of array size and choice of 241signed integer data type used to store array indices. 242Use 243.Fn ARB_ALLOCSIZE 244to compute the size of memory chunk to allocate. 245.Pp 246A red-black tree is headed by a structure defined by the 247.Fn ARB_HEAD 248macro. 249A 250structure is declared with either of the following: 251.Bd -ragged -offset indent 252.Fn ARB<8|16|32>_HEAD HEADNAME TYPE 253.Va head ; 254.Ed 255.Pp 256where 257.Fa HEADNAME 258is the name of the structure to be defined, and struct 259.Fa TYPE 260is the type of the elements to be inserted into the tree. 261.Pp 262The 263.Fn ARB_HEAD 264variant includes a suffix denoting the signed integer data type size 265.Pq in bits 266used to store array indices. 267For example, 268.Fn ARB_HEAD8 269creates a red-black tree head strucutre with 8-bit signed array indices capable 270of indexing up to 128 entries. 271.Pp 272The 273.Fn ARB_ENTRY 274macro declares a structure that allows elements to be connected in the tree. 275Similarly to the 276.Fn ARB<8|16|32>_HEAD 277macro, the 278.Fn ARB_ENTRY 279variant includes a suffix denoting the signed integer data type size 280.Pq in bits 281used to store array indices. 282Entries should use the same number of bits as the tree head structure they will 283be linked into. 284.Pp 285In order to use the functions that manipulate the tree structure, 286their prototypes need to be declared with the 287.Fn ARB_PROTOTYPE 288or 289.Fn ARB_PROTOTYPE_STATIC 290macro, 291where 292.Fa NAME 293is a unique identifier for this particular tree. 294The 295.Fa TYPE 296argument is the type of the structure that is being managed 297by the tree. 298The 299.Fa FIELD 300argument is the name of the element defined by 301.Fn ARB_ENTRY . 302Individual prototypes can be declared with 303.Fn ARB_PROTOTYPE_INSERT , 304.Fn ARB_PROTOTYPE_INSERT_COLOR , 305.Fn ARB_PROTOTYPE_REMOVE , 306.Fn ARB_PROTOTYPE_REMOVE_COLOR , 307.Fn ARB_PROTOTYPE_FIND , 308.Fn ARB_PROTOTYPE_NFIND , 309.Fn ARB_PROTOTYPE_NEXT , 310.Fn ARB_PROTOTYPE_PREV , 311.Fn ARB_PROTOTYPE_MINMAX , 312and 313.Fn ARB_PROTOTYPE_REINSERT 314in case not all functions are required. 315The individual prototype macros expect 316.Fa NAME , 317.Fa TYPE , 318and 319.Fa ATTR 320arguments. 321The 322.Fa ATTR 323argument must be empty for global functions or 324.Fa static 325for static functions. 326.Pp 327The function bodies are generated with the 328.Fn ARB_GENERATE 329or 330.Fn ARB_GENERATE_STATIC 331macro. 332These macros take the same arguments as the 333.Fn ARB_PROTOTYPE 334and 335.Fn ARB_PROTOTYPE_STATIC 336macros, but should be used only once. 337As an alternative individual function bodies are generated with the 338.Fn ARB_GENERATE_INSERT , 339.Fn ARB_GENERATE_INSERT_COLOR , 340.Fn ARB_GENERATE_REMOVE , 341.Fn ARB_GENERATE_REMOVE_COLOR , 342.Fn ARB_GENERATE_FIND , 343.Fn ARB_GENERATE_NFIND , 344.Fn ARB_GENERATE_NEXT , 345.Fn ARB_GENERATE_PREV , 346.Fn ARB_GENERATE_MINMAX , 347and 348.Fn ARB_GENERATE_REINSERT 349macros. 350.Pp 351Finally, 352the 353.Fa CMP 354argument is the name of a function used to compare tree nodes 355with each other. 356The function takes two arguments of type 357.Vt "struct TYPE *" . 358If the first argument is smaller than the second, the function returns a 359value smaller than zero. 360If they are equal, the function returns zero. 361Otherwise, it should return a value greater than zero. 362The compare 363function defines the order of the tree elements. 364.Pp 365The 366.Fn ARB_INIT 367macro initializes the tree referenced by 368.Fa head , 369with the array length of 370.Fa maxnodes . 371.Pp 372The red-black tree can also be initialized statically by using the 373.Fn ARB_INITIALIZER 374macro: 375.Bd -ragged -offset indent 376.Fn ARB<8|16|32>_HEAD HEADNAME TYPE 377.Va head 378= 379.Fn ARB_INITIALIZER &head maxnodes ; 380.Ed 381.Pp 382The 383.Fn ARB_INSERT 384macro inserts the new element 385.Fa elm 386into the tree. 387.Pp 388The 389.Fn ARB_REMOVE 390macro removes the element 391.Fa elm 392from the tree pointed by 393.Fa head . 394.Pp 395The 396.Fn ARB_FIND 397and 398.Fn ARB_NFIND 399macros can be used to find a particular element in the tree. 400.Bd -literal -offset indent 401struct TYPE find, *res; 402find.key = 30; 403res = ARB_FIND(NAME, head, &find); 404.Ed 405.Pp 406The 407.Fn ARB_ROOT , 408.Fn ARB_MIN , 409.Fn ARB_MAX , 410.Fn ARB_NEXT , 411and 412.Fn ARB_PREV 413macros can be used to traverse the tree: 414.Pp 415.Dl "for (np = ARB_MIN(NAME, &head); np != NULL; np = ARB_NEXT(NAME, &head, np))" 416.Pp 417Or, for simplicity, one can use the 418.Fn ARB_FOREACH 419or 420.Fn ARB_FOREACH_REVERSE 421macro: 422.Bd -ragged -offset indent 423.Fn ARB_FOREACH np NAME head 424.Ed 425.Pp 426The macros 427.Fn ARB_FOREACH_SAFE 428and 429.Fn ARB_FOREACH_REVERSE_SAFE 430traverse the tree referenced by head 431in a forward or reverse direction respectively, 432assigning each element in turn to np. 433However, unlike their unsafe counterparts, 434they permit both the removal of np 435as well as freeing it from within the loop safely 436without interfering with the traversal. 437.Pp 438Both 439.Fn ARB_FOREACH_FROM 440and 441.Fn ARB_FOREACH_REVERSE_FROM 442may be used to continue an interrupted traversal 443in a forward or reverse direction respectively. 444The head pointer is not required. 445The pointer to the node from where to resume the traversal 446should be passed as their last argument, 447and will be overwritten to provide safe traversal. 448.Pp 449The 450.Fn ARB_EMPTY 451macro should be used to check whether a red-black tree is empty. 452.Pp 453Given that ARB trees have an intrinsic upper bound on the number of entries, 454some ARB-specific additional macros are defined. 455The 456.Fn ARB_FULL 457macro returns a boolean indicating whether the current number of tree entries 458equals the tree's maximum. 459The 460.Fn ARB_CURNODES 461and 462.Fn ARB_MAXNODES 463macros return the current and maximum number of entries respectively. 464The 465.Fn ARB_GETFREE 466macro returns a pointer to the next free entry in the array of entries, ready to 467be linked into the tree. 468The 469.Fn ARB_INSERT 470returns 471.Dv NULL 472if the element was inserted in the tree successfully, otherwise they 473return a pointer to the element with the colliding key. 474.Pp 475Accordingly, 476.Fn ARB_REMOVE 477returns the pointer to the removed element otherwise they return 478.Dv NULL 479to indicate an error. 480.Pp 481The 482.Fn ARB_REINSERT 483macro updates the position of the element 484.Fa elm 485in the tree. 486This must be called if a member of a 487.Nm tree 488is modified in a way that affects comparison, such as by modifying 489a node's key. 490This is a lower overhead alternative to removing the element 491and reinserting it again. 492.Pp 493The 494.Fn ARB_RESET_TREE 495macro discards the tree topology. 496It does not modify embedded object values or the free list. 497.Sh SEE ALSO 498.Xr queue 3 , 499.Xr tree 3 500.Sh HISTORY 501The 502.Nm ARB 503macros first appeared in 504.Fx 13.0 . 505.Sh AUTHORS 506The 507.Nm ARB 508macros were implemented by 509.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org , 510based on 511.Xr tree 3 512macros written by 513.An Niels Provos . 514