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