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