summaryrefslogtreecommitdiffstats
path: root/man/man3/tailq.3
diff options
context:
space:
mode:
Diffstat (limited to 'man/man3/tailq.3')
-rw-r--r--man/man3/tailq.3397
1 files changed, 397 insertions, 0 deletions
diff --git a/man/man3/tailq.3 b/man/man3/tailq.3
new file mode 100644
index 000000000..ced7b5408
--- /dev/null
+++ b/man/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 (date) "Linux man-pages (unreleased)"
+.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>
+.P
+.B TAILQ_ENTRY(TYPE);
+.P
+.B TAILQ_HEAD(HEADNAME, TYPE);
+.BI "TAILQ_HEAD TAILQ_HEAD_INITIALIZER(TAILQ_HEAD " head );
+.BI "void TAILQ_INIT(TAILQ_HEAD *" head );
+.P
+.BI "int TAILQ_EMPTY(TAILQ_HEAD *" head );
+.P
+.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 );
+.P
+.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 );
+.P
+.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 );
+.\" .P
+.\" .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 );
+.P
+.BI "void TAILQ_REMOVE(TAILQ_HEAD *" head ", struct TYPE *" elm ,
+.BI " TAILQ_ENTRY " NAME );
+.P
+.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.
+.P
+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:
+.P
+.in +4
+.EX
+TAILQ_HEAD(HEADNAME, TYPE) head;
+.EE
+.in
+.P
+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:
+.P
+.in +4
+.EX
+struct HEADNAME *headp;
+.EE
+.in
+.P
+(The names
+.I head
+and
+.I headp
+are user selectable.)
+.P
+.BR TAILQ_ENTRY ()
+declares a structure that connects the elements in the queue.
+.P
+.BR TAILQ_HEAD_INITIALIZER ()
+evaluates to an initializer for the queue
+.IR head .
+.P
+.BR TAILQ_INIT ()
+initializes the queue referenced by
+.P
+.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.
+.P
+.BR TAILQ_INSERT_TAIL ()
+inserts the new element
+.I elm
+at the end of the queue.
+.P
+.BR TAILQ_INSERT_BEFORE ()
+inserts the new element
+.I elm
+before the element
+.IR listelm .
+.P
+.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.
+.P
+.BR TAILQ_LAST ()
+returns the last item on the queue.
+If the queue is empty the return value is NULL.
+.P
+.BR TAILQ_PREV ()
+returns the previous item on the queue, or NULL if this item is the first.
+.P
+.BR TAILQ_NEXT ()
+returns the next item on the queue, or NULL if this item is the last.
+.P
+.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.
+.\" .P
+.\" .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 .
+.P
+.BR TAILQ_FOREACH_REVERSE ()
+traverses the queue referenced by
+.I head
+in the reverse direction,
+assigning each element in turn to
+.IR var .
+.\" .P
+.\" .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 .
+.\" .P
+.\" .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.
+.\" .P
+.\" .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 .
+.\" .P
+.\" .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 .
+.\" .P
+.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.
+.P
+.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.
+.P
+.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)