Re: Vectorization of some functions and improving pg_list interface - Mailing list pgsql-hackers
From | Yura Sokolov |
---|---|
Subject | Re: Vectorization of some functions and improving pg_list interface |
Date | |
Msg-id | e9ebfa9a-89c7-4db6-cbf9-9ceba8051966@postgrespro.ru Whole thread Raw |
In response to | Re: Vectorization of some functions and improving pg_list interface (Yura Sokolov <y.sokolov@postgrespro.ru>) |
List | pgsql-hackers |
06.09.2023 13:24, Yura Sokolov wrote: > 24.08.2023 17:07, Maxim Orlov wrote: >> Hi! >> >> Recently, I've been playing around with pg_lists and realize how >> annoying (maybe, I was a bit tired) some stuff related to the lists. >> For an example, see this code >> List *l1 = list_make4(1, 2, 3, 4), >> *l2 = list_make4(5, 6, 7, 8), >> *l3 = list_make4(9, 0, 1, 2); >> ListCell *lc1, *lc2, *lc3; >> >> forthree(lc1, l1, lc2, l2, lc3, l3) { >> ... >> } >> >> list_free(l1); >> list_free(l2); >> list_free(l3); >> >> There are several questions: >> 1) Why do I need to specify the number of elements in the list in the >> function name? >> Compiler already knew how much arguments do I use. >> 2) Why I have to call free for every list? I don't know how to call it >> right, for now I call it vectorization. >> Why not to use simple wrapper to "vectorize" function args? >> >> So, my proposal is: >> 1) Add a simple macro to "vectorize" functions. >> 2) Use this macro to "vectorize" list_free and list_free_deep functions. >> 3) Use this macro to "vectorize" bms_free function. >> 4) "Vectorize" list_makeN functions. >> >> For this V1 version, I do not remove all list_makeN calls in order to >> reduce diff, but I'll address >> this in future, if it will be needed. >> >> In my view, one thing still waiting to be improved if foreach loop. It >> is not very handy to have a bunch of >> similar calls foreach, forboth, forthree and etc. It will be ideal to >> have single foreach interface, but I don't know how >> to do it without overall interface of the loop. >> >> Any opinions are very welcome! > > Given use case doesn't assume "zero" arguments, it is possible to > implement "lists_free" with just macro expansion (following code is not > checked, but close to valid): > > #define VA_FOR_EACH(invoke, join, ...) \ > CppConcat(VA_FOR_EACH_, VA_ARGS_NARGS(__VA_ARGS__))( \ > invoke, join, __VA_ARGS__) > #define VA_FOR_EACH_1(invoke, join, a1) \ > invoke(a1) > #define VA_FOR_EACH_2(invoke, join, a1, a2) \ > invoke(a1) join() invoke(a2) > #define VA_FOR_EACH_3(invoke, join, a1, a2, a3) \ > invoke(a1) join() invoke(a2) join() invoke(a3) > ... up to 63 args > > #define VA_SEMICOLON() ; > > #define lists_free(...) \ > VA_FOR_EACH(list_free, VA_SEMICOLON, __VA_ARGS__) > > #define lists_free_deep(...) \ > VA_FOR_EACH(list_free_deep, VA_SEMICOLON, __VA_ARGS__) > > There could be couple of issues with msvc, but they are solvable. Given we could use C99 compound literals, list contruction could be implemented without C vaarg functions as well List * list_make_impl(NodeTag t, int n, ListCell *datums) { List *list = new_list(t, n); memcpy(list->elements, datums, sizeof(ListCell)*n); return list; } #define VA_COMMA() , #define list_make__m(Tag, type, ...) \ list_make_impl(Tag, VA_ARGS_NARGS(__VA_ARGS__), \ ((ListCell[]){ \ VA_FOR_EACH(list_make_##type##_cell, VA_COMMA, __VA_ARGS__) \ })) #define list_make(...) list_make__m(T_List, ptr, __VA_ARGS__) #define list_make_int(...) list_make__m(T_IntList, int, __VA_ARGS__) #define list_make_oid(...) list_make__m(T_OidList, oid, __VA_ARGS__) #define list_make_xid(...) list_make__m(T_XidList, xid, __VA_ARGS__) (code is not checked) If zero arguments (no arguments) should be supported, it is tricky because of mvsc, but solvable.
pgsql-hackers by date: