| .\" Copyright (c) 1993 |
| .\" The Regents of the University of California. All rights reserved. |
| .\" and Copyright (c) 2020 by Alejandro Colomar <colomar.6.4.3@gmail.com> |
| .\" |
| .\" %%%LICENSE_START(BSD_3_CLAUSE_UCB) |
| .\" Redistribution and use in source and binary forms, with or without |
| .\" modification, are permitted provided that the following conditions |
| .\" are met: |
| .\" 1. Redistributions of source code must retain the above copyright |
| .\" notice, this list of conditions and the following disclaimer. |
| .\" 2. Redistributions in binary form must reproduce the above copyright |
| .\" notice, this list of conditions and the following disclaimer in the |
| .\" documentation and/or other materials provided with the distribution. |
| .\" 3. Neither the name of the University nor the names of its contributors |
| .\" may be used to endorse or promote products derived from this software |
| .\" without specific prior written permission. |
| .\" |
| .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| .\" SUCH DAMAGE. |
| .\" %%%LICENSE_END |
| .\" |
| .\" |
| .TH STAILQ 3 2021-03-22 "GNU" "Linux Programmer's Manual" |
| .SH NAME |
| .\"SIMPLEQ_CONCAT, |
| SIMPLEQ_EMPTY, |
| SIMPLEQ_ENTRY, |
| SIMPLEQ_FIRST, |
| SIMPLEQ_FOREACH, |
| .\"SIMPLEQ_FOREACH_FROM, |
| .\"SIMPLEQ_FOREACH_FROM_SAFE, |
| .\"SIMPLEQ_FOREACH_SAFE, |
| SIMPLEQ_HEAD, |
| SIMPLEQ_HEAD_INITIALIZER, |
| SIMPLEQ_INIT, |
| SIMPLEQ_INSERT_AFTER, |
| SIMPLEQ_INSERT_HEAD, |
| SIMPLEQ_INSERT_TAIL, |
| .\"SIMPLEQ_LAST, |
| SIMPLEQ_NEXT, |
| SIMPLEQ_REMOVE, |
| .\"SIMPLEQ_REMOVE_AFTER, |
| SIMPLEQ_REMOVE_HEAD, |
| .\"SIMPLEQ_SWAP, |
| STAILQ_CONCAT, |
| STAILQ_EMPTY, |
| STAILQ_ENTRY, |
| STAILQ_FIRST, |
| STAILQ_FOREACH, |
| .\"STAILQ_FOREACH_FROM, |
| .\"STAILQ_FOREACH_FROM_SAFE, |
| .\"STAILQ_FOREACH_SAFE, |
| STAILQ_HEAD, |
| STAILQ_HEAD_INITIALIZER, |
| STAILQ_INIT, |
| STAILQ_INSERT_AFTER, |
| STAILQ_INSERT_HEAD, |
| STAILQ_INSERT_TAIL, |
| .\"STAILQ_LAST, |
| STAILQ_NEXT, |
| STAILQ_REMOVE, |
| .\"STAILQ_REMOVE_AFTER, |
| STAILQ_REMOVE_HEAD, |
| .\"STAILQ_SWAP |
| \- implementation of a singly linked tail queue |
| .SH SYNOPSIS |
| .nf |
| .B #include <sys/queue.h> |
| .PP |
| .B STAILQ_ENTRY(TYPE); |
| .PP |
| .B STAILQ_HEAD(HEADNAME, TYPE); |
| .BI "STAILQ_HEAD STAILQ_HEAD_INITIALIZER(STAILQ_HEAD " head ); |
| .BI "void STAILQ_INIT(STAILQ_HEAD *" head ); |
| .PP |
| .BI "int STAILQ_EMPTY(STAILQ_HEAD *" head ); |
| .PP |
| .BI "void STAILQ_INSERT_HEAD(STAILQ_HEAD *" head , |
| .BI " struct TYPE *" elm ", STAILQ_ENTRY " NAME ); |
| .BI "void STAILQ_INSERT_TAIL(STAILQ_HEAD *" head , |
| .BI " struct TYPE *" elm ", STAILQ_ENTRY " NAME ); |
| .BI "void STAILQ_INSERT_AFTER(STAILQ_HEAD *" head ", struct TYPE *" listelm , |
| .BI " struct TYPE *" elm ", STAILQ_ENTRY " NAME ); |
| .PP |
| .BI "struct TYPE *STAILQ_FIRST(STAILQ_HEAD *" head ); |
| .\" .BI "struct TYPE *STAILQ_LAST(STAILQ_HEAD *" head ", struct TYPE *" elm , |
| .\" .BI " STAILQ_ENTRY " NAME ); |
| .BI "struct TYPE *STAILQ_NEXT(struct TYPE *" elm ", STAILQ_ENTRY " NAME ); |
| .PP |
| .BI "STAILQ_FOREACH(struct TYPE *" var ", STAILQ_HEAD *" head ", STAILQ_ENTRY " NAME ); |
| .\" .BI "STAILQ_FOREACH_FROM(struct TYPE *" var ", STAILQ_HEAD *" head , |
| .\" .BI " STAILQ_ENTRY " NAME ); |
| .\" .PP |
| .\" .BI "STAILQ_FOREACH_SAFE(struct TYPE *" var ", STAILQ_HEAD *" head , |
| .\" .BI " STAILQ_ENTRY " NAME ", struct TYPE *" temp_var ); |
| .\" .BI "STAILQ_FOREACH_FROM_SAFE(struct TYPE *" var ", STAILQ_HEAD *" head , |
| .\" .BI " STAILQ_ENTRY " NAME ", struct TYPE *" temp_var ); |
| .PP |
| .BI "void STAILQ_REMOVE(STAILQ_HEAD *" head ", struct TYPE *" elm ", TYPE," |
| .BI " STAILQ_ENTRY " NAME ); |
| .BI "void STAILQ_REMOVE_HEAD(STAILQ_HEAD *" head , |
| .BI " STAILQ_ENTRY " NAME ); |
| .\" .BI "void STAILQ_REMOVE_AFTER(STAILQ_HEAD *" head ", struct TYPE *" elm , |
| .\" .BI " STAILQ_ENTRY " NAME ); |
| .PP |
| .BI "void STAILQ_CONCAT(STAILQ_HEAD *" head1 ", STAILQ_HEAD *" head2 ); |
| .\" .BI "void STAILQ_SWAP(STAILQ_HEAD *" head1 ", STAILQ_HEAD *" head2 , |
| .\" .BI " STAILQ_ENTRY " NAME ); |
| .fi |
| .IR Note : |
| Identical macros prefixed with SIMPLEQ instead of STAILQ exist; see NOTES. |
| .SH DESCRIPTION |
| These macros define and operate on singly linked tail queues. |
| .PP |
| In the macro definitions, |
| .I TYPE |
| is the name of a user-defined structure, |
| that must contain a field of type |
| .IR STAILQ_ENTRY , |
| named |
| .IR NAME . |
| The argument |
| .I HEADNAME |
| is the name of a user-defined structure that must be declared |
| using the macro |
| .BR STAILQ_HEAD (). |
| .SS Creation |
| A singly linked tail queue is headed by a structure defined by the |
| .BR STAILQ_HEAD () |
| macro. |
| This structure contains a pair of pointers, |
| one to the first element in the tail queue and the other to |
| the last element in the tail queue. |
| The elements are singly linked for minimum space and pointer |
| manipulation overhead at the expense of O(n) removal for arbitrary elements. |
| New elements can be added to the tail queue after an existing element, |
| at the head of the tail queue, or at the end of the tail queue. |
| A |
| .I STAILQ_HEAD |
| structure is declared as follows: |
| .PP |
| .in +4 |
| .EX |
| STAILQ_HEAD(HEADNAME, TYPE) head; |
| .EE |
| .in |
| .PP |
| where |
| .I struct HEADNAME |
| is the structure to be defined, and |
| .I struct TYPE |
| is the type of the elements to be linked into the tail queue. |
| A pointer to the head of the tail queue can later be declared as: |
| .PP |
| .in +4 |
| .EX |
| struct HEADNAME *headp; |
| .EE |
| .in |
| .PP |
| (The names |
| .I head |
| and |
| .I headp |
| are user selectable.) |
| .PP |
| .BR STAILQ_ENTRY () |
| declares a structure that connects the elements in the tail queue. |
| .PP |
| .BR STAILQ_HEAD_INITIALIZER () |
| evaluates to an initializer for the tail queue |
| .IR head . |
| .PP |
| .BR STAILQ_INIT () |
| initializes the tail queue referenced by |
| .IR head . |
| .PP |
| .BR STAILQ_EMPTY () |
| evaluates to true if there are no items on the tail queue. |
| .SS Insertion |
| .BR STAILQ_INSERT_HEAD () |
| inserts the new element |
| .I elm |
| at the head of the tail queue. |
| .PP |
| .BR STAILQ_INSERT_TAIL () |
| inserts the new element |
| .I elm |
| at the end of the tail queue. |
| .PP |
| .BR STAILQ_INSERT_AFTER () |
| inserts the new element |
| .I elm |
| after the element |
| .IR listelm . |
| .SS Traversal |
| .BR STAILQ_FIRST () |
| returns the first item on the tail queue or NULL if the tail queue is empty. |
| .\" .PP |
| .\" .BR STAILQ_LAST () |
| .\" returns the last item on the tail queue. |
| .\" If the tail queue is empty the return value is NULL . |
| .PP |
| .BR STAILQ_NEXT () |
| returns the next item on the tail queue, or NULL this item is the last. |
| .PP |
| .BR STAILQ_FOREACH () |
| traverses the tail queue referenced by |
| .I head |
| in the forward direction, |
| assigning each element in turn to |
| .IR var . |
| .\" .PP |
| .\" .BR STAILQ_FOREACH_FROM () |
| .\" behaves identically to |
| .\" .BR STAILQ_FOREACH () |
| .\" when |
| .\" .I var |
| .\" is NULL, else it treats |
| .\" .I var |
| .\" as a previously found STAILQ element and begins the loop at |
| .\" .I var |
| .\" instead of the first element in the STAILQ referenced by |
| .\" .IR head . |
| .\" .PP |
| .\" .BR STAILQ_FOREACH_SAFE () |
| .\" traverses the tail queue referenced by |
| .\" .I head |
| .\" in the forward direction, assigning each element |
| .\" in turn to |
| .\" .IR var . |
| .\" However, unlike |
| .\" .BR STAILQ_FOREACH () |
| .\" here it is permitted to both remove |
| .\" .I var |
| .\" as well as free it from within the loop safely without interfering with the |
| .\" traversal. |
| .\" .PP |
| .\" .BR STAILQ_FOREACH_FROM_SAFE () |
| .\" behaves identically to |
| .\" .BR STAILQ_FOREACH_SAFE () |
| .\" when |
| .\" .I var |
| .\" is NULL, else it treats |
| .\" .I var |
| .\" as a previously found STAILQ element and begins the loop at |
| .\" .I var |
| .\" instead of the first element in the STAILQ referenced by |
| .\" .IR head . |
| .SS Removal |
| .BR STAILQ_REMOVE () |
| removes the element |
| .I elm |
| from the tail queue. |
| .PP |
| .BR STAILQ_REMOVE_HEAD () |
| removes the element at the head of the tail queue. |
| For optimum efficiency, |
| elements being removed from the head of the tail queue should |
| use this macro explicitly rather than the generic |
| .BR STAILQ_REMOVE () |
| macro. |
| .\" .PP |
| .\" .BR STAILQ_REMOVE_AFTER () |
| .\" removes the element after |
| .\" .I elm |
| .\" from the tail queue. |
| .\" Unlike |
| .\" .BR STAILQ_REMOVE (), |
| .\" this macro does not traverse the entire tail queue. |
| .SS Other features |
| .BR STAILQ_CONCAT () |
| concatenates the tail queue headed by |
| .I head2 |
| onto the end of the one headed by |
| .I head1 |
| removing all entries from the former. |
| .\" .PP |
| .\" .BR STAILQ_SWAP () |
| .\" swaps the contents of |
| .\" .I head1 |
| .\" and |
| .\" .IR head2 . |
| .SH RETURN VALUE |
| .BR STAILQ_EMPTY () |
| returns nonzero if the queue is empty, |
| and zero if the queue contains at least one entry. |
| .PP |
| .BR STAILQ_FIRST (), |
| and |
| .BR STAILQ_NEXT () |
| return a pointer to the first or next |
| .I TYPE |
| structure, respectively. |
| .PP |
| .BR STAILQ_HEAD_INITIALIZER () |
| returns an initializer that can be assigned to the queue |
| .IR head . |
| .SH CONFORMING TO |
| Not in POSIX.1, POSIX.1-2001, or POSIX.1-2008. |
| Present on the BSDs |
| (STAILQ macros first appeared in 4.4BSD). |
| .SH BUGS |
| .BR STAILQ_FOREACH () |
| doesn't allow |
| .I var |
| to be removed or freed within the loop, |
| as it would interfere with the traversal. |
| .BR STAILQ_FOREACH_SAFE (), |
| which is present on the BSDs but is not present in glibc, |
| fixes this limitation by allowing |
| .I var |
| to safely be removed from the list and freed from within the loop |
| without interfering with the traversal. |
| .SH NOTES |
| Some BSDs provide SIMPLEQ instead of STAILQ. |
| They are identical, but for historical reasons |
| they were named differently on different BSDs. |
| STAILQ originated on FreeBSD, and SIMPLEQ originated on NetBSD. |
| For compatibility reasons, some systems provide both sets of macros. |
| Glibc provides both STAILQ and SIMPLEQ, |
| which are identical except for a missing SIMPLEQ equivalent to |
| .BR STAILQ_CONCAT (). |
| .SH EXAMPLES |
| .EX |
| #include <stddef.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <sys/queue.h> |
| |
| struct entry { |
| int data; |
| STAILQ_ENTRY(entry) entries; /* Singly linked tail queue */ |
| }; |
| |
| STAILQ_HEAD(stailhead, entry); |
| |
| int |
| main(void) |
| { |
| struct entry *n1, *n2, *n3, *np; |
| struct stailhead head; /* Singly linked tail queue |
| head */ |
| |
| STAILQ_INIT(&head); /* Initialize the queue */ |
| |
| n1 = malloc(sizeof(struct entry)); /* Insert at the head */ |
| STAILQ_INSERT_HEAD(&head, n1, entries); |
| |
| n1 = malloc(sizeof(struct entry)); /* Insert at the tail */ |
| STAILQ_INSERT_TAIL(&head, n1, entries); |
| |
| n2 = malloc(sizeof(struct entry)); /* Insert after */ |
| STAILQ_INSERT_AFTER(&head, n1, n2, entries); |
| |
| STAILQ_REMOVE(&head, n2, entry, entries); /* Deletion */ |
| free(n2); |
| |
| n3 = STAILQ_FIRST(&head); |
| STAILQ_REMOVE_HEAD(&head, entries); /* Deletion from the head */ |
| free(n3); |
| |
| n1 = STAILQ_FIRST(&head); |
| n1\->data = 0; |
| for (int i = 1; i < 5; i++) { |
| n1 = malloc(sizeof(struct entry)); |
| STAILQ_INSERT_HEAD(&head, n1, entries); |
| n1\->data = i; |
| } |
| /* Forward traversal */ |
| STAILQ_FOREACH(np, &head, entries) |
| printf("%i\en", np\->data); |
| /* TailQ deletion */ |
| n1 = STAILQ_FIRST(&head); |
| while (n1 != NULL) { |
| n2 = STAILQ_NEXT(n1, entries); |
| free(n1); |
| n1 = n2; |
| } |
| STAILQ_INIT(&head); |
| |
| exit(EXIT_SUCCESS); |
| } |
| .EE |
| .SH SEE ALSO |
| .BR insque (3), |
| .BR queue (7) |