xref: /openbsd-src/share/man/man3/queue.3 (revision 4bc2832d0a071121eb4e4834063fc282081657a1)
1*4bc2832dSnaddy.\"	$OpenBSD: queue.3,v 1.70 2022/03/29 18:15:52 naddy Exp $
2df930be7Sderaadt.\"	$NetBSD: queue.3,v 1.4 1995/07/03 00:25:36 mycroft Exp $
3df930be7Sderaadt.\"
4df930be7Sderaadt.\" Copyright (c) 1993 The Regents of the University of California.
5df930be7Sderaadt.\" All rights reserved.
6df930be7Sderaadt.\"
7df930be7Sderaadt.\" Redistribution and use in source and binary forms, with or without
8df930be7Sderaadt.\" modification, are permitted provided that the following conditions
9df930be7Sderaadt.\" are met:
10df930be7Sderaadt.\" 1. Redistributions of source code must retain the above copyright
11df930be7Sderaadt.\"    notice, this list of conditions and the following disclaimer.
12df930be7Sderaadt.\" 2. Redistributions in binary form must reproduce the above copyright
13df930be7Sderaadt.\"    notice, this list of conditions and the following disclaimer in the
14df930be7Sderaadt.\"    documentation and/or other materials provided with the distribution.
1529295d1cSmillert.\" 3. Neither the name of the University nor the names of its contributors
16df930be7Sderaadt.\"    may be used to endorse or promote products derived from this software
17df930be7Sderaadt.\"    without specific prior written permission.
18df930be7Sderaadt.\"
19df930be7Sderaadt.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df930be7Sderaadt.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df930be7Sderaadt.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df930be7Sderaadt.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df930be7Sderaadt.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df930be7Sderaadt.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df930be7Sderaadt.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df930be7Sderaadt.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df930be7Sderaadt.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df930be7Sderaadt.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df930be7Sderaadt.\" SUCH DAMAGE.
30df930be7Sderaadt.\"
31df930be7Sderaadt.\"	@(#)queue.3	8.1 (Berkeley) 12/13/93
32df930be7Sderaadt.\"
333fd951e6Snaddy.Dd $Mdocdate: March 29 2022 $
34d04ba2ccSjmc.Dt SLIST_INIT 3
35c0e8509eSaaron.Os
36df930be7Sderaadt.Sh NAME
379237eaaaSespie.Nm SLIST_ENTRY ,
389237eaaaSespie.Nm SLIST_HEAD ,
399237eaaaSespie.Nm SLIST_HEAD_INITIALIZER ,
409237eaaaSespie.Nm SLIST_FIRST ,
419237eaaaSespie.Nm SLIST_NEXT ,
429237eaaaSespie.Nm SLIST_EMPTY ,
439237eaaaSespie.Nm SLIST_FOREACH ,
442acff70eSpirofti.Nm SLIST_FOREACH_SAFE ,
459237eaaaSespie.Nm SLIST_INIT ,
469237eaaaSespie.Nm SLIST_INSERT_AFTER ,
479237eaaaSespie.Nm SLIST_INSERT_HEAD ,
4861f9916fSnaddy.Nm SLIST_REMOVE_AFTER ,
499237eaaaSespie.Nm SLIST_REMOVE_HEAD ,
5014bdd124Sjason.Nm SLIST_REMOVE ,
51df930be7Sderaadt.Nm LIST_ENTRY ,
52df930be7Sderaadt.Nm LIST_HEAD ,
530868d64cSespie.Nm LIST_HEAD_INITIALIZER ,
540868d64cSespie.Nm LIST_FIRST ,
550868d64cSespie.Nm LIST_NEXT ,
569237eaaaSespie.Nm LIST_EMPTY ,
579237eaaaSespie.Nm LIST_FOREACH ,
582acff70eSpirofti.Nm LIST_FOREACH_SAFE ,
59df930be7Sderaadt.Nm LIST_INIT ,
60df930be7Sderaadt.Nm LIST_INSERT_AFTER ,
61df930be7Sderaadt.Nm LIST_INSERT_BEFORE ,
62df930be7Sderaadt.Nm LIST_INSERT_HEAD ,
63df930be7Sderaadt.Nm LIST_REMOVE ,
64df7c2479Sangelos.Nm LIST_REPLACE ,
650868d64cSespie.Nm SIMPLEQ_ENTRY ,
660868d64cSespie.Nm SIMPLEQ_HEAD ,
670868d64cSespie.Nm SIMPLEQ_HEAD_INITIALIZER ,
680868d64cSespie.Nm SIMPLEQ_FIRST ,
690868d64cSespie.Nm SIMPLEQ_NEXT ,
709237eaaaSespie.Nm SIMPLEQ_EMPTY ,
719237eaaaSespie.Nm SIMPLEQ_FOREACH ,
722acff70eSpirofti.Nm SIMPLEQ_FOREACH_SAFE ,
730868d64cSespie.Nm SIMPLEQ_INIT ,
7461f9916fSnaddy.Nm SIMPLEQ_INSERT_AFTER ,
750868d64cSespie.Nm SIMPLEQ_INSERT_HEAD ,
760868d64cSespie.Nm SIMPLEQ_INSERT_TAIL ,
7761f9916fSnaddy.Nm SIMPLEQ_REMOVE_AFTER ,
780868d64cSespie.Nm SIMPLEQ_REMOVE_HEAD ,
7944ab62a3Smillert.Nm SIMPLEQ_CONCAT ,
809322932cSmillert.Nm STAILQ_ENTRY ,
819322932cSmillert.Nm STAILQ_HEAD ,
829322932cSmillert.Nm STAILQ_HEAD_INITIALIZER ,
839322932cSmillert.Nm STAILQ_FIRST ,
849322932cSmillert.Nm STAILQ_NEXT ,
859322932cSmillert.Nm STAILQ_LAST ,
869322932cSmillert.Nm STAILQ_EMPTY ,
879322932cSmillert.Nm STAILQ_FOREACH ,
889322932cSmillert.Nm STAILQ_FOREACH_SAFE ,
899322932cSmillert.Nm STAILQ_INIT ,
909322932cSmillert.Nm STAILQ_INSERT_AFTER ,
919322932cSmillert.Nm STAILQ_INSERT_HEAD ,
929322932cSmillert.Nm STAILQ_INSERT_TAIL ,
939322932cSmillert.Nm STAILQ_REMOVE ,
949322932cSmillert.Nm STAILQ_REMOVE_AFTER ,
959322932cSmillert.Nm STAILQ_REMOVE_HEAD ,
969322932cSmillert.Nm STAILQ_CONCAT ,
97df930be7Sderaadt.Nm TAILQ_ENTRY ,
98df930be7Sderaadt.Nm TAILQ_HEAD ,
990868d64cSespie.Nm TAILQ_HEAD_INITIALIZER ,
1000868d64cSespie.Nm TAILQ_FIRST ,
1010868d64cSespie.Nm TAILQ_NEXT ,
1020868d64cSespie.Nm TAILQ_LAST ,
1030868d64cSespie.Nm TAILQ_PREV ,
1049237eaaaSespie.Nm TAILQ_EMPTY ,
1059237eaaaSespie.Nm TAILQ_FOREACH ,
1062acff70eSpirofti.Nm TAILQ_FOREACH_SAFE ,
107c9cbb67dSderaadt.Nm TAILQ_FOREACH_REVERSE ,
1082acff70eSpirofti.Nm TAILQ_FOREACH_REVERSE_SAFE ,
109df930be7Sderaadt.Nm TAILQ_INIT ,
110df930be7Sderaadt.Nm TAILQ_INSERT_AFTER ,
111df930be7Sderaadt.Nm TAILQ_INSERT_BEFORE ,
112df930be7Sderaadt.Nm TAILQ_INSERT_HEAD ,
113df930be7Sderaadt.Nm TAILQ_INSERT_TAIL ,
114df930be7Sderaadt.Nm TAILQ_REMOVE ,
11544ab62a3Smillert.Nm TAILQ_REPLACE ,
11644ab62a3Smillert.Nm TAILQ_CONCAT
1179322932cSmillert.Nd intrusive singly-linked and doubly-linked lists, simple queues, singly-linked and doubly-linked tail queues
118df930be7Sderaadt.Sh SYNOPSIS
119cfcc6981Stedu.In sys/queue.h
120431305c8Saaron.Pp
1219237eaaaSespie.Fn SLIST_ENTRY "TYPE"
1229237eaaaSespie.Fn SLIST_HEAD "HEADNAME" "TYPE"
1239237eaaaSespie.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
1249237eaaaSespie.Ft "struct TYPE *"
1259237eaaaSespie.Fn SLIST_FIRST "SLIST_HEAD *head"
1269237eaaaSespie.Ft "struct TYPE *"
1275479c038Sguenther.Fn SLIST_NEXT "struct TYPE *listelm" "FIELDNAME"
128652a0345Sjmc.Ft int
1299237eaaaSespie.Fn SLIST_EMPTY "SLIST_HEAD *head"
1305479c038Sguenther.Fn SLIST_FOREACH "VARNAME" "SLIST_HEAD *head" "FIELDNAME"
1315479c038Sguenther.Fn SLIST_FOREACH_SAFE "VARNAME" "SLIST_HEAD *head" "FIELDNAME" "TEMP_VARNAME"
1329237eaaaSespie.Ft void
1339237eaaaSespie.Fn SLIST_INIT "SLIST_HEAD *head"
1349237eaaaSespie.Ft void
1355479c038Sguenther.Fn SLIST_INSERT_AFTER "struct TYPE *listelm" "struct TYPE *elm" "FIELDNAME"
1369237eaaaSespie.Ft void
1375479c038Sguenther.Fn SLIST_INSERT_HEAD "SLIST_HEAD *head" "struct TYPE *elm" "FIELDNAME"
1389237eaaaSespie.Ft void
1395479c038Sguenther.Fn SLIST_REMOVE_AFTER "struct TYPE *elm" "FIELDNAME"
14014bdd124Sjason.Ft void
1415479c038Sguenther.Fn SLIST_REMOVE_HEAD "SLIST_HEAD *head" "FIELDNAME"
142d377bb64Smillert.Ft void
1435479c038Sguenther.Fn SLIST_REMOVE "SLIST_HEAD *head" "struct TYPE *elm" "TYPE" "FIELDNAME"
144431305c8Saaron.Pp
145df930be7Sderaadt.Fn LIST_ENTRY "TYPE"
146df930be7Sderaadt.Fn LIST_HEAD "HEADNAME" "TYPE"
1470868d64cSespie.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
1480868d64cSespie.Ft "struct TYPE *"
1490868d64cSespie.Fn LIST_FIRST "LIST_HEAD *head"
1500868d64cSespie.Ft "struct TYPE *"
1515479c038Sguenther.Fn LIST_NEXT "struct TYPE *listelm" "FIELDNAME"
152652a0345Sjmc.Ft int
1539237eaaaSespie.Fn LIST_EMPTY "LIST_HEAD *head"
1545479c038Sguenther.Fn LIST_FOREACH "VARNAME" "LIST_HEAD *head" "FIELDNAME"
1555479c038Sguenther.Fn LIST_FOREACH_SAFE "VARNAME" "LIST_HEAD *head" "FIELDNAME" "TEMP_VARNAME"
1560868d64cSespie.Ft void
157df930be7Sderaadt.Fn LIST_INIT "LIST_HEAD *head"
1580868d64cSespie.Ft void
1595479c038Sguenther.Fn LIST_INSERT_AFTER "struct TYPE *listelm" "struct TYPE *elm" "FIELDNAME"
1600868d64cSespie.Ft void
1615479c038Sguenther.Fn LIST_INSERT_BEFORE "struct TYPE *listelm" "struct TYPE *elm" "FIELDNAME"
1620868d64cSespie.Ft void
1635479c038Sguenther.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "struct TYPE *elm" "FIELDNAME"
1640868d64cSespie.Ft void
1655479c038Sguenther.Fn LIST_REMOVE "struct TYPE *elm" "FIELDNAME"
166df7c2479Sangelos.Ft void
1675479c038Sguenther.Fn LIST_REPLACE "struct TYPE *elm" "struct TYPE *elm2" "FIELDNAME"
168431305c8Saaron.Pp
1690868d64cSespie.Fn SIMPLEQ_ENTRY "TYPE"
1700868d64cSespie.Fn SIMPLEQ_HEAD "HEADNAME" "TYPE"
1710868d64cSespie.Fn SIMPLEQ_HEAD_INITIALIZER "SIMPLEQ_HEAD head"
1720868d64cSespie.Ft "struct TYPE *"
1730868d64cSespie.Fn SIMPLEQ_FIRST "SIMPLEQ_HEAD *head"
1740868d64cSespie.Ft "struct TYPE *"
1755479c038Sguenther.Fn SIMPLEQ_NEXT "struct TYPE *listelm" "FIELDNAME"
176652a0345Sjmc.Ft int
177652a0345Sjmc.Fn SIMPLEQ_EMPTY "SIMPLEQ_HEAD *head"
1785479c038Sguenther.Fn SIMPLEQ_FOREACH "VARNAME" "SIMPLEQ_HEAD *head" "FIELDNAME"
1795479c038Sguenther.Fn SIMPLEQ_FOREACH_SAFE "VARNAME" "SIMPLEQ_HEAD *head" "FIELDNAME" "TEMP_VARNAME"
1800868d64cSespie.Ft void
1810868d64cSespie.Fn SIMPLEQ_INIT "SIMPLEQ_HEAD *head"
1820868d64cSespie.Ft void
1835479c038Sguenther.Fn SIMPLEQ_INSERT_AFTER "SIMPLEQ_HEAD *head" "struct TYPE *listelm" "struct TYPE *elm" "FIELDNAME"
18461f9916fSnaddy.Ft void
1855479c038Sguenther.Fn SIMPLEQ_INSERT_HEAD "SIMPLEQ_HEAD *head" "struct TYPE *elm" "FIELDNAME"
1860868d64cSespie.Ft void
1875479c038Sguenther.Fn SIMPLEQ_INSERT_TAIL "SIMPLEQ_HEAD *head" "struct TYPE *elm" "FIELDNAME"
1880868d64cSespie.Ft void
1895479c038Sguenther.Fn SIMPLEQ_REMOVE_AFTER "SIMPLEQ_HEAD *head" "struct TYPE *elm" "FIELDNAME"
1900868d64cSespie.Ft void
1915479c038Sguenther.Fn SIMPLEQ_REMOVE_HEAD "SIMPLEQ_HEAD *head" "FIELDNAME"
19244ab62a3Smillert.Fn SIMPLEQ_CONCAT "SIMPLEQ_HEAD *head1" "SIMPLEQ_HEAD *head2"
193431305c8Saaron.Pp
1949322932cSmillert.Fn STAILQ_ENTRY "TYPE"
1959322932cSmillert.Fn STAILQ_HEAD "HEADNAME" "TYPE"
1969322932cSmillert.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
1979322932cSmillert.Fn STAILQ_FIRST "STAILQ_HEAD *head"
1989322932cSmillert.Fn STAILQ_NEXT "TYPE *elm" "STAILQ_ENTRY NAME"
1999322932cSmillert.Fn STAILQ_LAST "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
2009322932cSmillert.Fn STAILQ_EMPTY "STAILQ_HEAD *head"
2019322932cSmillert.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
2029322932cSmillert.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
2039322932cSmillert.Fn STAILQ_INIT "STAILQ_HEAD *head"
2049322932cSmillert.Fn STAILQ_INSERT_AFTER "STAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "STAILQ_ENTRY NAME"
2059322932cSmillert.Fn STAILQ_INSERT_HEAD "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
2069322932cSmillert.Fn STAILQ_INSERT_TAIL "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
2079322932cSmillert.Fn STAILQ_REMOVE "STAILQ_HEAD *head" "TYPE *elm" "TYPE" "STAILQ_ENTRY NAME"
2089322932cSmillert.Fn STAILQ_REMOVE_AFTER "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
2099322932cSmillert.Fn STAILQ_REMOVE_HEAD "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
2109322932cSmillert.Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2"
2119322932cSmillert.Pp
212df930be7Sderaadt.Fn TAILQ_ENTRY "TYPE"
213df930be7Sderaadt.Fn TAILQ_HEAD "HEADNAME" "TYPE"
2140868d64cSespie.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
2150868d64cSespie.Ft "struct TYPE *"
2160868d64cSespie.Fn TAILQ_FIRST "TAILQ_HEAD *head"
2170868d64cSespie.Ft "struct TYPE *"
2185479c038Sguenther.Fn TAILQ_NEXT "struct TYPE *listelm" "FIELDNAME"
2190868d64cSespie.Ft "struct TYPE *"
2205479c038Sguenther.Fn TAILQ_LAST "TAILQ_HEAD *head" "HEADNAME"
221a3d4d7bcSjmc.Ft "struct TYPE *"
2225479c038Sguenther.Fn TAILQ_PREV "struct TYPE *listelm" "HEADNAME" "FIELDNAME"
223652a0345Sjmc.Ft int
224c9cbb67dSderaadt.Fn TAILQ_EMPTY "TAILQ_HEAD *head"
2255479c038Sguenther.Fn TAILQ_FOREACH "VARNAME" "TAILQ_HEAD *head" "FIELDNAME"
2265479c038Sguenther.Fn TAILQ_FOREACH_SAFE "VARNAME" "TAILQ_HEAD *head" "FIELDNAME" "TEMP_VARNAME"
2275479c038Sguenther.Fn TAILQ_FOREACH_REVERSE "VARNAME" "TAILQ_HEAD *head" "HEADNAME" "FIELDNAME"
2285479c038Sguenther.Fn TAILQ_FOREACH_REVERSE_SAFE "VARNAME" "TAILQ_HEAD *head" "HEADNAME" "FIELDNAME" "TEMP_VARNAME"
2290868d64cSespie.Ft void
230df930be7Sderaadt.Fn TAILQ_INIT "TAILQ_HEAD *head"
2310868d64cSespie.Ft void
2325479c038Sguenther.Fn TAILQ_INSERT_AFTER "TAILQ_HEAD *head" "struct TYPE *listelm" "struct TYPE *elm" "FIELDNAME"
2330868d64cSespie.Ft void
2345479c038Sguenther.Fn TAILQ_INSERT_BEFORE "struct TYPE *listelm" "struct TYPE *elm" "FIELDNAME"
2350868d64cSespie.Ft void
2365479c038Sguenther.Fn TAILQ_INSERT_HEAD "TAILQ_HEAD *head" "struct TYPE *elm" "FIELDNAME"
2370868d64cSespie.Ft void
2385479c038Sguenther.Fn TAILQ_INSERT_TAIL "TAILQ_HEAD *head" "struct TYPE *elm" "FIELDNAME"
2390868d64cSespie.Ft void
2405479c038Sguenther.Fn TAILQ_REMOVE "TAILQ_HEAD *head" "struct TYPE *elm" "FIELDNAME"
24128601b65Sjmc.Ft void
2425479c038Sguenther.Fn TAILQ_REPLACE "TAILQ_HEAD *head" "struct TYPE *elm" "struct TYPE *elm2" "FIELDNAME"
243f21864e4Smpi.Fn TAILQ_CONCAT "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "FIELDNAME"
244df930be7Sderaadt.Sh DESCRIPTION
2459322932cSmillertThese macros define and operate on five types of data structures:
2469322932cSmillertsingly-linked lists, simple queues, lists, singly-linked tail queues,
2479322932cSmillertand tail queues.
2489322932cSmillertAll five structures support the following functionality:
249f33e0097Saaron.Pp
250df930be7Sderaadt.Bl -enum -compact -offset indent
251df930be7Sderaadt.It
252df930be7SderaadtInsertion of a new entry at the head of the list.
253df930be7Sderaadt.It
2549237eaaaSespieInsertion of a new entry after any element in the list.
255df930be7Sderaadt.It
2569237eaaaSespieRemoval of an entry from the head of the list.
257df930be7Sderaadt.It
258df930be7SderaadtForward traversal through the list.
259df930be7Sderaadt.El
260df930be7Sderaadt.Pp
26191c1d590SschwarzeThe following table provides a quick overview
26291c1d590Sschwarzeof which types support which additional macros:
2639322932cSmillert.Bl -column -offset 6n "LAST, PREV, FOREACH_REVERSE" SLIST LIST SIMPLEQ STAILQ TAILQ
2649322932cSmillert.It LAST, PREV, FOREACH_REVERSE Ta -     Ta -    Ta -       Ta -      Ta TAILQ
2659322932cSmillert.It INSERT_BEFORE, REPLACE      Ta -     Ta LIST Ta -       Ta -      Ta TAILQ
2669322932cSmillert.It INSERT_TAIL, CONCAT         Ta -     Ta -    Ta SIMPLEQ Ta STAILQ Ta TAILQ
2679322932cSmillert.It REMOVE_AFTER, REMOVE_HEAD   Ta SLIST Ta -    Ta SIMPLEQ Ta STAILQ Ta -
2689322932cSmillert.It REMOVE                      Ta SLIST Ta LIST Ta -       Ta STAILQ Ta TAILQ
26991c1d590Sschwarze.El
27091c1d590Sschwarze.Pp
2719322932cSmillertSingly-linked lists are the simplest of the five data structures
2729237eaaaSespieand support only the above functionality.
2739237eaaaSespieSingly-linked lists are ideal for applications with large datasets
274431305c8Saaronand few or no removals, or for implementing a LIFO queue.
2750868d64cSespie.Pp
2769322932cSmillertSimple queues and singly-linked tail queues add the following functionality:
2770868d64cSespie.Pp
2780868d64cSespie.Bl -enum -compact -offset indent
2790868d64cSespie.It
2809237eaaaSespieEntries can be added at the end of a list.
281df930be7Sderaadt.El
282f33e0097Saaron.Pp
283df930be7SderaadtHowever:
284f33e0097Saaron.Pp
285df930be7Sderaadt.Bl -enum -compact -offset indent
286df930be7Sderaadt.It
2879237eaaaSespieAll list insertions must specify the head of the list.
288df930be7Sderaadt.It
289df930be7SderaadtEach head entry requires two pointers rather than one.
290df930be7Sderaadt.It
291df930be7SderaadtCode size is about 15% greater and operations run about 20% slower
2929237eaaaSespiethan singly-linked lists.
2939237eaaaSespie.El
2949237eaaaSespie.Pp
2959322932cSmillertSimple queues and singly-linked tail queues are ideal for applications with
2969322932cSmillertlarge datasets and few or no removals, or for implementing a FIFO queue.
2979237eaaaSespie.Pp
298b9b58a6dSguentherAll doubly linked types of data structures (lists and tail queues)
299b9b58a6dSguentheradditionally allow:
3009237eaaaSespie.Pp
3019237eaaaSespie.Bl -enum -compact -offset indent
3029237eaaaSespie.It
3039237eaaaSespieInsertion of a new entry before any element in the list.
3049237eaaaSespie.It
3059237eaaaSespieRemoval of any entry in the list.
3069237eaaaSespie.El
3079237eaaaSespie.Pp
3089237eaaaSespieHowever:
3099237eaaaSespie.Pp
3109237eaaaSespie.Bl -enum -compact -offset indent
3119237eaaaSespie.It
312cc405d09SjmcEach element requires two pointers rather than one.
3139237eaaaSespie.It
3149237eaaaSespieCode size and execution time of operations (except for removal) is about
3159237eaaaSespietwice that of the singly-linked data-structures.
3169237eaaaSespie.El
3179237eaaaSespie.Pp
3189237eaaaSespieLists are the simplest of the doubly linked data structures and support
3199237eaaaSespieonly the above functionality over singly-linked lists.
3209237eaaaSespie.Pp
3219237eaaaSespieTail queues add the following functionality:
3229237eaaaSespie.Pp
3239237eaaaSespie.Bl -enum -compact -offset indent
3249237eaaaSespie.It
3259237eaaaSespieEntries can be added at the end of a list.
3269237eaaaSespie.It
3279237eaaaSespieThey may be traversed backwards, at a cost.
3289237eaaaSespie.El
3299237eaaaSespie.Pp
3309237eaaaSespieHowever:
3319237eaaaSespie.Pp
3329237eaaaSespie.Bl -enum -compact -offset indent
3339237eaaaSespie.It
3349237eaaaSespieAll list insertions and removals must specify the head of the list.
3359237eaaaSespie.It
3369237eaaaSespieEach head entry requires two pointers rather than one.
3379237eaaaSespie.It
3389237eaaaSespieCode size is about 15% greater and operations run about 20% slower
3399237eaaaSespiethan singly-linked lists.
340df930be7Sderaadt.El
341df930be7Sderaadt.Pp
342b9b58a6dSguentherAn additional type of data structure, circular queues, violated the C
343b9b58a6dSguentherlanguage aliasing rules and were miscompiled as a result.
344b9b58a6dSguentherAll code using them should be converted to another structure;
345b9b58a6dSguenthertail queues are usually the easiest to convert to.
346df930be7Sderaadt.Pp
34724e04962SschwarzeAll these lists and queues are intrusive: they link together user
34824e04962Sschwarzedefined structures containing a field of type
3499237eaaaSespie.Li SLIST_ENTRY ,
350df930be7Sderaadt.Li LIST_ENTRY ,
3510868d64cSespie.Li SIMPLEQ_ENTRY ,
3529322932cSmillert.Li STAILQ_ENTRY ,
353df930be7Sderaadtor
35424e04962Sschwarze.Li TAILQ_ENTRY .
35524e04962SschwarzeIn the macro definitions,
35624e04962Sschwarze.Fa TYPE
35724e04962Sschwarzeis the name tag of the user defined structure and
35824e04962Sschwarze.Fa FIELDNAME
35924e04962Sschwarzeis the name of the
36024e04962Sschwarze.Li *_ENTRY
36124e04962Sschwarzefield.
36224e04962SschwarzeIf an instance of the user defined structure needs to be a member of
36324e04962Sschwarzemultiple lists at the same time, the structure requires multiple
36424e04962Sschwarze.Li *_ENTRY
36524e04962Sschwarzefields, one for each list.
36624e04962Sschwarze.Pp
367df930be7SderaadtThe argument
368df930be7Sderaadt.Fa HEADNAME
3690868d64cSespieis the name tag of a user defined structure that must be declared
370df930be7Sderaadtusing the macros
3719237eaaaSespie.Fn SLIST_HEAD ,
372f33e0097Saaron.Fn LIST_HEAD ,
3730868d64cSespie.Fn SIMPLEQ_HEAD ,
3749322932cSmillert.Fn STAILQ_HEAD ,
375df930be7Sderaadtor
376b9b58a6dSguenther.Fn TAILQ_HEAD .
377431305c8SaaronSee the examples below for further explanation of how these macros are used.
378c8ff027bSjaredy.Sh SINGLY-LINKED LISTS
3799237eaaaSespieA singly-linked list is headed by a structure defined by the
3809237eaaaSespie.Fn SLIST_HEAD
3819237eaaaSespiemacro.
382431305c8SaaronThis structure contains a single pointer to the first element on the list.
3839237eaaaSespieThe elements are singly linked for minimum space and pointer manipulation
3849237eaaaSespieoverhead at the expense of O(n) removal for arbitrary elements.
3859237eaaaSespieNew elements can be added to the list after an existing element or
3869237eaaaSespieat the head of the list.
3879237eaaaSespieA
3889237eaaaSespie.Fa SLIST_HEAD
3899237eaaaSespiestructure is declared as follows:
3909237eaaaSespie.Bd -literal -offset indent
3919237eaaaSespieSLIST_HEAD(HEADNAME, TYPE) head;
3929237eaaaSespie.Ed
393431305c8Saaron.Pp
3949237eaaaSespiewhere
3959237eaaaSespie.Fa HEADNAME
3969237eaaaSespieis the name of the structure to be defined, and struct
3979237eaaaSespie.Fa TYPE
3989237eaaaSespieis the type of the elements to be linked into the list.
3999237eaaaSespieA pointer to the head of the list can later be declared as:
4009237eaaaSespie.Bd -literal -offset indent
4019237eaaaSespiestruct HEADNAME *headp;
4029237eaaaSespie.Ed
403431305c8Saaron.Pp
4049237eaaaSespie(The names
4059237eaaaSespie.Li head
4069237eaaaSespieand
4079237eaaaSespie.Li headp
4089237eaaaSespieare user selectable.)
409431305c8Saaron.Pp
4109237eaaaSespieThe
4119237eaaaSespie.Fa HEADNAME
4129237eaaaSespiefacility is often not used, leading to the following bizarre code:
4139237eaaaSespie.Bd -literal -offset indent
4149237eaaaSespieSLIST_HEAD(, TYPE) head, *headp;
4159237eaaaSespie.Ed
4169237eaaaSespie.Pp
4179237eaaaSespieThe
4189237eaaaSespie.Fn SLIST_ENTRY
419431305c8Saaronmacro declares a structure that connects the elements in the list.
4209237eaaaSespie.Pp
4219237eaaaSespieThe
4229237eaaaSespie.Fn SLIST_INIT
4239237eaaaSespiemacro initializes the list referenced by
4249237eaaaSespie.Fa head .
4259237eaaaSespie.Pp
4269237eaaaSespieThe list can also be initialized statically by using the
4279237eaaaSespie.Fn SLIST_HEAD_INITIALIZER
4289237eaaaSespiemacro like this:
4299237eaaaSespie.Bd -literal -offset indent
4309237eaaaSespieSLIST_HEAD(HEADNAME, TYPE) head = SLIST_HEAD_INITIALIZER(head);
4319237eaaaSespie.Ed
4329237eaaaSespie.Pp
4339237eaaaSespieThe
4349237eaaaSespie.Fn SLIST_INSERT_HEAD
4359237eaaaSespiemacro inserts the new element
4369237eaaaSespie.Fa elm
4379237eaaaSespieat the head of the list.
4389237eaaaSespie.Pp
4399237eaaaSespieThe
4409237eaaaSespie.Fn SLIST_INSERT_AFTER
4419237eaaaSespiemacro inserts the new element
4429237eaaaSespie.Fa elm
4439237eaaaSespieafter the element
4449237eaaaSespie.Fa listelm .
4459237eaaaSespie.Pp
4469237eaaaSespieThe
4479237eaaaSespie.Fn SLIST_REMOVE_HEAD
4489237eaaaSespiemacro removes the first element of the list pointed by
4499237eaaaSespie.Fa head .
4509237eaaaSespie.Pp
4519237eaaaSespieThe
45261f9916fSnaddy.Fn SLIST_REMOVE_AFTER
453d377bb64Smillertmacro removes the list element immediately following
454d377bb64Smillert.Fa elm .
455d377bb64Smillert.Pp
456d377bb64SmillertThe
45714bdd124Sjason.Fn SLIST_REMOVE
45814bdd124Sjasonmacro removes the element
45914bdd124Sjason.Fa elm
46014bdd124Sjasonof the list pointed by
46114bdd124Sjason.Fa head .
46214bdd124Sjason.Pp
46314bdd124SjasonThe
464cc405d09Sjmc.Fn SLIST_FIRST
4659237eaaaSespieand
4669237eaaaSespie.Fn SLIST_NEXT
4679237eaaaSespiemacros can be used to traverse the list:
4689237eaaaSespie.Bd -literal -offset indent
4695479c038Sguentherfor (np = SLIST_FIRST(&head); np != NULL; np = SLIST_NEXT(np, FIELDNAME))
4709237eaaaSespie.Ed
4711f53fde1Saaron.Pp
4729237eaaaSespieOr, for simplicity, one can use the
4739237eaaaSespie.Fn SLIST_FOREACH
4749237eaaaSespiemacro:
4759237eaaaSespie.Bd -literal -offset indent
4765479c038SguentherSLIST_FOREACH(np, head, FIELDNAME)
4779237eaaaSespie.Ed
4789237eaaaSespie.Pp
479658b0e47SbluhmThe macro
480658b0e47Sbluhm.Fn SLIST_FOREACH_SAFE
481658b0e47Sbluhmtraverses the list referenced by head in a
482d2ad55b1Sjmcforward direction, assigning each element in turn to var.
483d2ad55b1SjmcHowever, unlike
484d2ad55b1Sjmc.Fn SLIST_FOREACH
485d2ad55b1Sjmcit is permitted to remove var as well
4862acff70eSpiroftias free it from within the loop safely without interfering with the traversal.
4872acff70eSpirofti.Pp
4889237eaaaSespieThe
4899237eaaaSespie.Fn SLIST_EMPTY
4909237eaaaSespiemacro should be used to check whether a simple list is empty.
491d8e11b2fSjmc.Sh SINGLY-LINKED LIST EXAMPLE
492d8e11b2fSjmc.Bd -literal
493d8e11b2fSjmcSLIST_HEAD(listhead, entry) head;
494d8e11b2fSjmcstruct entry {
495d8e11b2fSjmc	...
496d8e11b2fSjmc	SLIST_ENTRY(entry) entries;	/* Simple list. */
497d8e11b2fSjmc	...
498d8e11b2fSjmc} *n1, *n2, *np;
499d8e11b2fSjmc
500d8e11b2fSjmcSLIST_INIT(&head);			/* Initialize simple list. */
501d8e11b2fSjmc
502d8e11b2fSjmcn1 = malloc(sizeof(struct entry));	/* Insert at the head. */
503d8e11b2fSjmcSLIST_INSERT_HEAD(&head, n1, entries);
504d8e11b2fSjmc
505d8e11b2fSjmcn2 = malloc(sizeof(struct entry));	/* Insert after. */
506d8e11b2fSjmcSLIST_INSERT_AFTER(n1, n2, entries);
507d8e11b2fSjmc
508d8e11b2fSjmcSLIST_FOREACH(np, &head, entries)	/* Forward traversal. */
509d8e11b2fSjmc	np-> ...
510d8e11b2fSjmc
51175fe3d80Sbeckwhile (!SLIST_EMPTY(&head)) {	 	/* Delete. */
51275fe3d80Sbeck	n1 = SLIST_FIRST(&head);
513d8e11b2fSjmc	SLIST_REMOVE_HEAD(&head, entries);
51475fe3d80Sbeck	free(n1);
51575fe3d80Sbeck}
51675fe3d80Sbeck
517d8e11b2fSjmc.Ed
518df930be7Sderaadt.Sh LISTS
519df930be7SderaadtA list is headed by a structure defined by the
520f33e0097Saaron.Fn LIST_HEAD
521df930be7Sderaadtmacro.
522431305c8SaaronThis structure contains a single pointer to the first element on the list.
523df930be7SderaadtThe elements are doubly linked so that an arbitrary element can be
524df930be7Sderaadtremoved without traversing the list.
525df930be7SderaadtNew elements can be added to the list after an existing element,
526df930be7Sderaadtbefore an existing element, or at the head of the list.
527df930be7SderaadtA
528df930be7Sderaadt.Fa LIST_HEAD
529df930be7Sderaadtstructure is declared as follows:
530df930be7Sderaadt.Bd -literal -offset indent
531df930be7SderaadtLIST_HEAD(HEADNAME, TYPE) head;
532df930be7Sderaadt.Ed
533431305c8Saaron.Pp
534df930be7Sderaadtwhere
535df930be7Sderaadt.Fa HEADNAME
5360868d64cSespieis the name of the structure to be defined, and struct
537df930be7Sderaadt.Fa TYPE
538df930be7Sderaadtis the type of the elements to be linked into the list.
539df930be7SderaadtA pointer to the head of the list can later be declared as:
540df930be7Sderaadt.Bd -literal -offset indent
541df930be7Sderaadtstruct HEADNAME *headp;
542df930be7Sderaadt.Ed
543431305c8Saaron.Pp
544df930be7Sderaadt(The names
545df930be7Sderaadt.Li head
546df930be7Sderaadtand
547df930be7Sderaadt.Li headp
548df930be7Sderaadtare user selectable.)
549431305c8Saaron.Pp
5500868d64cSespieThe
5510868d64cSespie.Fa HEADNAME
5520868d64cSespiefacility is often not used, leading to the following bizarre code:
5530868d64cSespie.Bd -literal -offset indent
5540868d64cSespieLIST_HEAD(, TYPE) head, *headp;
5550868d64cSespie.Ed
556df930be7Sderaadt.Pp
557f33e0097SaaronThe
558f33e0097Saaron.Fn LIST_ENTRY
559431305c8Saaronmacro declares a structure that connects the elements in the list.
560df930be7Sderaadt.Pp
561f33e0097SaaronThe
562f33e0097Saaron.Fn LIST_INIT
563f33e0097Saaronmacro initializes the list referenced by
564df930be7Sderaadt.Fa head .
565df930be7Sderaadt.Pp
5660868d64cSespieThe list can also be initialized statically by using the
5670868d64cSespie.Fn LIST_HEAD_INITIALIZER
5680868d64cSespiemacro like this:
5690868d64cSespie.Bd -literal -offset indent
5700868d64cSespieLIST_HEAD(HEADNAME, TYPE) head = LIST_HEAD_INITIALIZER(head);
5710868d64cSespie.Ed
5720868d64cSespie.Pp
573f33e0097SaaronThe
574f33e0097Saaron.Fn LIST_INSERT_HEAD
575f33e0097Saaronmacro inserts the new element
576df930be7Sderaadt.Fa elm
577df930be7Sderaadtat the head of the list.
578df930be7Sderaadt.Pp
579f33e0097SaaronThe
580f33e0097Saaron.Fn LIST_INSERT_AFTER
581f33e0097Saaronmacro inserts the new element
582df930be7Sderaadt.Fa elm
583df930be7Sderaadtafter the element
584df930be7Sderaadt.Fa listelm .
585df930be7Sderaadt.Pp
586f33e0097SaaronThe
587f33e0097Saaron.Fn LIST_INSERT_BEFORE
588f33e0097Saaronmacro inserts the new element
589df930be7Sderaadt.Fa elm
590df930be7Sderaadtbefore the element
591df930be7Sderaadt.Fa listelm .
592df930be7Sderaadt.Pp
593f33e0097SaaronThe
594f33e0097Saaron.Fn LIST_REMOVE
595f33e0097Saaronmacro removes the element
596df930be7Sderaadt.Fa elm
597df930be7Sderaadtfrom the list.
5980868d64cSespie.Pp
5990868d64cSespieThe
600df7c2479Sangelos.Fn LIST_REPLACE
601df7c2479Sangelosmacro replaces the list element
602df7c2479Sangelos.Fa elm
603df7c2479Sangeloswith the new element
604df7c2479Sangelos.Fa elm2 .
605df7c2479Sangelos.Pp
606df7c2479SangelosThe
607cc405d09Sjmc.Fn LIST_FIRST
6080868d64cSespieand
6090868d64cSespie.Fn LIST_NEXT
6100868d64cSespiemacros can be used to traverse the list:
6110868d64cSespie.Bd -literal -offset indent
6125479c038Sguentherfor (np = LIST_FIRST(&head); np != NULL; np = LIST_NEXT(np, FIELDNAME))
6130868d64cSespie.Ed
6141f53fde1Saaron.Pp
6159237eaaaSespieOr, for simplicity, one can use the
6169237eaaaSespie.Fn LIST_FOREACH
6179237eaaaSespiemacro:
6189237eaaaSespie.Bd -literal -offset indent
6195479c038SguentherLIST_FOREACH(np, head, FIELDNAME)
6209237eaaaSespie.Ed
6219237eaaaSespie.Pp
622658b0e47SbluhmThe macro
623658b0e47Sbluhm.Fn LIST_FOREACH_SAFE
624658b0e47Sbluhmtraverses the list referenced by head in a
625d2ad55b1Sjmcforward direction, assigning each element in turn to var.
626d2ad55b1SjmcHowever, unlike
627d2ad55b1Sjmc.Fn LIST_FOREACH
628d2ad55b1Sjmcit is permitted to remove var as well
6292acff70eSpiroftias free it from within the loop safely without interfering with the traversal.
6302acff70eSpirofti.Pp
6319237eaaaSespieThe
6329237eaaaSespie.Fn LIST_EMPTY
6339237eaaaSespiemacro should be used to check whether a list is empty.
634df930be7Sderaadt.Sh LIST EXAMPLE
635df930be7Sderaadt.Bd -literal
636df930be7SderaadtLIST_HEAD(listhead, entry) head;
637df930be7Sderaadtstruct entry {
638df930be7Sderaadt	...
639df930be7Sderaadt	LIST_ENTRY(entry) entries;	/* List. */
640df930be7Sderaadt	...
641df930be7Sderaadt} *n1, *n2, *np;
642df930be7Sderaadt
6430b0b405fSaaronLIST_INIT(&head);			/* Initialize list. */
644df930be7Sderaadt
645df930be7Sderaadtn1 = malloc(sizeof(struct entry));	/* Insert at the head. */
646df930be7SderaadtLIST_INSERT_HEAD(&head, n1, entries);
647df930be7Sderaadt
648df930be7Sderaadtn2 = malloc(sizeof(struct entry));	/* Insert after. */
649df930be7SderaadtLIST_INSERT_AFTER(n1, n2, entries);
650df930be7Sderaadt
651df930be7Sderaadtn2 = malloc(sizeof(struct entry));	/* Insert before. */
652df930be7SderaadtLIST_INSERT_BEFORE(n1, n2, entries);
653df930be7Sderaadt					/* Forward traversal. */
6541d29e077SottoLIST_FOREACH(np, &head, entries)
655df930be7Sderaadt	np-> ...
656df930be7Sderaadt
657c0c67761Stobiaswhile (!LIST_EMPTY(&head)) {		/* Delete. */
65875fe3d80Sbeck	n1 = LIST_FIRST(&head);
65975fe3d80Sbeck	LIST_REMOVE(n1, entries);
66075fe3d80Sbeck	free(n1);
66175fe3d80Sbeck}
662df930be7Sderaadt.Ed
6630868d64cSespie.Sh SIMPLE QUEUES
6640868d64cSespieA simple queue is headed by a structure defined by the
6659237eaaaSespie.Fn SIMPLEQ_HEAD
6660868d64cSespiemacro.
667431305c8SaaronThis structure contains a pair of pointers, one to the first element in the
668431305c8Saaronsimple queue and the other to the last element in the simple queue.
6699237eaaaSespieThe elements are singly linked.
6700868d64cSespieNew elements can be added to the queue after an existing element,
6710868d64cSespieat the head of the queue or at the tail of the queue.
6720868d64cSespieA
6730868d64cSespie.Fa SIMPLEQ_HEAD
6740868d64cSespiestructure is declared as follows:
6750868d64cSespie.Bd -literal -offset indent
6760868d64cSespieSIMPLEQ_HEAD(HEADNAME, TYPE) head;
6770868d64cSespie.Ed
678431305c8Saaron.Pp
6790868d64cSespiewhere
6800868d64cSespie.Fa HEADNAME
6810868d64cSespieis the name of the structure to be defined, and struct
6820868d64cSespie.Fa TYPE
6830868d64cSespieis the type of the elements to be linked into the queue.
6840868d64cSespieA pointer to the head of the queue can later be declared as:
6850868d64cSespie.Bd -literal -offset indent
6860868d64cSespiestruct HEADNAME *headp;
6870868d64cSespie.Ed
688431305c8Saaron.Pp
6890868d64cSespie(The names
6900868d64cSespie.Li head
6910868d64cSespieand
6920868d64cSespie.Li headp
6930868d64cSespieare user selectable.)
6940868d64cSespie.Pp
6950868d64cSespieThe
6960868d64cSespie.Fn SIMPLEQ_ENTRY
6970868d64cSespiemacro declares a structure that connects the elements in
6980868d64cSespiethe queue.
6990868d64cSespie.Pp
7000868d64cSespieThe
7010868d64cSespie.Fn SIMPLEQ_INIT
7020868d64cSespiemacro initializes the queue referenced by
7030868d64cSespie.Fa head .
7040868d64cSespie.Pp
7050868d64cSespieThe queue can also be initialized statically by using the
7060868d64cSespie.Fn SIMPLEQ_HEAD_INITIALIZER
7070868d64cSespiemacro like this:
7080868d64cSespie.Bd -literal -offset indent
7090868d64cSespieSIMPLEQ_HEAD(HEADNAME, TYPE) head = SIMPLEQ_HEAD_INITIALIZER(head);
7100868d64cSespie.Ed
7110868d64cSespie.Pp
7120868d64cSespieThe
71361f9916fSnaddy.Fn SIMPLEQ_INSERT_AFTER
71461f9916fSnaddymacro inserts the new element
71561f9916fSnaddy.Fa elm
71661f9916fSnaddyafter the element
71761f9916fSnaddy.Fa listelm .
71861f9916fSnaddy.Pp
71961f9916fSnaddyThe
7200868d64cSespie.Fn SIMPLEQ_INSERT_HEAD
7210868d64cSespiemacro inserts the new element
7220868d64cSespie.Fa elm
7230868d64cSespieat the head of the queue.
7240868d64cSespie.Pp
7250868d64cSespieThe
7260868d64cSespie.Fn SIMPLEQ_INSERT_TAIL
7270868d64cSespiemacro inserts the new element
7280868d64cSespie.Fa elm
7290868d64cSespieat the end of the queue.
7300868d64cSespie.Pp
7310868d64cSespieThe
73261f9916fSnaddy.Fn SIMPLEQ_REMOVE_AFTER
73361f9916fSnaddymacro removes the queue element immediately following
73461f9916fSnaddy.Fa elm .
7350868d64cSespie.Pp
7360868d64cSespieThe
7370868d64cSespie.Fn SIMPLEQ_REMOVE_HEAD
7380868d64cSespiemacro removes the first element
7390868d64cSespiefrom the queue.
7400868d64cSespie.Pp
7410868d64cSespieThe
74244ab62a3Smillert.Fn SIMPLEQ_CONCAT
74344ab62a3Smillertmacro concatenates all the elements of the queue referenced by
74444ab62a3Smillert.Fa head2
74544ab62a3Smillertto the end of the queue referenced by
74644ab62a3Smillert.Fa head1 ,
74744ab62a3Smillertemptying
74844ab62a3Smillert.Fa head2
74944ab62a3Smillertin the process.
75044ab62a3SmillertThis is more efficient than removing and inserting the individual elements
75144ab62a3Smillertas it does not actually traverse
75244ab62a3Smillert.Fa head2 .
75344ab62a3Smillert.Pp
75444ab62a3SmillertThe
755cc405d09Sjmc.Fn SIMPLEQ_FIRST
7560868d64cSespieand
7570868d64cSespie.Fn SIMPLEQ_NEXT
7580868d64cSespiemacros can be used to traverse the queue.
7599237eaaaSespieThe
7609237eaaaSespie.Fn SIMPLEQ_FOREACH
761*4bc2832dSnaddymacro is used for queue traversal:
7629237eaaaSespie.Bd -literal -offset indent
7635479c038SguentherSIMPLEQ_FOREACH(np, head, FIELDNAME)
7649237eaaaSespie.Ed
7659237eaaaSespie.Pp
766658b0e47SbluhmThe macro
767658b0e47Sbluhm.Fn SIMPLEQ_FOREACH_SAFE
768658b0e47Sbluhmtraverses the queue referenced by head in a
769d2ad55b1Sjmcforward direction, assigning each element in turn to var.
770d2ad55b1SjmcHowever, unlike
771d2ad55b1Sjmc.Fn SIMPLEQ_FOREACH
772d2ad55b1Sjmcit is permitted to remove var as well
7732acff70eSpiroftias free it from within the loop safely without interfering with the traversal.
7742acff70eSpirofti.Pp
7759237eaaaSespieThe
7769237eaaaSespie.Fn SIMPLEQ_EMPTY
7779237eaaaSespiemacro should be used to check whether a list is empty.
7780868d64cSespie.Sh SIMPLE QUEUE EXAMPLE
7790868d64cSespie.Bd -literal
7800868d64cSespieSIMPLEQ_HEAD(listhead, entry) head = SIMPLEQ_HEAD_INITIALIZER(head);
7810868d64cSespiestruct entry {
7820868d64cSespie	...
78335ebeca3Sjmc	SIMPLEQ_ENTRY(entry) entries;	/* Simple queue. */
7840868d64cSespie	...
7850868d64cSespie} *n1, *n2, *np;
7860868d64cSespie
7870868d64cSespien1 = malloc(sizeof(struct entry));	/* Insert at the head. */
7880868d64cSespieSIMPLEQ_INSERT_HEAD(&head, n1, entries);
7890868d64cSespie
7900868d64cSespien2 = malloc(sizeof(struct entry));	/* Insert after. */
791ef699885SjfbSIMPLEQ_INSERT_AFTER(&head, n1, n2, entries);
7920868d64cSespie
7930868d64cSespien2 = malloc(sizeof(struct entry));	/* Insert at the tail. */
7943c2c9ac9SjmcSIMPLEQ_INSERT_TAIL(&head, n2, entries);
7950868d64cSespie					/* Forward traversal. */
7961d29e077SottoSIMPLEQ_FOREACH(np, &head, entries)
7970868d64cSespie	np-> ...
7980868d64cSespie					/* Delete. */
79975fe3d80Sbeckwhile (!SIMPLEQ_EMPTY(&head)) {
80075fe3d80Sbeck	n1 = SIMPLEQ_FIRST(&head);
801ef699885Sjfb	SIMPLEQ_REMOVE_HEAD(&head, entries);
80275fe3d80Sbeck	free(n1);
80375fe3d80Sbeck}
8040868d64cSespie.Ed
8059322932cSmillert.Sh SINGLY-LINKED TAIL QUEUES
8069322932cSmillertA singly-linked tail queue is headed by a structure defined by the
8079322932cSmillert.Fn STAILQ_HEAD
8089322932cSmillertmacro.
8099322932cSmillertThis structure contains a pair of pointers, one to the first element in
8109322932cSmillertthe tail queue and the other to the last element in the tail queue.
8119322932cSmillertThe elements are singly linked for minimum space and pointer manipulation
8129322932cSmillertoverhead at the expense of O(n) removal for arbitrary elements.
8139322932cSmillertNew elements can be added to the tail queue after an existing element,
8149322932cSmillertat the head of the tail queue or at the end of the tail queue.
8159322932cSmillertA
8169322932cSmillert.Fa STAILQ_HEAD
8179322932cSmillertstructure is declared as follows:
8189322932cSmillert.Bd -literal -offset indent
8199322932cSmillertSTAILQ_HEAD(HEADNAME, TYPE) head;
8209322932cSmillert.Ed
8219322932cSmillert.Pp
8229322932cSmillertwhere
8239322932cSmillert.Fa HEADNAME
8249322932cSmillertis the name of the structure to be defined, and struct
8259322932cSmillert.Fa TYPE
8269322932cSmillertis the type of the elements to be linked into the tail queue.
8279322932cSmillertA pointer to the head of the tail queue can later be declared as:
8289322932cSmillert.Bd -literal -offset indent
8299322932cSmillertstruct HEADNAME *headp;
8309322932cSmillert.Ed
8319322932cSmillert.Pp
8329322932cSmillert(The names
8339322932cSmillert.Li head
8349322932cSmillertand
8359322932cSmillert.Li headp
8369322932cSmillertare user selectable.)
8379322932cSmillert.Pp
8389322932cSmillertThe
8399322932cSmillert.Fn STAILQ_ENTRY
8409322932cSmillertmacro declares a structure that connects the elements in
8419322932cSmillertthe tail queue.
8429322932cSmillert.Pp
8439322932cSmillertThe
8449322932cSmillert.Fn STAILQ_INIT
8459322932cSmillertmacro initializes the tail queue referenced by
8469322932cSmillert.Fa head .
8479322932cSmillert.Pp
8489322932cSmillertThe tail queue can also be initialized statically by using the
8499322932cSmillert.Fn STAILQ_HEAD_INITIALIZER
8509322932cSmillertmacro like this:
8519322932cSmillert.Bd -literal -offset indent
8529322932cSmillertSTAILQ_HEAD(HEADNAME, TYPE) head = STAILQ_HEAD_INITIALIZER(head);
8539322932cSmillert.Ed
8549322932cSmillert.Pp
8559322932cSmillertThe
8569322932cSmillert.Fn STAILQ_INSERT_AFTER
8579322932cSmillertmacro inserts the new element
8589322932cSmillert.Fa elm
8599322932cSmillertafter the element
8609322932cSmillert.Fa listelm .
8619322932cSmillert.Pp
8629322932cSmillertThe
8639322932cSmillert.Fn STAILQ_INSERT_HEAD
8649322932cSmillertmacro inserts the new element
8659322932cSmillert.Fa elm
8669322932cSmillertat the head of the tail queue.
8679322932cSmillert.Pp
8689322932cSmillertThe
8699322932cSmillert.Fn STAILQ_INSERT_TAIL
8709322932cSmillertmacro inserts the new element
8719322932cSmillert.Fa elm
8729322932cSmillertat the end of the tail queue.
8739322932cSmillert.Pp
8749322932cSmillertThe
8759322932cSmillert.Fn STAILQ_REMOVE_AFTER
8769322932cSmillertmacro removes the queue element immediately following
8779322932cSmillert.Fa elm .
8789322932cSmillertUnlike
8799322932cSmillert.Fa STAILQ_REMOVE ,
8809322932cSmillertthis macro does not traverse the entire tail queue.
8819322932cSmillert.Pp
8829322932cSmillertThe
8839322932cSmillert.Fn STAILQ_REMOVE_HEAD
8849322932cSmillertmacro removes the first element
8859322932cSmillertfrom the tail queue.
8869322932cSmillertFor optimum efficiency,
8879322932cSmillertelements being removed from the head of the tail queue should
8889322932cSmillertuse this macro explicitly rather than the generic
8899322932cSmillert.Fa STAILQ_REMOVE
8909322932cSmillertmacro.
8919322932cSmillert.Pp
8929322932cSmillertThe
8939322932cSmillert.Fn STAILQ_REMOVE
8949322932cSmillertmacro removes the element
8959322932cSmillert.Fa elm
8969322932cSmillertfrom the tail queue.
8979322932cSmillertUse of this macro should be avoided as it traverses the entire list.
8989322932cSmillertA doubly-linked tail queue should be used if this macro is needed in
8999322932cSmillerthigh-usage code paths or to operate on long tail queues.
9009322932cSmillert.Pp
9019322932cSmillertThe
9029322932cSmillert.Fn STAILQ_CONCAT
9039322932cSmillertmacro concatenates all the elements of the tail queue referenced by
9049322932cSmillert.Fa head2
9059322932cSmillertto the end of the tail queue referenced by
9069322932cSmillert.Fa head1 ,
9079322932cSmillertemptying
9089322932cSmillert.Fa head2
9099322932cSmillertin the process.
9109322932cSmillertThis is more efficient than removing and inserting the individual elements
9119322932cSmillertas it does not actually traverse
9129322932cSmillert.Fa head2 .
9139322932cSmillert.Pp
9149322932cSmillertThe
9159322932cSmillert.Fn STAILQ_FOREACH
916*4bc2832dSnaddymacro is used for queue traversal:
9179322932cSmillert.Bd -literal -offset indent
9189322932cSmillertSTAILQ_FOREACH(np, head, FIELDNAME)
9199322932cSmillert.Ed
9209322932cSmillert.Pp
9219322932cSmillertThe macro
9229322932cSmillert.Fn STAILQ_FOREACH_SAFE
9239322932cSmillerttraverses the queue referenced by head in a
9249322932cSmillertforward direction, assigning each element in turn to var.
9259322932cSmillertHowever, unlike
9269322932cSmillert.Fn STAILQ_FOREACH
9279322932cSmillertit is permitted to remove var as well
9289322932cSmillertas free it from within the loop safely without interfering with the traversal.
9299322932cSmillert.Pp
9309322932cSmillertThe
9313fd951e6Snaddy.Fn STAILQ_FIRST ,
9329322932cSmillert.Fn STAILQ_NEXT ,
9339322932cSmillertand
9349322932cSmillert.Fn STAILQ_LAST
9359322932cSmillertmacros can be used to manually traverse a tail queue or an arbitrary part of
9369322932cSmillertone.
9379322932cSmillertThe
9389322932cSmillert.Fn STAILQ_EMPTY
9399322932cSmillertmacro should be used to check whether a tail queue is empty.
9409322932cSmillert.Sh SINGLY-LINKED TAIL QUEUE EXAMPLE
9419322932cSmillert.Bd -literal
9429322932cSmillertSTAILQ_HEAD(listhead, entry) head = STAILQ_HEAD_INITIALIZER(head);
9439322932cSmillertstruct entry {
9449322932cSmillert	...
9459322932cSmillert	STAILQ_ENTRY(entry) entries;	/* Singly-linked tail queue. */
9469322932cSmillert	...
9479322932cSmillert} *n1, *n2, *np;
9489322932cSmillert
9499322932cSmillertn1 = malloc(sizeof(struct entry));	/* Insert at the head. */
9509322932cSmillertSTAILQ_INSERT_HEAD(&head, n1, entries);
9519322932cSmillert
9529322932cSmillertn2 = malloc(sizeof(struct entry));	/* Insert at the tail. */
9539322932cSmillertSTAILQ_INSERT_TAIL(&head, n2, entries);
9549322932cSmillert
9559322932cSmillertn2 = malloc(sizeof(struct entry));	/* Insert after. */
9569322932cSmillertSTAILQ_INSERT_AFTER(&head, n1, n2, entries);
9579322932cSmillert
9589322932cSmillert					/* Deletion. */
9599322932cSmillertSTAILQ_REMOVE(&head, n2, entry, entries);
9609322932cSmillertfree(n2);
9619322932cSmillert					/* Deletion from the head. */
9629322932cSmillertn3 = STAILQ_FIRST(&head);
9639322932cSmillertSTAILQ_REMOVE_HEAD(&head, entries);
9649322932cSmillertfree(n3);
9659322932cSmillert					/* Forward traversal. */
9669322932cSmillertSTAILQ_FOREACH(np, &head, entries)
9679322932cSmillert	np-> ...
9689322932cSmillert					/* Safe forward traversal. */
9699322932cSmillertSTAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
9709322932cSmillert	np-> ...
9719322932cSmillert	STAILQ_REMOVE(&head, np, entry, entries);
9729322932cSmillert	free(np);
9739322932cSmillert}
9749322932cSmillert					/* Delete. */
9759322932cSmillertwhile (!STAILQ_EMPTY(&head)) {
9769322932cSmillert	n1 = STAILQ_FIRST(&head);
9779322932cSmillert	STAILQ_REMOVE_HEAD(&head, entries);
9789322932cSmillert	free(n1);
9799322932cSmillert}
9809322932cSmillert.Ed
981df930be7Sderaadt.Sh TAIL QUEUES
982df930be7SderaadtA tail queue is headed by a structure defined by the
983f33e0097Saaron.Fn TAILQ_HEAD
984df930be7Sderaadtmacro.
985df930be7SderaadtThis structure contains a pair of pointers,
986df930be7Sderaadtone to the first element in the tail queue and the other to
987df930be7Sderaadtthe last element in the tail queue.
988df930be7SderaadtThe elements are doubly linked so that an arbitrary element can be
989df930be7Sderaadtremoved without traversing the tail queue.
990df930be7SderaadtNew elements can be added to the queue after an existing element,
991df930be7Sderaadtbefore an existing element, at the head of the queue, or at the end
992b9d2958cSaaronof the queue.
993df930be7SderaadtA
994df930be7Sderaadt.Fa TAILQ_HEAD
995df930be7Sderaadtstructure is declared as follows:
996df930be7Sderaadt.Bd -literal -offset indent
997df930be7SderaadtTAILQ_HEAD(HEADNAME, TYPE) head;
998df930be7Sderaadt.Ed
999431305c8Saaron.Pp
1000df930be7Sderaadtwhere
1001f33e0097Saaron.Fa HEADNAME
10020868d64cSespieis the name of the structure to be defined, and struct
1003f33e0097Saaron.Fa TYPE
1004df930be7Sderaadtis the type of the elements to be linked into the tail queue.
1005df930be7SderaadtA pointer to the head of the tail queue can later be declared as:
1006df930be7Sderaadt.Bd -literal -offset indent
1007df930be7Sderaadtstruct HEADNAME *headp;
1008df930be7Sderaadt.Ed
1009431305c8Saaron.Pp
1010df930be7Sderaadt(The names
1011df930be7Sderaadt.Li head
1012df930be7Sderaadtand
1013df930be7Sderaadt.Li headp
1014df930be7Sderaadtare user selectable.)
1015df930be7Sderaadt.Pp
1016f33e0097SaaronThe
1017f33e0097Saaron.Fn TAILQ_ENTRY
1018f33e0097Saaronmacro declares a structure that connects the elements in
1019df930be7Sderaadtthe tail queue.
1020df930be7Sderaadt.Pp
1021f33e0097SaaronThe
1022f33e0097Saaron.Fn TAILQ_INIT
1023f33e0097Saaronmacro initializes the tail queue referenced by
1024df930be7Sderaadt.Fa head .
1025df930be7Sderaadt.Pp
10260868d64cSespieThe tail queue can also be initialized statically by using the
10270868d64cSespie.Fn TAILQ_HEAD_INITIALIZER
10280868d64cSespiemacro.
10290868d64cSespie.Pp
1030f33e0097SaaronThe
1031f33e0097Saaron.Fn TAILQ_INSERT_HEAD
1032f33e0097Saaronmacro inserts the new element
1033df930be7Sderaadt.Fa elm
1034df930be7Sderaadtat the head of the tail queue.
1035df930be7Sderaadt.Pp
1036f33e0097SaaronThe
1037f33e0097Saaron.Fn TAILQ_INSERT_TAIL
1038f33e0097Saaronmacro inserts the new element
1039df930be7Sderaadt.Fa elm
1040df930be7Sderaadtat the end of the tail queue.
1041df930be7Sderaadt.Pp
1042f33e0097SaaronThe
1043f33e0097Saaron.Fn TAILQ_INSERT_AFTER
1044f33e0097Saaronmacro inserts the new element
1045df930be7Sderaadt.Fa elm
1046df930be7Sderaadtafter the element
1047df930be7Sderaadt.Fa listelm .
1048df930be7Sderaadt.Pp
1049f33e0097SaaronThe
1050f33e0097Saaron.Fn TAILQ_INSERT_BEFORE
1051f33e0097Saaronmacro inserts the new element
1052df930be7Sderaadt.Fa elm
1053df930be7Sderaadtbefore the element
1054df930be7Sderaadt.Fa listelm .
1055df930be7Sderaadt.Pp
1056f33e0097SaaronThe
1057f33e0097Saaron.Fn TAILQ_REMOVE
1058f33e0097Saaronmacro removes the element
1059df930be7Sderaadt.Fa elm
1060df930be7Sderaadtfrom the tail queue.
10610868d64cSespie.Pp
106228601b65SjmcThe
106328601b65Sjmc.Fn TAILQ_REPLACE
106428601b65Sjmcmacro replaces the list element
106528601b65Sjmc.Fa elm
106628601b65Sjmcwith the new element
106728601b65Sjmc.Fa elm2 .
106828601b65Sjmc.Pp
106944ab62a3SmillertThe
107044ab62a3Smillert.Fn TAILQ_CONCAT
107144ab62a3Smillertmacro concatenates all the elements of the tail queue referenced by
107244ab62a3Smillert.Fa head2
107344ab62a3Smillertto the end of the tail queue referenced by
107444ab62a3Smillert.Fa head1 ,
107544ab62a3Smillertemptying
107644ab62a3Smillert.Fa head2
107744ab62a3Smillertin the process.
107844ab62a3SmillertThis is more efficient than removing and inserting the individual elements
107944ab62a3Smillertas it does not actually traverse
108044ab62a3Smillert.Fa head2 .
108144ab62a3Smillert.Pp
1082c79a4dd8Skrw.Fn TAILQ_FOREACH
1083c79a4dd8Skrwand
1084c79a4dd8Skrw.Fn TAILQ_FOREACH_REVERSE
1085c79a4dd8Skrware used for traversing a tail queue.
1086c79a4dd8Skrw.Fn TAILQ_FOREACH
1087c79a4dd8Skrwstarts at the first element and proceeds towards the last.
1088c79a4dd8Skrw.Fn TAILQ_FOREACH_REVERSE
1089c79a4dd8Skrwstarts at the last element and proceeds towards the first.
1090c79a4dd8Skrw.Bd -literal -offset indent
10915479c038SguentherTAILQ_FOREACH(np, &head, FIELDNAME)
10925479c038SguentherTAILQ_FOREACH_REVERSE(np, &head, HEADNAME, FIELDNAME)
1093c79a4dd8Skrw.Ed
1094c79a4dd8Skrw.Pp
1095d2ad55b1SjmcThe macros
1096d2ad55b1Sjmc.Fn TAILQ_FOREACH_SAFE
1097d2ad55b1Sjmcand
1098d2ad55b1Sjmc.Fn TAILQ_FOREACH_REVERSE_SAFE
1099d2ad55b1Sjmctraverse the list referenced by head
1100d2ad55b1Sjmcin a forward or reverse direction respectively,
1101d2ad55b1Sjmcassigning each element in turn to var.
1102d2ad55b1SjmcHowever, unlike their unsafe counterparts,
1103d2ad55b1Sjmcthey permit both the removal of var
1104d2ad55b1Sjmcas well as freeing it from within the loop safely
1105d2ad55b1Sjmcwithout interfering with the traversal.
11062acff70eSpirofti.Pp
11070868d64cSespieThe
11088a784db4Smillert.Fn TAILQ_FIRST ,
11090868d64cSespie.Fn TAILQ_NEXT ,
11100868d64cSespie.Fn TAILQ_LAST
11110868d64cSespieand
11120868d64cSespie.Fn TAILQ_PREV
1113c79a4dd8Skrwmacros can be used to manually traverse a tail queue or an arbitrary part of
1114c79a4dd8Skrwone.
1115c9cbb67dSderaadt.Pp
1116c9cbb67dSderaadtThe
11179237eaaaSespie.Fn TAILQ_EMPTY
11189237eaaaSespiemacro should be used to check whether a tail queue is empty.
1119df930be7Sderaadt.Sh TAIL QUEUE EXAMPLE
1120df930be7Sderaadt.Bd -literal
1121df930be7SderaadtTAILQ_HEAD(tailhead, entry) head;
1122df930be7Sderaadtstruct entry {
1123df930be7Sderaadt	...
1124df930be7Sderaadt	TAILQ_ENTRY(entry) entries;	/* Tail queue. */
1125df930be7Sderaadt	...
1126df930be7Sderaadt} *n1, *n2, *np;
1127df930be7Sderaadt
11280b0b405fSaaronTAILQ_INIT(&head);			/* Initialize queue. */
1129df930be7Sderaadt
1130df930be7Sderaadtn1 = malloc(sizeof(struct entry));	/* Insert at the head. */
1131df930be7SderaadtTAILQ_INSERT_HEAD(&head, n1, entries);
1132df930be7Sderaadt
1133df930be7Sderaadtn1 = malloc(sizeof(struct entry));	/* Insert at the tail. */
1134df930be7SderaadtTAILQ_INSERT_TAIL(&head, n1, entries);
1135df930be7Sderaadt
1136df930be7Sderaadtn2 = malloc(sizeof(struct entry));	/* Insert after. */
1137df930be7SderaadtTAILQ_INSERT_AFTER(&head, n1, n2, entries);
1138df930be7Sderaadt
1139df930be7Sderaadtn2 = malloc(sizeof(struct entry));	/* Insert before. */
1140df930be7SderaadtTAILQ_INSERT_BEFORE(n1, n2, entries);
1141df930be7Sderaadt					/* Forward traversal. */
1142c79a4dd8SkrwTAILQ_FOREACH(np, &head, entries)
1143c79a4dd8Skrw	np-> ...
1144c6072168Sjmc					/* Manual forward traversal. */
1145c79a4dd8Skrwfor (np = n2; np != NULL; np = TAILQ_NEXT(np, entries))
1146df930be7Sderaadt	np-> ...
1147df930be7Sderaadt					/* Delete. */
1148b1475358Shaesbaertwhile ((np = TAILQ_FIRST(&head))) {
11499ed04d0aSprovos	TAILQ_REMOVE(&head, np, entries);
115075fe3d80Sbeck	free(np);
115175fe3d80Sbeck}
115275fe3d80Sbeck
1153df930be7Sderaadt.Ed
1154b9af1e79Sjmc.Sh SEE ALSO
1155b9af1e79Sjmc.Xr tree 3
11560868d64cSespie.Sh NOTES
11571d29e077SottoIt is an error to assume the next and previous fields are preserved
11581d29e077Sottoafter an element has been removed from a list or queue.
11591d29e077SottoUsing any macro (except the various forms of insertion) on an element
11601d29e077Sottoremoved from a list or queue is incorrect.
11611d29e077SottoAn example of erroneous usage is removing the same element twice.
11621d29e077Sotto.Pp
11630868d64cSespieThe
11649237eaaaSespie.Fn SLIST_END ,
11650868d64cSespie.Fn LIST_END ,
11669322932cSmillert.Fn SIMPLEQ_END ,
11679322932cSmillert.Fn STAILQ_END
11680868d64cSespieand
11690868d64cSespie.Fn TAILQ_END
1170b9b58a6dSguenthermacros are deprecated; they provided symmetry with the historical
1171b9b58a6dSguenther.Fn CIRCLEQ_END
1172b9b58a6dSguentherand just expand to
1173b9b58a6dSguenther.Dv NULL .
11749237eaaaSespie.Pp
11759237eaaaSespieTrying to free a list in the following way is a common error:
11769237eaaaSespie.Bd -literal -offset indent
11779237eaaaSespieLIST_FOREACH(var, head, entry)
11789237eaaaSespie	free(var);
11799237eaaaSespiefree(head);
11809237eaaaSespie.Ed
11815d436663Sderaadt.Pp
11829237eaaaSespieSince
11839237eaaaSespie.Va var
1184658b0e47Sbluhmis free'd, the FOREACH macros refer to a pointer that may have been
1185658b0e47Sbluhmreallocated already.
11861d29e077SottoA similar situation occurs when the current element is deleted
11871d29e077Sottofrom the list.
11882acff70eSpiroftiIn cases like these the data structure's FOREACH_SAFE macros should be used
11892acff70eSpiroftiinstead.
1190df930be7Sderaadt.Sh HISTORY
1191df930be7SderaadtThe
1192df930be7Sderaadt.Nm queue
1193a873166dSmickeyfunctions first appeared in
1194a873166dSmickey.Bx 4.4 .
1195b9b58a6dSguentherThe historical circle queue macros were deprecated in
1196b9b58a6dSguenther.Ox 5.5 .
1197