Re: embedded list v2 - Mailing list pgsql-hackers

From Andres Freund
Subject Re: embedded list v2
Date
Msg-id 201209161956.54346.andres@2ndquadrant.com
Whole thread Raw
In response to Re: embedded list v2  (Andres Freund <andres@2ndquadrant.com>)
List 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



pgsql-hackers by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: [ADMIN] pg_upgrade from 9.1.3 to 9.2 failed
Next
From: Peter Eisentraut
Date:
Subject: Re: _FORTIFY_SOURCE by default?