mirror of
https://gitlab.freedesktop.org/libbsd/libbsd.git
synced 2025-01-09 03:08:38 +01:00
Sync queue(3) from FreeBSD
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85147
This commit is contained in:
parent
3267114483
commit
c7e01e9884
@ -65,7 +65,7 @@
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
* may be traversed in either direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
@ -85,12 +85,16 @@
|
||||
* _EMPTY + + + +
|
||||
* _FIRST + + + +
|
||||
* _NEXT + + + +
|
||||
* _PREV - - - +
|
||||
* _PREV - + - +
|
||||
* _LAST - - + +
|
||||
* _FOREACH + + + +
|
||||
* _FOREACH_FROM + + + +
|
||||
* _FOREACH_SAFE + + + +
|
||||
* _FOREACH_FROM_SAFE + + + +
|
||||
* _FOREACH_REVERSE - - - +
|
||||
* _FOREACH_REVERSE_FROM - - - +
|
||||
* _FOREACH_REVERSE_SAFE - - - +
|
||||
* _FOREACH_REVERSE_FROM_SAFE - - - +
|
||||
* _INSERT_HEAD + + + +
|
||||
* _INSERT_BEFORE - + - +
|
||||
* _INSERT_AFTER + + + +
|
||||
@ -99,19 +103,22 @@
|
||||
* _REMOVE_AFTER + - + -
|
||||
* _REMOVE_HEAD + - + -
|
||||
* _REMOVE + + + +
|
||||
* _SWAP + + + +
|
||||
*
|
||||
*/
|
||||
#ifdef QUEUE_MACRO_DEBUG
|
||||
/* Store the last 2 places the queue element or head was altered */
|
||||
struct qm_trace {
|
||||
char * lastfile;
|
||||
int lastline;
|
||||
char * prevfile;
|
||||
int prevline;
|
||||
unsigned long lastline;
|
||||
unsigned long prevline;
|
||||
const char *lastfile;
|
||||
const char *prevfile;
|
||||
};
|
||||
|
||||
#define TRACEBUF struct qm_trace trace;
|
||||
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
|
||||
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
|
||||
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
|
||||
|
||||
#define QMD_TRACE_HEAD(head) do { \
|
||||
(head)->trace.prevline = (head)->trace.lastline; \
|
||||
@ -130,7 +137,9 @@ struct qm_trace {
|
||||
#else
|
||||
#define QMD_TRACE_ELEM(elem)
|
||||
#define QMD_TRACE_HEAD(head)
|
||||
#define QMD_SAVELINK(name, link)
|
||||
#define TRACEBUF
|
||||
#define TRACEBUF_INITIALIZER
|
||||
#define TRASHIT(x)
|
||||
#endif /* QUEUE_MACRO_DEBUG */
|
||||
|
||||
@ -162,11 +171,21 @@ struct { \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_FOREACH_FROM(var, head, field) \
|
||||
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
|
||||
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
|
||||
for ((varp) = &SLIST_FIRST((head)); \
|
||||
((var) = *(varp)) != NULL; \
|
||||
@ -189,6 +208,7 @@ struct { \
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
@ -198,7 +218,7 @@ struct { \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_REMOVE_AFTER(curelm, field); \
|
||||
} \
|
||||
TRASHIT((elm)->field.sle_next); \
|
||||
TRASHIT(*oldnext); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_AFTER(elm, field) do { \
|
||||
@ -210,6 +230,12 @@ struct { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_SWAP(head1, head2, type) do { \
|
||||
struct type *swap_first = SLIST_FIRST(head1); \
|
||||
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
|
||||
SLIST_FIRST(head2) = swap_first; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
@ -247,12 +273,21 @@ struct { \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_FOREACH_FROM(var, head, field) \
|
||||
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = STAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
|
||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
@ -277,14 +312,13 @@ struct { \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head, type, field) \
|
||||
(STAILQ_EMPTY((head)) ? \
|
||||
NULL : \
|
||||
((struct type *)(void *) \
|
||||
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
|
||||
(STAILQ_EMPTY((head)) ? NULL : \
|
||||
__containerof((head)->stqh_last, struct type, field.stqe_next))
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
@ -294,13 +328,7 @@ struct { \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
STAILQ_REMOVE_AFTER(head, curelm, field); \
|
||||
} \
|
||||
TRASHIT((elm)->field.stqe_next); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
TRASHIT(*oldnext); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
|
||||
@ -309,6 +337,12 @@ struct { \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_SWAP(head1, head2, type) do { \
|
||||
struct type *swap_first = STAILQ_FIRST(head1); \
|
||||
struct type **swap_last = (head1)->stqh_last; \
|
||||
@ -378,11 +412,21 @@ struct { \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_FOREACH_FROM(var, head, field) \
|
||||
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
|
||||
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
@ -414,15 +458,21 @@ struct { \
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_PREV(elm, head, type, field) \
|
||||
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
|
||||
__containerof((elm)->field.le_prev, struct type, field.le_next))
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
|
||||
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
|
||||
QMD_LIST_CHECK_NEXT(elm, field); \
|
||||
QMD_LIST_CHECK_PREV(elm, field); \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
TRASHIT((elm)->field.le_next); \
|
||||
TRASHIT((elm)->field.le_prev); \
|
||||
TRASHIT(*oldnext); \
|
||||
TRASHIT(*oldprev); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_SWAP(head1, head2, type, field) do { \
|
||||
@ -446,7 +496,7 @@ struct name { \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
@ -509,21 +559,41 @@ struct { \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_FROM(var, head, field) \
|
||||
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
|
||||
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
|
||||
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
@ -587,6 +657,8 @@ struct { \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
|
||||
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
|
||||
QMD_TAILQ_CHECK_NEXT(elm, field); \
|
||||
QMD_TAILQ_CHECK_PREV(elm, field); \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
@ -597,8 +669,8 @@ struct { \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
TRASHIT((elm)->field.tqe_next); \
|
||||
TRASHIT((elm)->field.tqe_prev); \
|
||||
TRASHIT(*oldnext); \
|
||||
TRASHIT(*oldprev); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
|
186
man/queue.3bsd
186
man/queue.3bsd
@ -9,7 +9,7 @@
|
||||
.\" 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.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" 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.
|
||||
.\"
|
||||
@ -28,15 +28,17 @@
|
||||
.\" @(#)queue.3 8.2 (Berkeley) 1/24/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 13, 2011
|
||||
.Dt QUEUE 3bsd
|
||||
.Dd June 17, 2013
|
||||
.Dt QUEUE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm SLIST_EMPTY ,
|
||||
.Nm SLIST_ENTRY ,
|
||||
.Nm SLIST_FIRST ,
|
||||
.Nm SLIST_FOREACH ,
|
||||
.Nm SLIST_FOREACH_FROM ,
|
||||
.Nm SLIST_FOREACH_SAFE ,
|
||||
.Nm SLIST_FOREACH_FROM_SAFE ,
|
||||
.Nm SLIST_HEAD ,
|
||||
.Nm SLIST_HEAD_INITIALIZER ,
|
||||
.Nm SLIST_INIT ,
|
||||
@ -52,7 +54,9 @@
|
||||
.Nm STAILQ_ENTRY ,
|
||||
.Nm STAILQ_FIRST ,
|
||||
.Nm STAILQ_FOREACH ,
|
||||
.Nm STAILQ_FOREACH_FROM ,
|
||||
.Nm STAILQ_FOREACH_SAFE ,
|
||||
.Nm STAILQ_FOREACH_FROM_SAFE ,
|
||||
.Nm STAILQ_HEAD ,
|
||||
.Nm STAILQ_HEAD_INITIALIZER ,
|
||||
.Nm STAILQ_INIT ,
|
||||
@ -69,7 +73,9 @@
|
||||
.Nm LIST_ENTRY ,
|
||||
.Nm LIST_FIRST ,
|
||||
.Nm LIST_FOREACH ,
|
||||
.Nm LIST_FOREACH_FROM ,
|
||||
.Nm LIST_FOREACH_SAFE ,
|
||||
.Nm LIST_FOREACH_FROM_SAFE ,
|
||||
.Nm LIST_HEAD ,
|
||||
.Nm LIST_HEAD_INITIALIZER ,
|
||||
.Nm LIST_INIT ,
|
||||
@ -77,6 +83,7 @@
|
||||
.Nm LIST_INSERT_BEFORE ,
|
||||
.Nm LIST_INSERT_HEAD ,
|
||||
.Nm LIST_NEXT ,
|
||||
.Nm LIST_PREV ,
|
||||
.Nm LIST_REMOVE ,
|
||||
.Nm LIST_SWAP ,
|
||||
.Nm TAILQ_CONCAT ,
|
||||
@ -84,9 +91,13 @@
|
||||
.Nm TAILQ_ENTRY ,
|
||||
.Nm TAILQ_FIRST ,
|
||||
.Nm TAILQ_FOREACH ,
|
||||
.Nm TAILQ_FOREACH_FROM ,
|
||||
.Nm TAILQ_FOREACH_SAFE ,
|
||||
.Nm TAILQ_FOREACH_FROM_SAFE ,
|
||||
.Nm TAILQ_FOREACH_REVERSE ,
|
||||
.Nm TAILQ_FOREACH_REVERSE_FROM ,
|
||||
.Nm TAILQ_FOREACH_REVERSE_SAFE ,
|
||||
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE ,
|
||||
.Nm TAILQ_HEAD ,
|
||||
.Nm TAILQ_HEAD_INITIALIZER ,
|
||||
.Nm TAILQ_INIT ,
|
||||
@ -108,7 +119,9 @@ lists and tail queues
|
||||
.Fn SLIST_ENTRY "TYPE"
|
||||
.Fn SLIST_FIRST "SLIST_HEAD *head"
|
||||
.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
|
||||
.Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
|
||||
.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn SLIST_FOREACH_FROM_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn SLIST_HEAD "HEADNAME" "TYPE"
|
||||
.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
|
||||
.Fn SLIST_INIT "SLIST_HEAD *head"
|
||||
@ -125,7 +138,9 @@ lists and tail queues
|
||||
.Fn STAILQ_ENTRY "TYPE"
|
||||
.Fn STAILQ_FIRST "STAILQ_HEAD *head"
|
||||
.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
|
||||
.Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
|
||||
.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn STAILQ_FOREACH_FROM_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn STAILQ_HEAD "HEADNAME" "TYPE"
|
||||
.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
|
||||
.Fn STAILQ_INIT "STAILQ_HEAD *head"
|
||||
@ -143,7 +158,9 @@ lists and tail queues
|
||||
.Fn LIST_ENTRY "TYPE"
|
||||
.Fn LIST_FIRST "LIST_HEAD *head"
|
||||
.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
|
||||
.Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
|
||||
.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn LIST_FOREACH_FROM_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn LIST_HEAD "HEADNAME" "TYPE"
|
||||
.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
|
||||
.Fn LIST_INIT "LIST_HEAD *head"
|
||||
@ -151,6 +168,7 @@ lists and tail queues
|
||||
.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
|
||||
.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
|
||||
.Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME"
|
||||
.Fn LIST_PREV "TYPE *elm" "LIST_HEAD *head" "TYPE" "LIST_ENTRY NAME"
|
||||
.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
|
||||
.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
|
||||
.\"
|
||||
@ -159,9 +177,13 @@ lists and tail queues
|
||||
.Fn TAILQ_ENTRY "TYPE"
|
||||
.Fn TAILQ_FIRST "TAILQ_HEAD *head"
|
||||
.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
|
||||
.Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
|
||||
.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn TAILQ_FOREACH_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
|
||||
.Fn TAILQ_FOREACH_REVERSE_FROM "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
|
||||
.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn TAILQ_FOREACH_REVERSE_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
|
||||
.Fn TAILQ_HEAD "HEADNAME" "TYPE"
|
||||
.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
|
||||
.Fn TAILQ_INIT "TAILQ_HEAD *head"
|
||||
@ -244,8 +266,18 @@ Code size and execution time of operations (except for removal) is about
|
||||
twice that of the singly-linked data-structures.
|
||||
.El
|
||||
.Pp
|
||||
Linked lists are the simplest of the doubly linked data structures and support
|
||||
only the above functionality over singly-linked lists.
|
||||
Linked lists are the simplest of the doubly linked data structures.
|
||||
They add the following functionality over the above:
|
||||
.Bl -enum -compact -offset indent
|
||||
.It
|
||||
They may be traversed backwards.
|
||||
.El
|
||||
However:
|
||||
.Bl -enum -compact -offset indent
|
||||
.It
|
||||
To traverse backwards, an entry to begin the traversal and the list in
|
||||
which it is contained must be specified.
|
||||
.El
|
||||
.Pp
|
||||
Tail queues add the following functionality:
|
||||
.Bl -enum -compact -offset indent
|
||||
@ -349,6 +381,19 @@ turn to
|
||||
.Fa var .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm SLIST_FOREACH_FROM
|
||||
behaves identically to
|
||||
.Nm SLIST_FOREACH
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found SLIST element and begins the loop at
|
||||
.Fa var
|
||||
instead of the first element in the SLIST referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm SLIST_FOREACH_SAFE
|
||||
traverses the list referenced by
|
||||
.Fa head
|
||||
@ -363,6 +408,19 @@ as well as free it from within the loop safely without interfering with the
|
||||
traversal.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm SLIST_FOREACH_FROM_SAFE
|
||||
behaves identically to
|
||||
.Nm SLIST_FOREACH_SAFE
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found SLIST element and begins the loop at
|
||||
.Fa var
|
||||
instead of the first element in the SLIST referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm SLIST_INIT
|
||||
initializes the list referenced by
|
||||
.Fa head .
|
||||
@ -388,7 +446,8 @@ The macro
|
||||
.Nm SLIST_REMOVE_AFTER
|
||||
removes the element after
|
||||
.Fa elm
|
||||
from the list. Unlike
|
||||
from the list.
|
||||
Unlike
|
||||
.Fa SLIST_REMOVE ,
|
||||
this macro does not traverse the entire list.
|
||||
.Pp
|
||||
@ -528,6 +587,19 @@ in turn to
|
||||
.Fa var .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm STAILQ_FOREACH_FROM
|
||||
behaves identically to
|
||||
.Nm STAILQ_FOREACH
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found STAILQ element and begins the loop at
|
||||
.Fa var
|
||||
instead of the first element in the STAILQ referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm STAILQ_FOREACH_SAFE
|
||||
traverses the tail queue referenced by
|
||||
.Fa head
|
||||
@ -542,6 +614,19 @@ as well as free it from within the loop safely without interfering with the
|
||||
traversal.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm STAILQ_FOREACH_FROM_SAFE
|
||||
behaves identically to
|
||||
.Nm STAILQ_FOREACH_SAFE
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found STAILQ element and begins the loop at
|
||||
.Fa var
|
||||
instead of the first element in the STAILQ referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm STAILQ_INIT
|
||||
initializes the tail queue referenced by
|
||||
.Fa head .
|
||||
@ -579,7 +664,8 @@ The macro
|
||||
.Nm STAILQ_REMOVE_AFTER
|
||||
removes the element after
|
||||
.Fa elm
|
||||
from the tail queue. Unlike
|
||||
from the tail queue.
|
||||
Unlike
|
||||
.Fa STAILQ_REMOVE ,
|
||||
this macro does not traverse the entire tail queue.
|
||||
.Pp
|
||||
@ -717,6 +803,19 @@ in the forward direction, assigning each element in turn to
|
||||
.Fa var .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm LIST_FOREACH_FROM
|
||||
behaves identically to
|
||||
.Nm LIST_FOREACH
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found LIST element and begins the loop at
|
||||
.Fa var
|
||||
instead of the first element in the LIST referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm LIST_FOREACH_SAFE
|
||||
traverses the list referenced by
|
||||
.Fa head
|
||||
@ -730,6 +829,19 @@ as well as free it from within the loop safely without interfering with the
|
||||
traversal.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm LIST_FOREACH_FROM_SAFE
|
||||
behaves identically to
|
||||
.Nm LIST_FOREACH_SAFE
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found LIST element and begins the loop at
|
||||
.Fa var
|
||||
instead of the first element in the LIST referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm LIST_INIT
|
||||
initializes the list referenced by
|
||||
.Fa head .
|
||||
@ -759,6 +871,14 @@ The macro
|
||||
returns the next element in the list, or NULL if this is the last.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm LIST_PREV
|
||||
returns the previous element in the list, or NULL if this is the first.
|
||||
List
|
||||
.Fa head
|
||||
must contain element
|
||||
.Fa elm .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm LIST_REMOVE
|
||||
removes the element
|
||||
.Fa elm
|
||||
@ -894,12 +1014,38 @@ is set to
|
||||
if the loop completes normally, or if there were no elements.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm TAILQ_FOREACH_FROM
|
||||
behaves identically to
|
||||
.Nm TAILQ_FOREACH
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found TAILQ element and begins the loop at
|
||||
.Fa var
|
||||
instead of the first element in the TAILQ referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm TAILQ_FOREACH_REVERSE
|
||||
traverses the tail queue referenced by
|
||||
.Fa head
|
||||
in the reverse direction, assigning each element in turn to
|
||||
.Fa var .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm TAILQ_FOREACH_REVERSE_FROM
|
||||
behaves identically to
|
||||
.Nm TAILQ_FOREACH_REVERSE
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found TAILQ element and begins the reverse loop at
|
||||
.Fa var
|
||||
instead of the last element in the TAILQ referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macros
|
||||
.Nm TAILQ_FOREACH_SAFE
|
||||
and
|
||||
@ -919,6 +1065,32 @@ as well as free it from within the loop safely without interfering with the
|
||||
traversal.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm TAILQ_FOREACH_FROM_SAFE
|
||||
behaves identically to
|
||||
.Nm TAILQ_FOREACH_SAFE
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found TAILQ element and begins the loop at
|
||||
.Fa var
|
||||
instead of the first element in the TAILQ referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE
|
||||
behaves identically to
|
||||
.Nm TAILQ_FOREACH_REVERSE_SAFE
|
||||
when
|
||||
.Fa var
|
||||
is NULL, else it treats
|
||||
.Fa var
|
||||
as a previously found TAILQ element and begins the reverse loop at
|
||||
.Fa var
|
||||
instead of the last element in the TAILQ referenced by
|
||||
.Fa head .
|
||||
.Pp
|
||||
The macro
|
||||
.Nm TAILQ_INIT
|
||||
initializes the tail queue referenced by
|
||||
.Fa head .
|
||||
|
Loading…
Reference in New Issue
Block a user