diff options
author | kan <kan@FreeBSD.org> | 2003-08-14 14:49:26 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2003-08-14 14:49:26 +0000 |
commit | d822b4a77254150edb5672c9163920221303b91d (patch) | |
tree | 91e9a96878f77b64628c255cda6eb119ede0ab00 | |
parent | 0de4aa01fa11584b2919a74d9e2a08a5d5071bd3 (diff) | |
download | FreeBSD-src-d822b4a77254150edb5672c9163920221303b91d.zip FreeBSD-src-d822b4a77254150edb5672c9163920221303b91d.tar.gz |
Add safe _FOREACH iterators to the rest of the queue.h types.
-rw-r--r-- | share/man/man3/queue.3 | 76 | ||||
-rw-r--r-- | sys/sys/queue.h | 95 |
2 files changed, 134 insertions, 37 deletions
diff --git a/share/man/man3/queue.3 b/share/man/man3/queue.3 index b71f87a..b13c35c 100644 --- a/share/man/man3/queue.3 +++ b/share/man/man3/queue.3 @@ -40,6 +40,7 @@ .Nm SLIST_ENTRY , .Nm SLIST_FIRST , .Nm SLIST_FOREACH , +.Nm SLIST_FOREACH_SAFE , .Nm SLIST_HEAD , .Nm SLIST_HEAD_INITIALIZER , .Nm SLIST_INIT , @@ -53,6 +54,7 @@ .Nm STAILQ_ENTRY , .Nm STAILQ_FIRST , .Nm STAILQ_FOREACH , +.Nm STAILQ_FOREACH_SAFE , .Nm STAILQ_HEAD , .Nm STAILQ_HEAD_INITIALIZER , .Nm STAILQ_INIT , @@ -81,7 +83,9 @@ .Nm TAILQ_ENTRY , .Nm TAILQ_FIRST , .Nm TAILQ_FOREACH , +.Nm TAILQ_FOREACH_SAFE , .Nm TAILQ_FOREACH_REVERSE , +.Nm TAILQ_FOREACH_REVERSE_SAFE , .Nm TAILQ_HEAD , .Nm TAILQ_HEAD_INITIALIZER , .Nm TAILQ_INIT , @@ -102,6 +106,7 @@ 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_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" @@ -116,6 +121,7 @@ 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_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" @@ -146,7 +152,9 @@ 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_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_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" @@ -326,6 +334,20 @@ turn to .Fa var . .Pp The macro +.Nm SLIST_FOREACH_SAFE +traverses the list referenced by +.Fa head +in the forward direction, assigning each element in +turn to +.Fa var . +However, unlike +.Fn SLIST_FOREACH +here it is permitted to both remove +.Fa var +as well as free it from within the loop safely without interfering with the +traversal. +.Pp +The macro .Nm SLIST_INIT initializes the list referenced by .Fa head . @@ -391,6 +413,13 @@ free(n3); /* Forward traversal. */ 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); @@ -469,6 +498,20 @@ in turn to .Fa var . .Pp The macro +.Nm STAILQ_FOREACH_SAFE +traverses the tail queue referenced by +.Fa head +in the forward direction, assigning each element +in turn to +.Fa var . +However, unlike +.Fn STAILQ_FOREACH +here it is permitted to both remove +.Fa var +as well as free it from within the loop safely without interfering with the +traversal. +.Pp +The macro .Nm STAILQ_INIT initializes the tail queue referenced by .Fa head . @@ -546,6 +589,13 @@ free(n3); /* Forward traversal. */ 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); @@ -797,6 +847,24 @@ traverses the tail queue referenced by in the reverse direction, assigning each element in turn to .Fa var . .Pp +The macros +.Nm TAILQ_FOREACH_SAFE +and +.Nm TAILQ_FOREACH_REVERSE_SAFE +traverse the list referenced by +.Fa head +in the forward or reverse direction respectively, +assigning each element in turn to +.Fa var . +However, unlike their unsafe conterparts, +.Nm TAILQ_FOREACH +and +.Nm TAILQ_FOREACH_REVERSE +permit to both remove +.Fa var +as well as free it from within the loop safely without interfering with the +traversal. +.Pp The macro .Nm TAILQ_INIT initializes the tail queue referenced by @@ -877,6 +945,13 @@ free(n2); /* Forward traversal. */ 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 traversal. */ TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries) np-> ... @@ -893,6 +968,7 @@ while (n1 != NULL) { free(n1); n1 = n2; } + TAILQ_INIT(&head); .Ed .Sh HISTORY diff --git a/sys/sys/queue.h b/sys/sys/queue.h index a06f084..b875847 100644 --- a/sys/sys/queue.h +++ b/sys/sys/queue.h @@ -81,28 +81,30 @@ * For details on the use of these macros, see the queue(3) manual page. * * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - - - + - * _LAST - - + + - * _FOREACH + + + + - * _FOREACH_REVERSE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT - - + + - * _REMOVE_HEAD + - + - - * _REMOVE + + + + + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + * */ -#define QUEUE_MACRO_DEBUG 0 +#define QUEUE_MACRO_DEBUG 0 #if QUEUE_MACRO_DEBUG /* Store the last 2 places the queue element or head was altered */ struct qm_trace { @@ -112,17 +114,17 @@ struct qm_trace { int prevline; }; -#define TRACEBUF struct qm_trace trace; -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) -#define QMD_TRACE_HEAD(head) do { \ +#define QMD_TRACE_HEAD(head) do { \ (head)->trace.prevline = (head)->trace.lastline; \ (head)->trace.prevfile = (head)->trace.lastfile; \ (head)->trace.lastline = __LINE__; \ (head)->trace.lastfile = __FILE__; \ } while (0) -#define QMD_TRACE_ELEM(elem) do { \ +#define QMD_TRACE_ELEM(elem) do { \ (elem)->trace.prevline = (elem)->trace.lastline; \ (elem)->trace.prevfile = (elem)->trace.lastfile; \ (elem)->trace.lastline = __LINE__; \ @@ -130,10 +132,10 @@ struct qm_trace { } while (0) #else -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define TRACEBUF -#define TRASHIT(x) +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) #endif /* QUEUE_MACRO_DEBUG */ /* @@ -146,12 +148,12 @@ struct name { \ #define SLIST_HEAD_INITIALIZER(head) \ { NULL } - + #define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } - + /* * Singly-linked List functions. */ @@ -164,7 +166,12 @@ struct { \ (var); \ (var) = SLIST_NEXT((var), field)) -#define SLIST_FOREACH_PREVPTR(var, varp, head, 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_PREVPTR(var, varp, head, field) \ for ((varp) = &SLIST_FIRST((head)); \ ((var) = *(varp)) != NULL; \ (varp) = &SLIST_NEXT((var), field)) @@ -239,6 +246,12 @@ struct { \ (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_INIT(head) do { \ STAILQ_FIRST((head)) = NULL; \ (head)->stqh_last = &STAILQ_FIRST((head)); \ @@ -325,12 +338,10 @@ struct { \ (var); \ (var) = LIST_NEXT((var), field)) -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)), \ - (var) != NULL ? (tvar) = LIST_NEXT((var), field) : NULL; \ - (var) != NULL; \ - (var) = (tvar), \ - (var) != NULL ? (tvar) = LIST_NEXT((var), field) : NULL) +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) #define LIST_INIT(head) do { \ LIST_FIRST((head)) = NULL; \ @@ -410,11 +421,21 @@ struct { \ (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_REVERSE(var, head, headname, field) \ for ((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_INIT(head) do { \ TAILQ_FIRST((head)) = NULL; \ (head)->tqh_last = &TAILQ_FIRST((head)); \ |