diff options
Diffstat (limited to 'man3/tailq.3')
-rw-r--r-- | man3/tailq.3 | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/man3/tailq.3 b/man3/tailq.3 new file mode 100644 index 0000000..15f9203 --- /dev/null +++ b/man3/tailq.3 @@ -0,0 +1,397 @@ +.\" Copyright (c) 1993 +.\" The Regents of the University of California. All rights reserved. +.\" and Copyright (c) 2020 by Alejandro Colomar <alx@kernel.org> +.\" +.\" SPDX-License-Identifier: BSD-3-Clause +.\" +.\" +.TH TAILQ 3 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +TAILQ_CONCAT, +TAILQ_EMPTY, +TAILQ_ENTRY, +TAILQ_FIRST, +TAILQ_FOREACH, +.\"TAILQ_FOREACH_FROM, +.\"TAILQ_FOREACH_FROM_SAFE, +TAILQ_FOREACH_REVERSE, +.\"TAILQ_FOREACH_REVERSE_FROM, +.\"TAILQ_FOREACH_REVERSE_FROM_SAFE, +.\"TAILQ_FOREACH_REVERSE_SAFE, +.\"TAILQ_FOREACH_SAFE, +TAILQ_HEAD, +TAILQ_HEAD_INITIALIZER, +TAILQ_INIT, +TAILQ_INSERT_AFTER, +TAILQ_INSERT_BEFORE, +TAILQ_INSERT_HEAD, +TAILQ_INSERT_TAIL, +TAILQ_LAST, +TAILQ_NEXT, +TAILQ_PREV, +TAILQ_REMOVE +.\"TAILQ_SWAP +\- implementation of a doubly linked tail queue +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.B #include <sys/queue.h> +.PP +.B TAILQ_ENTRY(TYPE); +.PP +.B TAILQ_HEAD(HEADNAME, TYPE); +.BI "TAILQ_HEAD TAILQ_HEAD_INITIALIZER(TAILQ_HEAD " head ); +.BI "void TAILQ_INIT(TAILQ_HEAD *" head ); +.PP +.BI "int TAILQ_EMPTY(TAILQ_HEAD *" head ); +.PP +.BI "void TAILQ_INSERT_HEAD(TAILQ_HEAD *" head , +.BI " struct TYPE *" elm ", TAILQ_ENTRY " NAME ); +.BI "void TAILQ_INSERT_TAIL(TAILQ_HEAD *" head , +.BI " struct TYPE *" elm ", TAILQ_ENTRY " NAME ); +.BI "void TAILQ_INSERT_BEFORE(struct TYPE *" listelm , +.BI " struct TYPE *" elm ", TAILQ_ENTRY " NAME ); +.BI "void TAILQ_INSERT_AFTER(TAILQ_HEAD *" head ", struct TYPE *" listelm , +.BI " struct TYPE *" elm ", TAILQ_ENTRY " NAME ); +.PP +.BI "struct TYPE *TAILQ_FIRST(TAILQ_HEAD *" head ); +.BI "struct TYPE *TAILQ_LAST(TAILQ_HEAD *" head ", HEADNAME);" +.BI "struct TYPE *TAILQ_PREV(struct TYPE *" elm ", HEADNAME, TAILQ_ENTRY " NAME ); +.BI "struct TYPE *TAILQ_NEXT(struct TYPE *" elm ", TAILQ_ENTRY " NAME ); +.PP +.BI "TAILQ_FOREACH(struct TYPE *" var ", TAILQ_HEAD *" head , +.BI " TAILQ_ENTRY " NAME ); +.\" .BI "TAILQ_FOREACH_FROM(struct TYPE *" var ", TAILQ_HEAD *" head , +.\" .BI " TAILQ_ENTRY " NAME ); +.BI "TAILQ_FOREACH_REVERSE(struct TYPE *" var ", TAILQ_HEAD *" head ", HEADNAME," +.BI " TAILQ_ENTRY " NAME ); +.\" .BI "TAILQ_FOREACH_REVERSE_FROM(struct TYPE *" var ", TAILQ_HEAD *" head ", HEADNAME," +.\" .BI " TAILQ_ENTRY " NAME ); +.\" .PP +.\" .BI "TAILQ_FOREACH_SAFE(struct TYPE *" var ", TAILQ_HEAD *" head , +.\" .BI " TAILQ_ENTRY " NAME , +.\" .BI " struct TYPE *" temp_var ); +.\" .BI "TAILQ_FOREACH_FROM_SAFE(struct TYPE *" var ", TAILQ_HEAD *" head , +.\" .BI " TAILQ_ENTRY " NAME , +.\" .BI " struct TYPE *" temp_var ); +.\" .BI "TAILQ_FOREACH_REVERSE_SAFE(struct TYPE *" var ", TAILQ_HEAD *" head , +.\" .BI " HEADNAME, TAILQ_ENTRY " NAME , +.\" .BI " struct TYPE *" temp_var ); +.\" .BI "TAILQ_FOREACH_REVERSE_FROM_SAFE(struct TYPE *" var ", TAILQ_HEAD *" head , +.\" .BI " HEADNAME, TAILQ_ENTRY " NAME , +.\" .BI " struct TYPE *" temp_var ); +.PP +.BI "void TAILQ_REMOVE(TAILQ_HEAD *" head ", struct TYPE *" elm , +.BI " TAILQ_ENTRY " NAME ); +.PP +.BI "void TAILQ_CONCAT(TAILQ_HEAD *" head1 ", TAILQ_HEAD *" head2 , +.BI " TAILQ_ENTRY " NAME ); +.\" .BI "void TAILQ_SWAP(TAILQ_HEAD *" head1 ", TAILQ_HEAD *" head2 ", TYPE," +.\" .BI " TAILQ_ENTRY " NAME ); +.fi +.SH DESCRIPTION +These macros define and operate on doubly 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 TAILQ_ENTRY , +named +.IR NAME . +The argument +.I HEADNAME +is the name of a user defined structure that must be declared +using the macro +.BR TAILQ_HEAD (). +.SS Creation +A tail queue is headed by a structure defined by the +.BR TAILQ_HEAD () +macro. +This structure contains a pair of pointers, +one to the first element in the queue +and the other to the last element in the queue. +The elements are doubly linked +so that an arbitrary element can be removed without traversing the queue. +New elements can be added to the queue +after an existing element, +before an existing element, +at the head of the queue, +or at the end of the queue. +A +.I TAILQ_HEAD +structure is declared as follows: +.PP +.in +4 +.EX +TAILQ_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 queue. +A pointer to the head of the 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 TAILQ_ENTRY () +declares a structure that connects the elements in the queue. +.PP +.BR TAILQ_HEAD_INITIALIZER () +evaluates to an initializer for the queue +.IR head . +.PP +.BR TAILQ_INIT () +initializes the queue referenced by +.PP +.BR TAILQ_EMPTY () +evaluates to true if there are no items on the queue. +.IR head . +.SS Insertion +.BR TAILQ_INSERT_HEAD () +inserts the new element +.I elm +at the head of the queue. +.PP +.BR TAILQ_INSERT_TAIL () +inserts the new element +.I elm +at the end of the queue. +.PP +.BR TAILQ_INSERT_BEFORE () +inserts the new element +.I elm +before the element +.IR listelm . +.PP +.BR TAILQ_INSERT_AFTER () +inserts the new element +.I elm +after the element +.IR listelm . +.SS Traversal +.BR TAILQ_FIRST () +returns the first item on the queue, or NULL if the queue is empty. +.PP +.BR TAILQ_LAST () +returns the last item on the queue. +If the queue is empty the return value is NULL. +.PP +.BR TAILQ_PREV () +returns the previous item on the queue, or NULL if this item is the first. +.PP +.BR TAILQ_NEXT () +returns the next item on the queue, or NULL if this item is the last. +.PP +.BR TAILQ_FOREACH () +traverses the queue referenced by +.I head +in the forward direction, +assigning each element in turn to +.IR var . +.I var +is set to NULL if the loop completes normally, +or if there were no elements. +.\" .PP +.\" .BR TAILQ_FOREACH_FROM () +.\" behaves identically to +.\" .BR TAILQ_FOREACH () +.\" when +.\" .I var +.\" is NULL, else it treats +.\" .I var +.\" as a previously found TAILQ element and begins the loop at +.\" .I var +.\" instead of the first element in the TAILQ referenced by +.\" .IR head . +.PP +.BR TAILQ_FOREACH_REVERSE () +traverses the queue referenced by +.I head +in the reverse direction, +assigning each element in turn to +.IR var . +.\" .PP +.\" .BR TAILQ_FOREACH_REVERSE_FROM () +.\" behaves identically to +.\" .BR TAILQ_FOREACH_REVERSE () +.\" when +.\" .I var +.\" is NULL, else it treats +.\" .I var +.\" as a previously found TAILQ element and begins the reverse loop at +.\" .I var +.\" instead of the last element in the TAILQ referenced by +.\" .IR head . +.\" .PP +.\" .BR TAILQ_FOREACH_SAFE () +.\" and +.\" .BR TAILQ_FOREACH_REVERSE_SAFE () +.\" traverse the list referenced by +.\" .I head +.\" in the forward or reverse direction respectively, +.\" assigning each element in turn to +.\" .IR var . +.\" However, unlike their unsafe counterparts, +.\" .BR TAILQ_FOREACH () +.\" and +.\" .BR TAILQ_FOREACH_REVERSE () +.\" permit to both remove +.\" .I var +.\" as well as free it from within the loop safely without interfering with the +.\" traversal. +.\" .PP +.\" .BR TAILQ_FOREACH_FROM_SAFE () +.\" behaves identically to +.\" .BR TAILQ_FOREACH_SAFE () +.\" when +.\" .I var +.\" is NULL, else it treats +.\" .I var +.\" as a previously found TAILQ element and begins the loop at +.\" .I var +.\" instead of the first element in the TAILQ referenced by +.\" .IR head . +.\" .PP +.\" .BR TAILQ_FOREACH_REVERSE_FROM_SAFE () +.\" behaves identically to +.\" .BR TAILQ_FOREACH_REVERSE_SAFE () +.\" when +.\" .I var +.\" is NULL, else it treats +.\" .I var +.\" as a previously found TAILQ element and begins the reverse loop at +.\" .I var +.\" instead of the last element in the TAILQ referenced by +.\" .IR head . +.SS Removal +.BR TAILQ_REMOVE () +removes the element +.I elm +from the queue. +.SS Other features +.\" .BR TAILQ_SWAP () +.\" swaps the contents of +.\" .I head1 +.\" and +.\" .IR head2 . +.\" .PP +.BR TAILQ_CONCAT () +concatenates the queue headed by +.I head2 +onto the end of the one headed by +.I head1 +removing all entries from the former. +.SH RETURN VALUE +.BR TAILQ_EMPTY () +returns nonzero if the queue is empty, +and zero if the queue contains at least one entry. +.PP +.BR TAILQ_FIRST (), +.BR TAILQ_LAST (), +.BR TAILQ_PREV (), +and +.BR TAILQ_NEXT () +return a pointer to the first, last, previous, or next +.I TYPE +structure, respectively. +.PP +.BR TAILQ_HEAD_INITIALIZER () +returns an initializer that can be assigned to the queue +.IR head . +.SH STANDARDS +BSD. +.SH HISTORY +4.4BSD. +.SH CAVEATS +.BR TAILQ_FOREACH () +and +.BR TAILQ_FOREACH_REVERSE () +don't allow +.I var +to be removed or freed within the loop, +as it would interfere with the traversal. +.BR TAILQ_FOREACH_SAFE () +and +.BR TAILQ_FOREACH_REVERSE_SAFE (), +which are present on the BSDs but are not present in glibc, +fix 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 EXAMPLES +.\" SRC BEGIN (tailq.c) +.EX +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/queue.h> +\& +struct entry { + int data; + TAILQ_ENTRY(entry) entries; /* Tail queue */ +}; +\& +TAILQ_HEAD(tailhead, entry); +\& +int +main(void) +{ + struct entry *n1, *n2, *n3, *np; + struct tailhead head; /* Tail queue head */ + int i; +\& + TAILQ_INIT(&head); /* Initialize the queue */ +\& + n1 = malloc(sizeof(struct entry)); /* Insert at the head */ + TAILQ_INSERT_HEAD(&head, n1, entries); +\& + n1 = malloc(sizeof(struct entry)); /* Insert at the tail */ + TAILQ_INSERT_TAIL(&head, n1, entries); +\& + n2 = malloc(sizeof(struct entry)); /* Insert after */ + TAILQ_INSERT_AFTER(&head, n1, n2, entries); +\& + n3 = malloc(sizeof(struct entry)); /* Insert before */ + TAILQ_INSERT_BEFORE(n2, n3, entries); +\& + TAILQ_REMOVE(&head, n2, entries); /* Deletion */ + free(n2); + /* Forward traversal */ + i = 0; + TAILQ_FOREACH(np, &head, entries) + np\->data = i++; + /* Reverse traversal */ + TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries) + printf("%i\en", np\->data); + /* TailQ deletion */ + n1 = TAILQ_FIRST(&head); + while (n1 != NULL) { + n2 = TAILQ_NEXT(n1, entries); + free(n1); + n1 = n2; + } + TAILQ_INIT(&head); +\& + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR insque (3), +.BR queue (7) |