Bug 20024

Summary: [PATCH] queue(3) concatenation macros
Product: Base System Reporter: Tony Finch <dot>
Component: miscAssignee: Thomas Moestl <tmm>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.0-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description Tony Finch 2000-07-19 04:40:00 UTC
The patch below adds a couple of macros to queue.h so that TAILQs and
CIRCLEQs may be easily concatenated. It even includes documentation!
Comment 1 Sheldon Hearn freebsd_committer freebsd_triage 2000-07-19 08:47:26 UTC
Responsible Changed
From-To: freebsd-bugs->jake

Jake likes this part of the source tree.
Comment 2 Tony Finch 2000-09-07 10:22:15 UTC
I have updated the patch to the new coding style in sys/queue.h, and I
also found a couple of bracketing and style bugs.


--- /usr/src/sys/sys/queue.h	Thu Aug  3 17:31:56 2000
+++ /usr/src/sys/sys/queue.h	Thu Sep  7 09:14:23 2000
@@ -76,7 +76,8 @@
  * linked 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, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
+ * the list. A tail queue may be traversed in either direction. Tail
+ * queues may be concatenated.
  *
  * A circle 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
@@ -84,7 +85,7 @@
  * traverse the list. New elements can be added to the list before or after
  * an existing element, at the head of the list, or at the end of the list.
  * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
+ * complex end of list detection. Circle queues may be concatenated.
  *
  * For details on the use of these macros, see the queue(3) manual page.
  *
@@ -107,6 +108,7 @@
  * _INSERT_TAIL		-	-	+	+	+
  * _REMOVE_HEAD		+	-	+	-	-
  * _REMOVE		+	+	+	+	+
+ * _CONCAT		-	-	-	+	+
  *
  */
 
@@ -224,7 +226,7 @@
 } while (0)
 
 #define	STAILQ_LAST(head, type, field)					\
-	(STAILQ_EMPTY(head) ?						\
+	(STAILQ_EMPTY((head)) ?						\
 		NULL :							\
 		strbase(type, (head)->stqh_last, field))
 
@@ -232,7 +234,7 @@
 
 #define	STAILQ_REMOVE(head, elm, type, field) do {			\
 	if (STAILQ_FIRST((head)) == (elm)) {				\
-		STAILQ_REMOVE_HEAD(head, field);			\
+		STAILQ_REMOVE_HEAD((head), field);			\
 	}								\
 	else {								\
 		struct type *curelm = STAILQ_FIRST((head));		\
@@ -411,6 +413,15 @@
 	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
 } while (0)
 
+#define TAILQ_CONCAT(head1, head2, field) do {				\
+	if (!TAILQ_EMPTY(head2)) {					\
+		*(head1)->tqh_last = (head2)->tqh_first;		\
+		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
+		(head1)->tqh_last = (head2)->tqh_last;			\
+		TAILQ_INIT(head2);					\
+	}								\
+} while (0)
+
 /*
  * Circular queue declarations.
  */
@@ -491,11 +502,11 @@
 	CIRCLEQ_LAST((head)) = (elm);					\
 } while (0)
 
-#define	CIRCLEQ_LAST(head)	((head)->cqh_last)
+#define	CIRCLEQ_LAST(head)		((head)->cqh_last)
 
-#define	CIRCLEQ_NEXT(elm,field)	((elm)->field.cqe_next)
+#define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
 
-#define	CIRCLEQ_PREV(elm,field)	((elm)->field.cqe_prev)
+#define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
 
 #define	CIRCLEQ_REMOVE(head, elm, field) do {				\
 	if (CIRCLEQ_NEXT((elm), field) == (void *)(head))		\
@@ -508,6 +519,25 @@
 	else								\
 		CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) =	\
 		    CIRCLEQ_NEXT((elm), field);				\
+} while (0)
+
+#define CIRCLEQ_CONCAT(head1, head2, field) do {			\
+	if (!CIRCLEQ_EMPTY((head2))) {					\
+		if (!CIRCLEQ_EMPTY((head1))) {				\
+			CIRCLEQ_NEXT(CIRCLEQ_LAST((head1)), field) =	\
+				CIRCLEQ_FIRST((head2));			\
+			CIRCLEQ_PREV(CIRCLEQ_FIRST((head2)), field =	\
+				CIRCLEQ_LAST((head1));			\
+		} else {						\
+			CIRCLEQ_FIRST((head1)) = CIRCLEQ_FIRST((head2));\
+			CIRCLEQ_PREV(CIRCLEQ_FIRST((head1)), field) =	\
+				(void *)(head1);			\
+		}							\
+		CIRCLEQ_LAST((head1)) = CIRCLEQ_LAST((head2))		\
+		CIRCLEQ_NEXT(CIRCLEQ_LAST((head1)), field) =		\
+			(void *)(head1);				\
+		CIRCLEQ_INIT((head2));					\
+	}								\
 } while (0)
 
 #ifdef _KERNEL
Comment 3 Jake Burkholder freebsd_committer freebsd_triage 2002-04-14 17:18:27 UTC
Responsible Changed
From-To: jake->tmm

Thomas may find this useful.
Comment 4 Thomas Moestl freebsd_committer freebsd_triage 2002-04-17 15:00:48 UTC
State Changed
From-To: open->closed

Tailq part committed (the CIRCLEQ macro family was removed 
from queue.h a while ago). Thanks!