#include <sys/queue.h>
LIST_ENTRY(TYPE);
LIST_HEAD(HEADNAME, TYPE);
LIST_INIT(LIST_HEAD *head);
LIST_INSERT_AFTER(LIST_ENTRY *listelm,
TYPE *elm, LIST_ENTRY NAME);
LIST_INSERT_HEAD(LIST_HEAD *head,
TYPE *elm, LIST_ENTRY NAME);
LIST_REMOVE(TYPE *elm, LIST_ENTRY NAME);
TAILQ_ENTRY(TYPE);
TAILQ_HEAD(HEADNAME, TYPE);
TAILQ_INIT(TAILQ_HEAD *head);
TAILQ_INSERT_AFTER(TAILQ_HEAD *head, 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_REMOVE(TAILQ_HEAD *head, TYPE *elm, TAILQ_ENTRY NAME);
CIRCLEQ_ENTRY(TYPE);
CIRCLEQ_HEAD(HEADNAME, TYPE);
CIRCLEQ_INIT(CIRCLEQ_HEAD *head);
CIRCLEQ_INSERT_AFTER(CIRCLEQ_HEAD *head, TYPE *listelm,
TYPE *elm, CIRCLEQ_ENTRY NAME);
CIRCLEQ_INSERT_BEFORE(CIRCLEQ_HEAD *head, TYPE *listelm,
TYPE *elm, CIRCLEQ_ENTRY NAME);
CIRCLEQ_INSERT_HEAD(CIRCLEQ_HEAD *head,
TYPE *elm, CIRCLEQ_ENTRY NAME);
CIRCLEQ_INSERT_TAIL(CIRCLEQ_HEAD *head,
TYPE *elm, CIRCLEQ_ENTRY NAME);
CIRCLEQ_REMOVE(CIRCLEQ_HEAD *head,
TYPE *elm, CIRCLEQ_ENTRY NAME);
Lists are the simplest of the three data structures and support only the above functionality.
Tail queues add the following functionality:
However:
Circular queues add the following functionality:
However:
In the macro definitions, TYPE is the name of a user-defined structure, that must contain a field of type LIST_ENTRY, TAILQ_ENTRY, or CIRCLEQ_ENTRY, named NAME. The argument HEADNAME is the name of a user-defined structure that must be declared using the macros LIST_HEAD, TAILQ_HEAD, or CIRCLEQ_HEAD. See the examples below for further explanation of how these macros are used.
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_ENTRY declares a structure that connects the elements in the list.
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 after the element listelm.
The macro LIST_REMOVE removes the element elm from the list.
LIST_HEAD(listhead, entry) head;
struct listhead *headp; /* List head. */
struct entry {
...
LIST_ENTRY(entry) entries; /* List. */
...
} *n1, *n2, *np;
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);
/* Forward traversal. */
for (np = head.lh_first; np != NULL; np = np->entries.le_next)
np-> ...
while (head.lh_first != NULL) /* Delete. */
LIST_REMOVE(head.lh_first, entries);
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_ENTRY declares a structure that connects the elements in the tail queue.
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 after the element listelm.
The macro TAILQ_REMOVE removes the element elm from the tail queue.
TAILQ_HEAD(tailhead, entry) head;
struct tailhead *headp; /* Tail queue head. */
struct entry {
...
TAILQ_ENTRY(entry) entries; /* Tail queue. */
...
} *n1, *n2, *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);
/* Forward traversal. */
for (np = head.tqh_first; np != NULL; np = np->entries.tqe_next)
np-> ...
/* Delete. */
while (head.tqh_first != NULL)
TAILQ_REMOVE(&head, head.tqh_first, entries);
CIRCLEQ_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 circular queue. A pointer to the head of the circular queue can later be declared as:
struct HEADNAME *headp;
(The names head and headp are user selectable.)
The macro CIRCLEQ_ENTRY declares a structure that connects the elements in the circular queue.
The macro CIRCLEQ_INIT initializes the circular queue referenced by head.
The macro CIRCLEQ_INSERT_HEAD inserts the new element elm at the head of the circular queue.
The macro CIRCLEQ_INSERT_TAIL inserts the new element elm at the end of the circular queue.
The macro CIRCLEQ_INSERT_AFTER inserts the new element elm after the element listelm.
The macro CIRCLEQ_INSERT_BEFORE inserts the new element elm before the element listelm.
The macro CIRCLEQ_REMOVE removes the element elm from the circular queue.
CIRCLEQ_HEAD(circleq, entry) head;
struct circleq *headp; /* Circular queue head. */
struct entry {
...
CIRCLEQ_ENTRY(entry) entries; /* Circular queue. */
...
} *n1, *n2, *np;
CIRCLEQ_INIT(&head); /* Initialize the circular queue. */
n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
CIRCLEQ_INSERT_HEAD(&head, n1, entries);
n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */
CIRCLEQ_INSERT_TAIL(&head, n1, entries);
n2 = malloc(sizeof(struct entry)); /* Insert after. */
CIRCLEQ_INSERT_AFTER(&head, n1, n2, entries);
n2 = malloc(sizeof(struct entry)); /* Insert before. */
CIRCLEQ_INSERT_BEFORE(&head, n1, n2, entries);
/* Forward traversal. */
for (np = head.cqh_first; np != (void *)&head;
np = np->entries.cqe_next)
np-> ...
/* Reverse traversal. */
for (np = head.cqh_last; np != (void *)&head; np = np->entries.cqe_prev)
np-> ...
/* Delete. */
while (head.cqh_first != (void *)&head)
CIRCLEQ_REMOVE(&head, head.cqh_first, entries);