xref: /freebsd/share/man/man3/arb.3 (revision c697fb7f)
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