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