Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Mar 2007 09:01:54 +0000
From:      Poul-Henning Kamp <phk@phk.freebsd.dk>
To:        arch@freebsd.org
Subject:   <sys/queue.h> bikeshed proposal
Message-ID:  <39968.1173776514@critter.freebsd.dk>

next in thread | raw e-mail | index | archive | help

It has always bothered me that some of the TAILQ macros need to
know the struct name of the header type.

Many times where I could have avoided naming that structure, I
had to, only to satisfy this weird craving of <sys/queue.h>.

<sys/queue.h> needs the struct name TAILQ_LAST and TAILQ_PREV casts,
what is potentially a pointer to an entry, to the header type,
before it dereferences the backwards pointer.

The validity of this cast depends critically on the layout of the
entry struct and the header struct being identical with respect to
the two pointers.

So, if we have already assumed, that they have the same layout, why
do the cast in the first place ? 

The following proof of concept patch shows, that you can implement
these two macros without the cast to the header struct type.

If we did this, we could eliminate the "headname" argument to
	TAILQ_FOREACH_REVERSE
	TAILQ_FOREACH_REVERS_SAFE
	TAILQ_LAST
	TAILQ_PREV

Obviously this is bikeshed fodder, but given how big a help <sys/queue.h>
is programming-wise, and given that those four macros are comparatively
seldomly used, I will propose to remove this wart from <sys/queue.h>
under the banner of computer science in general and suffer the minor
backwards compatibility issues it will cause.

Poul-Henning


Index: queue.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/queue.h,v
retrieving revision 1.68
diff -u -r1.68 queue.h
--- queue.h	24 Oct 2006 11:20:29 -0000	1.68
+++ queue.h	13 Mar 2007 08:51:51 -0000
@@ -546,12 +546,12 @@
 } while (0)
 
 #define	TAILQ_LAST(head, headname)					\
-	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+	(*((head)->tqh_last->tqe_prev)
 
 #define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
 
 #define	TAILQ_PREV(elm, headname, field)				\
-	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+	(*((elm)->field.tqe_prev->tqe_prev))
 
 #define	TAILQ_REMOVE(head, elm, field) do {				\
 	QMD_TAILQ_CHECK_NEXT(elm, field);				\
-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?39968.1173776514>