summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2003-08-14 14:49:26 +0000
committerkan <kan@FreeBSD.org>2003-08-14 14:49:26 +0000
commitd822b4a77254150edb5672c9163920221303b91d (patch)
tree91e9a96878f77b64628c255cda6eb119ede0ab00
parent0de4aa01fa11584b2919a74d9e2a08a5d5071bd3 (diff)
downloadFreeBSD-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.376
-rw-r--r--sys/sys/queue.h95
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)); \
OpenPOWER on IntegriCloud