queue(3)
NAME
SLIST_EMPTY, SLIST_ENTRY, SLIST_FIRST, SLIST_FOREACH,
SLIST_FOREACH_SAFE
SLIST_HEAD, SLIST_HEAD_INITIALIZER, SLIST_INIT,
SLIST_INSERT_AFTER
SLIST_INSERT_HEAD, SLIST_NEXT, SLIST_REMOVE_HEAD,
SLIST_REMOVE
STAILQ_CONCAT, STAILQ_EMPTY, STAILQ_ENTRY, STAILQ_FIRST,
STAILQ_FOREACH
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_HEAD, STAILQ_REMOVE, LIST_EMPTY,
LIST_ENTRY
LIST_FIRST, LIST_FOREACH, LIST_FOREACH_SAFE, LIST_HEAD, LIST_HEAD_INITIALIZER, LIST_INIT, LIST_INSERT_AFTER,
LIST_INSERT_BEFORE
LIST_INSERT_HEAD, LIST_NEXT, LIST_REMOVE, TAILQ_CONCAT,
TAILQ_EMPTY
TAILQ_ENTRY, TAILQ_FIRST, TAILQ_FOREACH, TAILQ_FOREACH_SAFE, TAILQ_FOREACH_REVERSE, TAILQ_FOREACH_REVERSE_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 - implementations of
- singly-linked
lists, singly-linked tail queues, lists and tail queues
SYNOPSIS
#include <sys/queue.h> SLIST_EMPTY(SLIST_HEAD *head); SLIST_ENTRY(TYPE); SLIST_FIRST(SLIST_HEAD *head); SLIST_FOREACH(TYPE *var, SLIST_HEAD *head, SLIST_ENTRY NAME); SLIST_FOREACH_SAFE(TYPE *var, SLIST_HEAD *head, SLIST_ENTRY NAME, TYPE *temp_var); SLIST_HEAD(HEADNAME, TYPE); SLIST_HEAD_INITIALIZER(SLIST_HEAD head); SLIST_INIT(SLIST_HEAD *head); SLIST_INSERT_AFTER(TYPE *listelm, TYPE *elm, SLIST_ENTRY NAME); SLIST_INSERT_HEAD(SLIST_HEAD *head, TYPE *elm, SLIST_ENTRY NAME); SLIST_NEXT(TYPE *elm, SLIST_ENTRY NAME); SLIST_REMOVE_HEAD(SLIST_HEAD *head, SLIST_ENTRY NAME); SLIST_REMOVE(SLIST_HEAD *head, TYPE *elm, TYPE, SLIST_ENTRY NAME); STAILQ_CONCAT(STAILQ_HEAD *head1, STAILQ_HEAD *head2); STAILQ_EMPTY(STAILQ_HEAD *head); STAILQ_ENTRY(TYPE); STAILQ_FIRST(STAILQ_HEAD *head); STAILQ_FOREACH(TYPE *var, STAILQ_HEAD *head, STAILQ_ENTRY NAME); STAILQ_FOREACH_SAFE(TYPE *var, STAILQ_HEAD *head, STAILQ_ENTRY NAME, TYPE *temp_var); STAILQ_HEAD(HEADNAME, TYPE); STAILQ_HEAD_INITIALIZER(STAILQ_HEAD head); STAILQ_INIT(STAILQ_HEAD *head); STAILQ_INSERT_AFTER(STAILQ_HEAD *head, TYPE *listelm, TYPE *elm, STAILQ_ENTRY NAME); STAILQ_INSERT_HEAD(STAILQ_HEAD *head, TYPE *elm, STAILQ_ENTRY NAME); STAILQ_INSERT_TAIL(STAILQ_HEAD *head, TYPE *elm, STAILQ_ENTRY NAME); STAILQ_LAST(STAILQ_HEAD *head, TYPE, STAILQ_ENTRY NAME); STAILQ_NEXT(TYPE *elm, STAILQ_ENTRY NAME); STAILQ_REMOVE_HEAD(STAILQ_HEAD *head, STAILQ_ENTRY NAME); STAILQ_REMOVE(STAILQ_HEAD *head, TYPE *elm, TYPE, STAILQ_ENTRY NAME); LIST_EMPTY(LIST_HEAD *head); LIST_ENTRY(TYPE); LIST_FIRST(LIST_HEAD *head); LIST_FOREACH(TYPE *var, LIST_HEAD *head, LIST_ENTRY NAME); LIST_FOREACH_SAFE(TYPE *var, LIST_HEAD *head, LIST_ENTRY NAME, TYPE *temp_var); LIST_HEAD(HEADNAME, TYPE); LIST_HEAD_INITIALIZER(LIST_HEAD head); LIST_INIT(LIST_HEAD *head); LIST_INSERT_AFTER(TYPE *listelm, TYPE *elm, LIST_ENTRY NAME); LIST_INSERT_BEFORE(TYPE *listelm, TYPE *elm, LIST_ENTRY NAME); LIST_INSERT_HEAD(LIST_HEAD *head, TYPE *elm, LIST_ENTRY NAME); LIST_NEXT(TYPE *elm, LIST_ENTRY NAME); LIST_REMOVE(TYPE *elm, LIST_ENTRY NAME); TAILQ_CONCAT(TAILQ_HEAD *head1, TAILQ_HEAD *head2, TAILQ_ENTRY NAME); TAILQ_EMPTY(TAILQ_HEAD *head); TAILQ_ENTRY(TYPE); TAILQ_FIRST(TAILQ_HEAD *head); TAILQ_FOREACH(TYPE *var, TAILQ_HEAD *head, TAILQ_ENTRY NAME); TAILQ_FOREACH_SAFE(TYPE *var, TAILQ_HEAD *head, TAILQ_ENTRY NAME, TYPE *temp_var); TAILQ_FOREACH_REVERSE(TYPE *var, TAILQ_HEAD *head, HEADNAME, TAILQ_ENTRY NAME); TAILQ_FOREACH_REVERSE_SAFE(TYPE *var, TAILQ_HEAD *head, HEADNAME, TAILQ_ENTRY NAME, TYPE *temp_var); TAILQ_HEAD(HEADNAME, TYPE); TAILQ_HEAD_INITIALIZER(TAILQ_HEAD head); TAILQ_INIT(TAILQ_HEAD *head); TAILQ_INSERT_AFTER(TAILQ_HEAD *head, TYPE *listelm, TYPE *elm, TAILQ_ENTRY NAME); TAILQ_INSERT_BEFORE(TYPE *listelm, TYPE *elm, TAILQ_ENTRY NAME); TAILQ_INSERT_HEAD(TAILQ_HEAD *head, TYPE *elm, TAILQ_ENTRY NAME); TAILQ_INSERT_TAIL(TAILQ_HEAD *head, TYPE *elm, TAILQ_ENTRY NAME); TAILQ_LAST(TAILQ_HEAD *head, HEADNAME); TAILQ_NEXT(TYPE *elm, TAILQ_ENTRY NAME); TAILQ_PREV(TYPE *elm, HEADNAME, TAILQ_ENTRY NAME); TAILQ_REMOVE(TAILQ_HEAD *head, TYPE *elm, TAILQ_ENTRY NAME);
DESCRIPTION
- These macros define and operate on four types of data struc
- tures: singlylinked lists, singly-linked tail queues, lists, and tail
- queues. All
four structures support the following functionality:
1. Insertion of a new entry at the head of the list.
2. Insertion of a new entry after any element in the - list.
3. O(1) removal of an entry from the head of the - list.
4. O(n) removal of any entry in the list.
5. Forward traversal through the list. - Singly-linked lists are the simplest of the four data struc
- tures and support only the above functionality. Singly-linked lists are
- ideal for
applications with large datasets and few or no removals, or - for implementing a LIFO queue.
- Singly-linked tail queues add the following functionality:
1. Entries can be added at the end of a list.
2. They may be concatenated. - However:
1. All list insertions must specify the head of the - list.
2. Each head entry requires two pointers rather than - one.
3. Code size is about 15% greater and operations run - about 20%
slower than singly-linked lists. - Singly-linked tailqs are ideal for applications with large
- datasets and
few or no removals, or for implementing a FIFO queue. - All doubly linked types of data structures (lists and tail
- queues) additionally allow:
1. Insertion of a new entry before any element in - the list.
2. O(1) removal of any entry in the list. - However:
1. Each elements requires two pointers rather than - one.
2. Code size and execution time of operations (ex - cept for
removal) is about twice that of the singly-linked - data-structures.
- Linked lists are the simplest of the doubly linked data
- structures and
support only the above functionality over singly-linked - lists.
- Tail queues add the following functionality:
1. Entries can be added at the end of a list.
2. They may be traversed backwards, from tail to - head.
3. They may be concatenated. - However:
1. All list insertions and removals must specify the - head of the
list. - 2. Each head entry requires two pointers rather than
- one.
3. Code size is about 15% greater and operations run - about 20%
slower than singly-linked lists. - In the macro definitions, TYPE is the name of a user defined
- structure,
that must contain a field of type SLIST_ENTRY, STAILQ_ENTRY, - LIST_ENTRY,
or TAILQ_ENTRY, named NAME. The argument HEADNAME is the - name of a user
defined structure that must be declared using the macros - SLIST_HEAD,
STAILQ_HEAD, LIST_HEAD, or TAILQ_HEAD. See the examples be - low for further explanation of how these macros are used.
SINGLY-LINKED LISTS
A singly-linked list is headed by a structure defined by the
SLIST_HEAD
- macro. This structure contains a single pointer to the
- first element on
the list. The elements are singly linked for minimum space - and pointer
manipulation overhead at the expense of O(n) removal for ar - bitrary elements. New elements can be added to the list after an ex
- isting element
or at the head of the list. An SLIST_HEAD structure is de - clared as follows:
SLIST_HEAD(HEADNAME, TYPE) head;- where HEADNAME is the name of the structure to be defined,
- and TYPE is
the type of the elements to be linked into the list. A - pointer to the
head of the list can later be declared as:
struct HEADNAME *headp;- (The names head and headp are user selectable.)
- The macro SLIST_HEAD_INITIALIZER evaluates to an initializer
- for the list
head. - The macro SLIST_EMPTY evaluates to true if there are no ele
- ments in the
list. - The macro SLIST_ENTRY declares a structure that connects the
- elements in
the list. - The macro SLIST_FIRST returns the first element in the list
- or NULL if
the list is empty. - The macro SLIST_FOREACH traverses the list referenced by
- head in the forward direction, assigning each element in turn to var.
- The macro SLIST_FOREACH_SAFE traverses the list referenced
- by head in the
forward direction, assigning each element in turn to var. - However,
unlike SLIST_FOREACH() here it is permitted to both remove - var as well as
free it from within the loop safely without interfering with - the traversal.
- The macro SLIST_INIT initializes the list referenced by
- head.
- The macro SLIST_INSERT_HEAD inserts the new element elm at
- the head of
the list. - The macro SLIST_INSERT_AFTER inserts the new element elm af
- ter the element listelm.
- The macro SLIST_NEXT returns the next element in the list.
- The macro SLIST_REMOVE_HEAD removes the element elm from the
- head of the
list. For optimum efficiency, elements being removed from - the head of
the list should explicitly use this macro instead of the - generic
SLIST_REMOVE macro. - The macro SLIST_REMOVE removes the element elm from the
- list.
SINGLY-LINKED LIST EXAMPLE
- SLIST_HEAD(slisthead, entry) head =
- SLIST_HEAD_INITIALIZER(head);
- struct slisthead *headp; /* Singly-linked
- List head. */
struct entry {
...
SLIST_ENTRY(entry) entries; /* Singly-linked - List. */
... - } *n1, *n2, *n3, *np;
- SLIST_INIT(&head); /* Initialize the
- list. */
- n1 = malloc(sizeof(struct entry)); /* Insert at the
- head. */
SLIST_INSERT_HEAD(&head, n1, entries); - n2 = malloc(sizeof(struct entry)); /* Insert after. */
SLIST_INSERT_AFTER(n1, n2, entries); - SLIST_REMOVE(&head, n2, entry, entries);/* Deletion. */
free(n2); - n3 = SLIST_FIRST(&head);
SLIST_REMOVE_HEAD(&head, entries); /* Deletion from the - head. */
free(n3);/* Forward traver - sal. */
- SLIST_FOREACH(np, &head, entries)
np-> ...
/* Safe forward - traversal. */
- SLIST_FOREACH_SAFE(np, &head, entries, np_temp) {
np->do_stuff();
...
SLIST_REMOVE(&head, np, entry, entries);
free(np); - }
- while (!SLIST_EMPTY(&head)) { /* List Deletion. */
n1 = SLIST_FIRST(&head);
SLIST_REMOVE_HEAD(&head, entries);
free(n1); - }
SINGLY-LINKED TAIL QUEUES
- A singly-linked tail queue is headed by a structure defined
- by the
STAILQ_HEAD macro. This structure contains a pair of point - ers, 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 STAILQ_HEAD structure is declared as follows:
STAILQ_HEAD(HEADNAME, TYPE) head;- where HEADNAME is the name of the structure to be defined,
- and 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:
struct HEADNAME *headp;- (The names head and headp are user selectable.)
- The macro STAILQ_HEAD_INITIALIZER evaluates to an initializ
- er for the
tail queue head. - The macro STAILQ_CONCAT concatenates the tail queue headed
- by head2 onto
the end of the one headed by head1 removing all entries from - the former.
- The macro STAILQ_EMPTY evaluates to true if there are no
- items on the
tail queue. - The macro STAILQ_ENTRY declares a structure that connects
- the elements in
the tail queue. - The macro STAILQ_FIRST returns the first item on the tail
- queue or NULL
if the tail queue is empty. - The macro STAILQ_FOREACH traverses the tail queue referenced
- by head in
the forward direction, assigning each element in turn to - var.
- The macro STAILQ_FOREACH_SAFE traverses the tail queue ref
- erenced by head
in the forward direction, assigning each element in turn to - var. However, unlike STAILQ_FOREACH() here it is permitted to both
- remove var as
well as free it from within the loop safely without inter - fering with the
traversal. - The macro STAILQ_INIT initializes the tail queue referenced
- by head.
- The macro STAILQ_INSERT_HEAD inserts the new element elm at
- the head of
the tail queue. - The macro STAILQ_INSERT_TAIL inserts the new element elm at
- the end of
the tail queue. - The macro STAILQ_INSERT_AFTER inserts the new element elm
- after the element listelm.
- The macro STAILQ_LAST returns the last item on the tail
- queue. If the
tail queue is empty the return value is undefined. - The macro STAILQ_NEXT returns the next item on the tail
- queue, or NULL
this item is the last. - The macro 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
STAILQ_REMOVE macro. - The macro STAILQ_REMOVE removes the element elm from the
- tail queue.
SINGLY-LINKED TAIL QUEUE EXAMPLE
- STAILQ_HEAD(stailhead, entry) head =
- STAILQ_HEAD_INITIALIZER(head);
- struct stailhead *headp; /* Singly-linked
- tail queue head. */
struct entry {
...
STAILQ_ENTRY(entry) entries; /* Tail queue. */
... - } *n1, *n2, *n3, *np;
- 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);
/* Deletion. */ - STAILQ_REMOVE(&head, n2, entry, entries);
free(n2);
/* Deletion from the - head. */
- n3 = STAILQ_FIRST(&head);
STAILQ_REMOVE_HEAD(&head, entries);
free(n3);/* Forward traver - sal. */
- STAILQ_FOREACH(np, &head, entries)
np-> ...
/* Safe forward - traversal. */
- STAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
np->do_stuff();
...
STAILQ_REMOVE(&head, np, entry, entries);
free(np); - }
/* TailQ Deletion. - */
- while (!STAILQ_EMPTY(&head)) {
n1 = STAILQ_FIRST(&head);
STAILQ_REMOVE_HEAD(&head, entries);
free(n1); - }
/* Faster TailQ - Deletion. */
- n1 = STAILQ_FIRST(&head);
while (n1 != NULL) {
n2 = STAILQ_NEXT(n1, entries);
free(n1);
n1 = n2; - }
STAILQ_INIT(&head);
LISTS
- A list is headed by a structure defined by the LIST_HEAD
- macro. This
structure contains a single pointer to the first element on - the list.
The elements are doubly linked so that an arbitrary element - can be
removed without traversing the list. New elements can be - added to the
list after an existing element, before an existing element, - or at the
head of the list. A LIST_HEAD structure is declared as fol - lows:
LIST_HEAD(HEADNAME, TYPE) head;- where HEADNAME is the name of the structure to be defined,
- and TYPE is
the type of the elements to be linked into the list. A - pointer to the
head of the list can later be declared as:
struct HEADNAME *headp;- (The names head and headp are user selectable.)
- The macro LIST_HEAD_INITIALIZER evaluates to an initializer
- for the list
head. - The macro LIST_EMPTY evaluates to true if there are no ele
- ments in the
list. - The macro LIST_ENTRY declares a structure that connects the
- elements in
the list. - The macro LIST_FIRST returns the first element in the list
- or NULL if the
list is empty. - The macro LIST_FOREACH traverses the list referenced by head
- in the forward direction, assigning each element in turn to var.
- The macro LIST_FOREACH_SAFE traverses the list referenced by
- head in the
forward direction, assigning each element in turn to var. - However,
unlike LIST_FOREACH() here it is permitted to both remove - var as well as
free it from within the loop safely without interfering with - the traversal.
- The macro LIST_INIT initializes the list referenced by head.
- The macro LIST_INSERT_HEAD inserts the new element elm at
- the head of the
list. - The macro LIST_INSERT_AFTER inserts the new element elm af
- ter the element
listelm. - The macro LIST_INSERT_BEFORE inserts the new element elm be
- fore the element listelm.
- The macro LIST_NEXT returns the next element in the list, or
- NULL if this
is the last. - The macro LIST_REMOVE removes the element elm from the list.
LIST EXAMPLE
- LIST_HEAD(listhead, entry) head =
- LIST_HEAD_INITIALIZER(head);
- struct listhead *headp; /* List head. */
struct entry {
...
LIST_ENTRY(entry) entries; /* List. */
... - } *n1, *n2, *n3, *np, *np_temp;
- LIST_INIT(&head); /* Initialize the
- list. */
- n1 = malloc(sizeof(struct entry)); /* Insert at the
- head. */
LIST_INSERT_HEAD(&head, n1, entries); - n2 = malloc(sizeof(struct entry)); /* Insert after. */
LIST_INSERT_AFTER(n1, n2, entries); - n3 = malloc(sizeof(struct entry)); /* Insert before. */
LIST_INSERT_BEFORE(n2, n3, entries); - LIST_REMOVE(n2, entries); /* Deletion. */
free(n2);/* Forward traver - sal. */
- LIST_FOREACH(np, &head, entries)
np-> ...
/* Safe forward- traversal. */
- LIST_FOREACH_SAFE(np, &head, entries, np_temp) {
np->do_stuff();
...
LIST_REMOVE(np, entries);
free(np); - }
- while (!LIST_EMPTY(&head)) { /* List Deletion. */
n1 = LIST_FIRST(&head);
LIST_REMOVE(n1, entries);
free(n1); - }
- n1 = LIST_FIRST(&head); /* Faster List Dele
- tion. */
while (n1 != NULL) {
n2 = LIST_NEXT(n1, entries);
free(n1);
n1 = n2; - }
LIST_INIT(&head);
TAIL QUEUES
A tail queue is headed by a structure defined by the
TAILQ_HEAD
- 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 doubly linked so that an arbitrary element can - be removed
without traversing the tail queue. New elements can be - added to the tail
queue after an existing element, before an existing element, - at the head
of the tail queue, or at the end of the tail queue. A - TAILQ_HEAD structure is declared as follows:
TAILQ_HEAD(HEADNAME, TYPE) head;- where HEADNAME is the name of the structure to be defined,
- and 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:
struct HEADNAME *headp;- (The names head and headp are user selectable.)
- The macro TAILQ_HEAD_INITIALIZER evaluates to an initializer
- for the tail
queue head. - The macro TAILQ_CONCAT concatenates the tail queue headed by
- head2 onto
the end of the one headed by head1 removing all entries from - the former.
- The macro TAILQ_EMPTY evaluates to true if there are no
- items on the tail
queue. - The macro TAILQ_ENTRY declares a structure that connects the
- elements in
the tail queue. - The macro TAILQ_FIRST returns the first item on the tail
- queue or NULL if
the tail queue is empty. - The macro TAILQ_FOREACH traverses the tail queue referenced
- by head in
the forward direction, assigning each element in turn to - var. var is set
to NULL if the loop completes normally, or if there were no - elements.
- The macro TAILQ_FOREACH_REVERSE traverses the tail queue
- referenced by
head in the reverse direction, assigning each element in - turn to var.
- The macros TAILQ_FOREACH_SAFE and TAILQ_FOREACH_REVERSE_SAFE
- traverse the
list referenced by head in the forward or reverse direction - respectively,
assigning each element in turn to var. However, unlike - their unsafe
counterparts, TAILQ_FOREACH and TAILQ_FOREACH_REVERSE permit - to both
remove var as well as free it from within the loop safely - without interfering with the traversal.
- The macro TAILQ_INIT initializes the tail queue referenced
- by head.
- The macro TAILQ_INSERT_HEAD inserts the new element elm at
- the head of
the tail queue. - The macro TAILQ_INSERT_TAIL inserts the new element elm at
- the end of the
tail queue. - The macro TAILQ_INSERT_AFTER inserts the new element elm af
- ter the element listelm.
- The macro TAILQ_INSERT_BEFORE inserts the new element elm
- before the element listelm.
- The macro TAILQ_LAST returns the last item on the tail
- queue. If the
tail queue is empty the return value is undefined. - The macro TAILQ_NEXT returns the next item on the tail
- queue, or NULL if
this item is the last. - The macro TAILQ_PREV returns the previous item on the tail
- queue, or NULL
if this item is the first. - The macro TAILQ_REMOVE removes the element elm from the tail
- queue.
TAIL QUEUE EXAMPLE
- TAILQ_HEAD(tailhead, entry) head =
- TAILQ_HEAD_INITIALIZER(head);
- struct tailhead *headp; /* Tail queue head.
- */
struct entry {
...
TAILQ_ENTRY(entry) entries; /* Tail queue. */
... - } *n1, *n2, *n3, *np;
- 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 traver - sal. */
- TAILQ_FOREACH(np, &head, entries)
np-> ...
/* Safe forward - traversal. */
- TAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
np->do_stuff();
...
TAILQ_REMOVE(&head, np, entries);
free(np); - }/* Reverse traver
- sal. */
- TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries)
np-> ...
/* TailQ Deletion. - */
- while (!TAILQ_EMPTY(&head)) {
n1 = TAILQ_FIRST(&head);
TAILQ_REMOVE(&head, n1, entries);
free(n1); - }
/* Faster TailQ - Deletion. */
- n1 = TAILQ_FIRST(&head);
while (n1 != NULL) {
n2 = TAILQ_NEXT(n1, entries);
free(n1);
n1 = n2; - }
TAILQ_INIT(&head);
HISTORY
- The queue functions first appeared in 4.4BSD.
- BSD January 24, 1994