Re: embedded list v2

Andres Freund <andres@2ndquadrant.com>

From: Andres Freund <andres@2ndquadrant.com>
To: pgsql-hackers@postgresql.org
Cc: Tom Lane <tgl@sss.pgh.pa.us>, Alvaro Herrera <alvherre@2ndquadrant.com>, Robert Haas <robertmhaas@gmail.com>, Peter Geoghegan <peter@2ndquadrant.com>
Date: 2012-09-16T17:56:54Z
Lists: pgsql-hackers
Hi,

On Sunday, September 16, 2012 04:23:14 PM Andres Freund wrote:
> What do you think about something like:
> 
> typedef struct dlist_iter
> {
> 	/*
> 	 * Use a union with equivalent storage as dlist_node to make it possible
> to * initialize the struct inside a macro without multiple evaluation. */
> 	union {
> 		struct {
> 			dlist_node *cur;
> 			dlist_node *end;
> 		};
> 		dlist_node init;
> 	};
> } dlist_iter;
> 
> typedef struct dlist_mutable_iter
> {
> 	union {
> 		struct {
> 			dlist_node *cur;
> 			dlist_node *end;
> 		};
> 		dlist_node init;
> 	};
> 	dlist_node *next;
> } dlist_mutable_iter;
> 
> #define dlist_iter_foreach(iter, ptr)									     \
> 	for (iter.init = (ptr)->head; iter.cur != iter.end;                      \
> 	     iter.cur = iter.cur->next)
> 
> #define dlist_iter_foreach_modify(iter, ptr)								 
\
> 	for (iter.init = (ptr)->head, iter.next = iter.cur->next;                \
> 	     iter.cur != iter.end                                                \
> 	     iter.cur = iter.next, iter.next = iter.cur->next)
> 
> With that and some trivial changes *all* multiple evaluation possibilities
> are gone.
> 
> (_iter_ in there would go, thats just so I can have both in the same file
> for now).

I am thinking whether a macro like:

#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#define assert_compatible_types(a, b) _Static_assert(            \
		__builtin_types_compatible_p(a, __typeof__ (b) ), \
		"variable `" #b "` is not compatible to type `" #a "`" )
#else
#define assert_compatible_types(a, b) (void)0
#endif

used like:

#define dlist_iter_foreach(iter, ptr)									     \
	assert_compatible_types(dlist_iter, iter);                               \
	for (iter.init = (ptr)->head; iter.cur != iter.end;                      \
	     iter.cur = iter.cur->next)

would be useful.

If you use the wrong type you get an error like:

error: static assertion failed: "variable `iter` is not compatible to type 
`dlist_iter`"

Do people think this is something worthwile for some of the macros in pg? At 
times the compiler errors that get generated in larger macros can be a bit 
confusing and something like that would make it easier to see the originating 
error.

I found __builtin_types_compatible while perusing the gcc docs to find whether 
there is something like __builtin_constant_p for checking the pureness of an 
expression ;)

Andres
-- 
 Andres Freund	                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Provide some static-assertion functionality on all compilers.

  2. Add infrastructure for compile-time assertions about variable types.

  3. Remove 576 references of include files that were not needed.

  4. More include file adjustments.

  5. Allow each C include file to compile on its own by including any needed