Reformat macro to 80 characters

This commit is contained in:
Patrick Pelissier committed 2020-10-21 23:23:40 +02:00
1 parent 8a0a556604
commit 54d4b80368
27 files changed
+12821 -12821

No files matched your search

+171 -171
View File
@@ -31,18 +31,18 @@
which oplist is 'contOp', as static inline functions.
USAGE:
ALGO_DEF(algogName, containerOplist|type if oplist has been registered) */
#define ALGO_DEF(name, cont_oplist) \
M_BEGIN_PROTECTED_CODE \
ALGOI_DEF_P1(name, M_GLOBAL_OPLIST(cont_oplist)) \
#define ALGO_DEF(name, cont_oplist) \
M_BEGIN_PROTECTED_CODE \
ALGOI_DEF_P1(name, M_GLOBAL_OPLIST(cont_oplist)) \
M_END_PROTECTED_CODE
/* Map a function (or a macro) to all elements of a container.
USAGE:
ALGO_FOR_EACH(container, containerOplist, function[, extra arguments of function]) */
#define ALGO_FOR_EACH(container, cont_oplist, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(ALGOI_FOR_EACH(container, M_GLOBAL_OPLIST(cont_oplist), __VA_ARGS__), \
#define ALGO_FOR_EACH(container, cont_oplist, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(ALGOI_FOR_EACH(container, M_GLOBAL_OPLIST(cont_oplist), __VA_ARGS__), \
ALGOI_FOR_EACH_ARG(container, M_GLOBAL_OPLIST(cont_oplist), __VA_ARGS__ ))
@@ -51,8 +51,8 @@
USAGE:
ALGO_TRANSFORM(contDst, contDOplist, contSrc, contSrcOplist,
function[, extra arguments of function]) */
#define ALGO_TRANSFORM(contD, contDop, contS, contSop, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
#define ALGO_TRANSFORM(contD, contDop, contS, contSop, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(ALGOI_TRANSFORM(contD, M_GLOBAL_OPLIST(contDop), contS, M_GLOBAL_OPLIST(contSop), __VA_ARGS__), \
ALGOI_TRANSFORM_ARG(contD, M_GLOBAL_OPLIST(contDop), contS, M_GLOBAL_OPLIST(contSop), __VA_ARGS__ ))
@@ -61,10 +61,10 @@
USAGE:
ALGO_EXTRACT(contDst, contDstOplist, contSrc, contSrcOplist
[, function [, extra arguments of function]]) */
#define ALGO_EXTRACT(contD, contDop, contS, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
#define ALGO_EXTRACT(contD, contDop, contS, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(ALGOI_EXTRACT(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __VA_ARGS__), \
M_IF_NARGS_EQ2(__VA_ARGS__) \
M_IF_NARGS_EQ2(__VA_ARGS__) \
(ALGOI_EXTRACT_FUNC(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __VA_ARGS__), \
ALGOI_EXTRACT_ARG(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __VA_ARGS__ )))
@@ -73,8 +73,8 @@
USAGE:
ALGO_REDUCE(dstVar, container, contOplist, reduceFunc
[, mapFunc[, extraParameters of map function]]) */
#define ALGO_REDUCE(dest, cont, contOp, ...) \
M_IF(M_PARENTHESIS_P(dest)) \
#define ALGO_REDUCE(dest, cont, contOp, ...) \
M_IF(M_PARENTHESIS_P(dest)) \
(ALGOI_REDUCE_DISPATCH(M_PAIR_1 dest, M_GLOBAL_OPLIST(M_PAIR_2 dest), M_GLOBAL_TYPE(M_PAIR_2 dest),cont, M_GLOBAL_OPLIST(contOp), __VA_ARGS__), \
ALGOI_REDUCE_DISPATCH(dest, M_GET_OPLIST M_GLOBAL_OPLIST(contOp), M_GET_SUBTYPE M_GLOBAL_OPLIST(contOp), cont, contOp, __VA_ARGS__)) \
@@ -84,7 +84,7 @@
ALGO_INIT_VA(container, containerOplist, param1[, param2[, ...]]).
OBSOLETE: WILL BE DELETED.
*/
#define ALGO_INIT_VA(dest, contOp, ...) \
#define ALGO_INIT_VA(dest, contOp, ...) \
ALGO_INIT_VAI(dest, M_GLOBAL_OPLIST(contOp), __VA_ARGS__)
@@ -95,7 +95,7 @@
}
OBSOLETE: WILL BE DELETED.
*/
#define ALGO_LET_INIT_VA(dest, contOp, ...) \
#define ALGO_LET_INIT_VA(dest, contOp, ...) \
ALGO_LET_INIT_VAI(dest, M_GLOBAL_OPLIST(contOp), __VA_ARGS__)
@@ -104,16 +104,16 @@
USAGE:
ALGO_INSERT_AT(containerDst, containerDstOPLIST|containerDstType, containerDstIterator, containerSrc, containerSrcOPLIST|containerSrcType)
*/
#define ALGO_INSERT_AT(contDst, contDstOp, position, contSrc, contSrcOp) \
#define ALGO_INSERT_AT(contDst, contDstOp, position, contSrc, contSrcOp) \
ALGOI_INSERT_AT(contDst, M_GLOBAL_OPLIST(contDstOp), position, contSrc, M_GLOBAL_OPLIST(contSrcOp) )
/********************************** INTERNAL ************************************/
/* Try to expand the algorithms */
#define ALGOI_DEF_P1(name, cont_oplist) \
ALGOI_DEF_P2(name, M_GET_TYPE cont_oplist, cont_oplist, \
M_GET_SUBTYPE cont_oplist, M_GET_OPLIST cont_oplist, \
#define ALGOI_DEF_P1(name, cont_oplist) \
ALGOI_DEF_P2(name, M_GET_TYPE cont_oplist, cont_oplist, \
M_GET_SUBTYPE cont_oplist, M_GET_OPLIST cont_oplist, \
M_GET_IT_TYPE cont_oplist)
/* First validate the first oplist */
@@ -246,7 +246,7 @@
while (!M_CALL_IT_END_P(cont_oplist, it2)) { \
type_t const *ref1 = M_CALL_IT_CREF(cont_oplist, it1); \
type_t const *ref2 = M_CALL_IT_CREF(cont_oplist, it2); \
if (!(cmp_func(name, sort_name, ref1, ref2) <= 0)) { \
if (!(cmp_func(name, sort_name, ref1, ref2) <= 0)) { \
return false; \
} \
M_CALL_IT_SET(cont_oplist, it1, it2); \
@@ -260,11 +260,11 @@
/* - an unstable merge sort (need 'splice_back' method) */ \
/* - an insertion sort (need 'previous' method) */ \
/* - a selection sort */ \
M_IF(M_AND(M_TEST_METHOD_P(SORT, cont_oplist), M_EMPTY_P(cmp_arg)))( \
/******** OPTIMIZED SORT FOR CONTAINER *********/ \
M_IF(M_AND(M_TEST_METHOD_P(SORT, cont_oplist), M_EMPTY_P(cmp_arg)))( \
/******** OPTIMIZED SORT FOR CONTAINER *********/ \
static inline void M_C(name,sort_name)(container_t l) \
{ \
M_CALL_SORT(cont_oplist, l, M_C3(name, sort_name,_cmp)); \
M_CALL_SORT(cont_oplist, l, M_C3(name, sort_name,_cmp)); \
} \
, \
\
@@ -279,7 +279,7 @@
{ \
it_t it; \
bool b = false; \
/* Split 'l' into 'l1' and 'l2' */ \
/* Split 'l' into 'l1' and 'l2' */ \
for (M_CALL_IT_FIRST(cont_oplist,it, l); \
!M_CALL_IT_END_P(cont_oplist, it);) { \
M_CALL_SPLICE_BACK(cont_oplist, (b ? l1 : l2), l, it); \
@@ -300,14 +300,14 @@
M_CALL_IT_FIRST(cont_oplist,it1, l1); \
M_CALL_IT_FIRST(cont_oplist,it2, l2); \
while (true) { \
/* Compare current elements of the containers l1 and l2 */ \
/* Compare current elements of the containers l1 and l2 */ \
int c = cmp_func(name, sort_name, M_CALL_IT_CREF(cont_oplist, it1), \
M_CALL_IT_CREF(cont_oplist, it2)); \
M_CALL_IT_CREF(cont_oplist, it2)); \
if (c <= 0) { \
/* Move the element of l1 in the new container */ \
/* Move the element of l1 in the new container */ \
M_CALL_SPLICE_AT(cont_oplist, l, it, l1, it1); \
if (M_UNLIKELY (M_CALL_IT_END_P(cont_oplist, it1))) { \
/* Move all remaining elements of l2 in 'l' */ \
/* Move all remaining elements of l2 in 'l' */ \
while (!M_CALL_IT_END_P(cont_oplist, it2)) { \
M_CALL_SPLICE_AT(cont_oplist, l, it, l2, it2); \
} \
@@ -330,7 +330,7 @@
\
/* Sort the container 'l' */ \
static inline void \
M_C(name,sort_name)(container_t l cmp_param(name)) \
M_C(name,sort_name)(container_t l cmp_param(name)) \
{ \
container_t l1; \
container_t l2; \
@@ -350,8 +350,8 @@
if (M_UNLIKELY (M_CALL_IT_END_P(cont_oplist, it))) { \
/* Two elements */ \
int c = cmp_func(name, sort_name, \
M_CALL_IT_CREF(cont_oplist, it1), \
M_CALL_IT_CREF(cont_oplist, it2)); \
M_CALL_IT_CREF(cont_oplist, it1), \
M_CALL_IT_CREF(cont_oplist, it2)); \
if (c > 0) { \
/* SWAP */ \
M_CALL_SPLICE_BACK(cont_oplist, l, l, it2); \
@@ -391,8 +391,8 @@
M_CALL_IT_SET(cont_oplist, it2p1, it1); \
while (!M_CALL_IT_END_P(cont_oplist, it2) \
&& !(cmp_func(name, sort_name, \
M_CALL_IT_CREF(cont_oplist, it2), \
M_CONST_CAST(type_t, &x)) <= 0)) { \
M_CALL_IT_CREF(cont_oplist, it2), \
M_CONST_CAST(type_t, &x)) <= 0)) { \
/* TAB[jp1=j+1] := TAB[j] */ \
memcpy(M_CALL_IT_REF(cont_oplist, it2p1), \
M_CALL_IT_CREF(cont_oplist, it2), sizeof (type_t) ); \
@@ -423,7 +423,7 @@
!M_CALL_IT_END_P(cont_oplist, it2); \
M_CALL_IT_NEXT(cont_oplist, it2)) { \
if (cmp_func(name, sort_name, M_CALL_IT_CREF(cont_oplist, it2), \
M_CALL_IT_CREF(cont_oplist, it_min)) < 0) { \
M_CALL_IT_CREF(cont_oplist, it_min)) < 0) { \
M_CALL_IT_SET(cont_oplist, it_min, it2); \
} \
} \
@@ -463,23 +463,23 @@
if (cmp <= 0) { \
/* The element of dst is before. Go to next element of dst */ \
M_CALL_IT_SET(cont_oplist, itIns, itDst); \
M_CALL_IT_NEXT(cont_oplist, itDst); \
M_CALL_IT_NEXT(cont_oplist, itDst); \
if (cmp == 0) { \
/* Skip same arguments in both lists */ \
M_CALL_IT_NEXT(cont_oplist, itSrc); \
} \
} else { \
/* The element of src is before. */ \
/* insert objSrc before */ \
/* insert objSrc before */ \
/* NOTE: IT_INSERT insert after ==> Need of another iterator */ \
M_CALL_IT_INSERT(cont_oplist, dst, itIns, *objSrc); \
M_CALL_IT_NEXT(cont_oplist, itSrc); \
M_CALL_IT_INSERT(cont_oplist, dst, itIns, *objSrc); \
M_CALL_IT_NEXT(cont_oplist, itSrc); \
} \
} \
while (!M_CALL_IT_END_P(cont_oplist, itSrc)) { \
/* Finish inserting the element of src in dst */ \
type_t *objSrc = M_CALL_IT_REF(cont_oplist, itSrc); \
M_CALL_IT_INSERT(cont_oplist, dst, itIns, *objSrc); \
M_CALL_IT_INSERT(cont_oplist, dst, itIns, *objSrc); \
M_CALL_IT_NEXT(cont_oplist, itSrc); \
} \
} \
@@ -501,7 +501,7 @@
&& !M_CALL_IT_END_P(cont_oplist, itDst)) { \
type_t const *objSrc = M_CALL_IT_CREF(cont_oplist, itSrc); \
type_t const *objDst = M_CALL_IT_CREF(cont_oplist, itDst); \
int cmp = cmp_func(name, sort_name, objDst, objSrc); \
int cmp = cmp_func(name, sort_name, objDst, objSrc); \
if (cmp == 0) { \
/* Keep it */ \
M_CALL_IT_NEXT(cont_oplist, itSrc); \
@@ -677,7 +677,7 @@
M_CALL_IT_NEXT(cont_oplist, it1), \
M_CALL_IT_NEXT(cont_oplist, it2)) { \
if (!call_eq(func, *M_CALL_IT_CREF(cont_oplist, it1), \
*M_CALL_IT_CREF(cont_oplist, it2))) \
*M_CALL_IT_CREF(cont_oplist, it2))) \
break; \
} \
} \
@@ -696,7 +696,7 @@
/* Define the FILL algorithms */
#define ALGOI_FILL_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\
/* Fill all the container with value (overwritten) */ \
/* Fill all the container with value (overwritten) */ \
static inline void \
M_C(name, _fill) (container_t l, type_t const value) \
{ \
@@ -841,7 +841,7 @@
\
static inline bool \
M_C4(name, _all_of, suffix, p) (container_t const l, \
func_t func ) \
func_t func ) \
{ \
for M_EACH(item, l, cont_oplist) { \
if (!call(func, *item)) \
@@ -1051,93 +1051,93 @@
// _flatten (takes a set of containers and returns a new container containing all flatten objects)
#define ALGOI_FOR_EACH(container, cont_oplist, func) do { \
for M_EACH(_item, container, cont_oplist) { \
func(*_item); \
} \
#define ALGOI_FOR_EACH(container, cont_oplist, func) do { \
for M_EACH(_item, container, cont_oplist) { \
func(*_item); \
} \
} while (0)
#define ALGOI_FOR_EACH_ARG(container, cont_oplist, func, ...) do { \
for M_EACH(_item, container, cont_oplist) { \
func(__VA_ARGS__, *_item); \
} \
#define ALGOI_FOR_EACH_ARG(container, cont_oplist, func, ...) do { \
for M_EACH(_item, container, cont_oplist) { \
func(__VA_ARGS__, *_item); \
} \
} while (0)
#define ALGOI_TRANSFORM(contD, contDop, contS, contSop, func) do { \
M_CALL_CLEAN(contDop, contD); \
for M_EACH(_item, contS, contSop) { \
M_GET_SUBTYPE contDop _tmp; \
M_CALL_INIT(M_GET_OPLIST contDop, _tmp); \
func(_tmp, *_item); \
M_CALL_PUSH_MOVE(contDop, contD, &_tmp); \
} \
M_IF_METHOD(REVERSE, contDop) (M_CALL_REVERSE(contDop, contD);, ) \
#define ALGOI_TRANSFORM(contD, contDop, contS, contSop, func) do { \
M_CALL_CLEAN(contDop, contD); \
for M_EACH(_item, contS, contSop) { \
M_GET_SUBTYPE contDop _tmp; \
M_CALL_INIT(M_GET_OPLIST contDop, _tmp); \
func(_tmp, *_item); \
M_CALL_PUSH_MOVE(contDop, contD, &_tmp); \
} \
M_IF_METHOD(REVERSE, contDop) (M_CALL_REVERSE(contDop, contD);, ) \
} while (0)
#define ALGOI_TRANSFORM_ARG(contD, contDop, contS, contSop, func, ...) do { \
M_CALL_CLEAN(contDop, contD); \
for M_EACH(_item, contS, contSop) { \
M_GET_SUBTYPE contDop _tmp; \
M_CALL_INIT(M_GET_OPLIST contDop, _tmp); \
func(_tmp, *_item, __VA_ARGS__); \
M_CALL_PUSH_MOVE(contDop, contD, &_tmp); \
} \
M_IF_METHOD(REVERSE, contDop) (M_CALL_REVERSE(contDop, contD);, ) \
#define ALGOI_TRANSFORM_ARG(contD, contDop, contS, contSop, func, ...) do { \
M_CALL_CLEAN(contDop, contD); \
for M_EACH(_item, contS, contSop) { \
M_GET_SUBTYPE contDop _tmp; \
M_CALL_INIT(M_GET_OPLIST contDop, _tmp); \
func(_tmp, *_item, __VA_ARGS__); \
M_CALL_PUSH_MOVE(contDop, contD, &_tmp); \
} \
M_IF_METHOD(REVERSE, contDop) (M_CALL_REVERSE(contDop, contD);, ) \
} while (0)
#define ALGOI_EXTRACT(contDst, contDstOplist, \
contSrc, contSrcOplist) do { \
M_CALL_CLEAN(contDstOplist, contDst); \
for M_EACH(_item, contSrc, contSrcOplist) { \
M_IF_METHOD(PUSH, contDstOplist)( \
M_CALL_PUSH(contDstOplist, contDst, *_item); \
, \
#define ALGOI_EXTRACT(contDst, contDstOplist, \
contSrc, contSrcOplist) do { \
M_CALL_CLEAN(contDstOplist, contDst); \
for M_EACH(_item, contSrc, contSrcOplist) { \
M_IF_METHOD(PUSH, contDstOplist)( \
M_CALL_PUSH(contDstOplist, contDst, *_item); \
, \
M_CALL_SET_KEY(contDstOplist, contDst, (*_item).key, (*_item).value); \
) \
} \
) \
} \
M_IF_METHOD(REVERSE, contDstOplist) (M_CALL_REVERSE(contDstOplist, contDst);, ) \
} while (0)
#define ALGOI_EXTRACT_FUNC(contDst, contDstOplist, \
contSrc, contSrcOplist, \
condFunc) do { \
M_CALL_CLEAN(contDstOplist, contDst); \
for M_EACH(_item, contSrc, contSrcOplist) { \
if (condFunc (*_item)) { \
M_IF_METHOD(PUSH, contDstOplist)( \
M_CALL_PUSH(contDstOplist, contDst, *_item); \
, \
#define ALGOI_EXTRACT_FUNC(contDst, contDstOplist, \
contSrc, contSrcOplist, \
condFunc) do { \
M_CALL_CLEAN(contDstOplist, contDst); \
for M_EACH(_item, contSrc, contSrcOplist) { \
if (condFunc (*_item)) { \
M_IF_METHOD(PUSH, contDstOplist)( \
M_CALL_PUSH(contDstOplist, contDst, *_item); \
, \
M_CALL_SET_KEY(contDstOplist, contDst, (*_item).key, (*_item).value); \
) \
} \
} \
) \
} \
} \
M_IF_METHOD(REVERSE, contDstOplist) (M_CALL_REVERSE(contDstOplist, contDst);, ) \
} while (0)
#define ALGOI_EXTRACT_ARG(contDst, contDstOplist, \
contSrc, contSrcOplist, \
condFunc, ...) do { \
M_CALL_CLEAN(contDstOplist, contDst); \
for M_EACH(_item, contSrc, contSrcOplist) { \
if (condFunc (__VA_ARGS__, *_item)) { \
M_IF_METHOD(PUSH, contDstOplist)( \
M_CALL_PUSH(contDstOplist, contDst, *_item); \
, \
#define ALGOI_EXTRACT_ARG(contDst, contDstOplist, \
contSrc, contSrcOplist, \
condFunc, ...) do { \
M_CALL_CLEAN(contDstOplist, contDst); \
for M_EACH(_item, contSrc, contSrcOplist) { \
if (condFunc (__VA_ARGS__, *_item)) { \
M_IF_METHOD(PUSH, contDstOplist)( \
M_CALL_PUSH(contDstOplist, contDst, *_item); \
, \
M_CALL_SET_KEY(contDstOplist, contDst, (*_item).key, (*_item).value); \
) \
} \
} \
) \
} \
} \
M_IF_METHOD(REVERSE, contDstOplist) (M_CALL_REVERSE(contDstOplist, contDstOplist);, ) \
} while (0)
#define ALGOI_REDUCE_DISPATCH(dest, destOp, dest_t, cont, contOp, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(ALGOI_REDUCE_BASIC(dest, dest_t, destOp, cont, contOp, __VA_ARGS__), \
M_IF_NARGS_EQ2(__VA_ARGS__) \
(ALGOI_REDUCE_FOR_EACH(dest, dest_t, destOp, cont, contOp, __VA_ARGS__), \
#define ALGOI_REDUCE_DISPATCH(dest, destOp, dest_t, cont, contOp, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(ALGOI_REDUCE_BASIC(dest, dest_t, destOp, cont, contOp, __VA_ARGS__), \
M_IF_NARGS_EQ2(__VA_ARGS__) \
(ALGOI_REDUCE_FOR_EACH(dest, dest_t, destOp, cont, contOp, __VA_ARGS__), \
ALGOI_REDUCE_FOR_EACH_ARG(dest, dest_t, destOp, cont, contOp, __VA_ARGS__) ) )
/* The special functions handled by ALGO_REDUCE */
@@ -1149,94 +1149,94 @@
/* Return the method associated to a reduce operation.
It returns the special function handler if function is and, or, sum or add.
Otherwise it returns the original function */
#define ALGOI_REDUCE_FUNC(reduceFunc) \
M_IF(M_KEYWORD_P(and, reduceFunc)) \
(ALGOI_REDUCE_AND, \
M_IF(M_KEYWORD_P(or, reduceFunc)) \
(ALGOI_REDUCE_OR, \
M_IF(M_KEYWORD_P(sum, reduceFunc)) \
(ALGOI_REDUCE_SUM, \
M_IF(M_KEYWORD_P(product, reduceFunc)) \
(ALGOI_REDUCE_PRODUCT, \
reduceFunc) \
) \
) \
#define ALGOI_REDUCE_FUNC(reduceFunc) \
M_IF(M_KEYWORD_P(and, reduceFunc)) \
(ALGOI_REDUCE_AND, \
M_IF(M_KEYWORD_P(or, reduceFunc)) \
(ALGOI_REDUCE_OR, \
M_IF(M_KEYWORD_P(sum, reduceFunc)) \
(ALGOI_REDUCE_SUM, \
M_IF(M_KEYWORD_P(product, reduceFunc)) \
(ALGOI_REDUCE_PRODUCT, \
reduceFunc) \
) \
) \
)
#define ALGOI_REDUCE_BASIC(dest, dest_t, destOp, cont, cont_oplist, reduceFunc) do { \
bool _init_done = false; \
for M_EACH(_item, cont, cont_oplist) { \
if (_init_done) { \
ALGOI_REDUCE_FUNC(reduceFunc) (dest, *_item); \
} else { \
M_CALL_SET(destOp, dest, *_item); \
_init_done = true; \
} \
} \
bool _init_done = false; \
for M_EACH(_item, cont, cont_oplist) { \
if (_init_done) { \
ALGOI_REDUCE_FUNC(reduceFunc) (dest, *_item); \
} else { \
M_CALL_SET(destOp, dest, *_item); \
_init_done = true; \
} \
} \
} while (0)
#define ALGOI_REDUCE_FOR_EACH(dest, dest_t, destOp, cont, cont_oplist, reduceFunc, mapFunc) do { \
bool _init_done = false; \
dest_t _tmp; \
M_CALL_INIT(destOp, _tmp); \
for M_EACH(_item, cont, cont_oplist) { \
mapFunc(_tmp, *_item); \
if (_init_done) { \
ALGOI_REDUCE_FUNC(reduceFunc) (dest, _tmp); \
} else { \
M_CALL_SET(destOp, dest, _tmp); \
_init_done = true; \
} \
} \
M_CALL_CLEAR(destOp, _tmp); \
bool _init_done = false; \
dest_t _tmp; \
M_CALL_INIT(destOp, _tmp); \
for M_EACH(_item, cont, cont_oplist) { \
mapFunc(_tmp, *_item); \
if (_init_done) { \
ALGOI_REDUCE_FUNC(reduceFunc) (dest, _tmp); \
} else { \
M_CALL_SET(destOp, dest, _tmp); \
_init_done = true; \
} \
} \
M_CALL_CLEAR(destOp, _tmp); \
} while (0)
#define ALGOI_REDUCE_FOR_EACH_ARG(dest, dest_t, destOp, cont, cont_oplist, reduceFunc, mapFunc, ...) do { \
bool _init_done = false; \
dest_t _tmp; \
M_CALL_INIT(destOp, _tmp); \
for M_EACH(_item, cont, cont_oplist) { \
mapFunc(_tmp, __VA_ARGS__, *_item); \
if (_init_done) { \
ALGOI_REDUCE_FUNC(reduceFunc) (dest, _tmp); \
} else { \
M_CALL_SET(destOp, dest, _tmp); \
_init_done = true; \
} \
} \
M_CALL_CLEAR(destOp, _tmp); \
bool _init_done = false; \
dest_t _tmp; \
M_CALL_INIT(destOp, _tmp); \
for M_EACH(_item, cont, cont_oplist) { \
mapFunc(_tmp, __VA_ARGS__, *_item); \
if (_init_done) { \
ALGOI_REDUCE_FUNC(reduceFunc) (dest, _tmp); \
} else { \
M_CALL_SET(destOp, dest, _tmp); \
_init_done = true; \
} \
} \
M_CALL_CLEAR(destOp, _tmp); \
} while (0)
#define ALGOI_INIT_VA_FUNC(d, a) \
#define ALGOI_INIT_VA_FUNC(d, a) \
M_RET_ARG2 d (M_RET_ARG1 d, a) M_DEFERRED_COMMA
#define ALGO_INIT_VAI(dest, contOp, ...) \
(void)(M_CALL_INIT(contOp, dest) M_DEFERRED_COMMA \
#define ALGO_INIT_VAI(dest, contOp, ...) \
(void)(M_CALL_INIT(contOp, dest) M_DEFERRED_COMMA \
M_MAP2(ALGOI_INIT_VA_FUNC, (dest, M_GET_PUSH contOp, ) , __VA_ARGS__) \
true)
#define ALGO_LET_INIT_VAI(dest, ...) \
#define ALGO_LET_INIT_VAI(dest, ...) \
ALGOI_LET_INIT_VAI(M_C3(m_cont_, __LINE__, dest), dest, __VA_ARGS__)
#define ALGOI_LET_INIT_VAI(cont, dest, contOp, ...) \
for(bool cont = true; cont ; /* unused */) \
for(M_GET_TYPE contOp dest; \
cont && (ALGO_INIT_VAI (dest, contOp, __VA_ARGS__), true); \
#define ALGOI_LET_INIT_VAI(cont, dest, contOp, ...) \
for(bool cont = true; cont ; /* unused */) \
for(M_GET_TYPE contOp dest; \
cont && (ALGO_INIT_VAI (dest, contOp, __VA_ARGS__), true); \
(M_CALL_CLEAR(contOp, dest), cont = false))
#define ALGOI_INSERT_AT(contDst, contDstOp, position, contSrc, contSrcOp) do { \
M_GET_IT_TYPE contSrcOp _itSrc; \
M_GET_IT_TYPE contDstOp _itDst; \
M_CALL_IT_SET(contDstOp, _itDst, position); \
for (M_CALL_IT_FIRST(contSrcOp, _itSrc, contSrc) ; \
!M_CALL_IT_END_P(contSrcOp, _itSrc) ; \
M_CALL_IT_NEXT(contSrcOp, _itSrc) ) { \
M_CALL_IT_INSERT(contDstOp, contDst, _itDst, \
*M_CALL_IT_CREF(contSrcOp, _itSrc)); \
} \
M_GET_IT_TYPE contSrcOp _itSrc; \
M_GET_IT_TYPE contDstOp _itDst; \
M_CALL_IT_SET(contDstOp, _itDst, position); \
for (M_CALL_IT_FIRST(contSrcOp, _itSrc, contSrc) ; \
!M_CALL_IT_END_P(contSrcOp, _itSrc) ; \
M_CALL_IT_NEXT(contSrcOp, _itSrc) ) { \
M_CALL_IT_INSERT(contDstOp, contDst, _itDst, \
*M_CALL_IT_CREF(contSrcOp, _itSrc)); \
} \
} while (0)
#endif
+951 -951
View File
File diff suppressed because it is too large. Load diff
+36 -36
View File
@@ -35,7 +35,7 @@
APPLE Clang defines __GNUC__ to be only 4 despite having full support
for atomic.
*/
#if defined(__cplusplus) && __cplusplus >= 201103L \
#if defined(__cplusplus) && __cplusplus >= 201103L \
&& !(defined(__GNUC__) && __GNUC__ < 5 && !defined(__APPLE__))
/* NOTE: This is what the stdatomic.h header shall do in C++ mode. */
@@ -128,7 +128,7 @@ using std::memory_order_seq_cst;
*/
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) ) \
|| (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__cplusplus) && (__GNUC__*100 + __GNUC_MINOR__) >= 409) \
|| (defined(__clang__) && __clang_major__ >= 4) \
|| (defined(__clang__) && __clang_major__ >= 4) \
|| (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1800)
#include <stdatomic.h>
@@ -167,12 +167,12 @@ M_BEGIN_PROTECTED_CODE
_lock : the mutex lock.
Support up to sizeof (long long) type.
*/
#define _Atomic(T) \
struct { \
T volatile _val; \
T _zero; \
T _previous; \
m_mutex_t _lock; \
#define _Atomic(T) \
struct { \
T volatile _val; \
T _zero; \
T _previous; \
m_mutex_t _lock; \
}
/* Define the supported memory order.
@@ -217,8 +217,8 @@ typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
#endif
/* Detect if stdint.h was included */
#if (defined (INTMAX_C) && defined (UINTMAX_C) && !defined(__cplusplus)) || \
defined (_STDINT_H) || defined (_STDINT_H_) || defined (_STDINT) || \
#if (defined (INTMAX_C) && defined (UINTMAX_C) && !defined(__cplusplus)) || \
defined (_STDINT_H) || defined (_STDINT_H_) || defined (_STDINT) || \
defined (_SYS_STDINT_H_)
/* Define additional atomic types */
typedef _Atomic(intmax_t) atomic_intmax_t;
@@ -241,10 +241,10 @@ static inline long long atomic_fetch_unlock (m_mutex_t *lock, long long val)
The trick is computing _val - _zero within the lock, then
returns retvalue + _zero after the release of the lock.
*/
#define atomic_fetch_op(ptr, val, op) \
(m_mutex_lock((ptr)->_lock), \
(ptr)->_previous = (ptr)->_val, \
(ptr)->_val op (val), \
#define atomic_fetch_op(ptr, val, op) \
(m_mutex_lock((ptr)->_lock), \
(ptr)->_previous = (ptr)->_val, \
(ptr)->_val op (val), \
atomic_fetch_unlock(&(ptr)->_lock, (long long)((ptr)->_previous-(ptr)->_zero))+(ptr)->_zero)
/* Perform an atomic add (EMULATION) */
@@ -264,49 +264,49 @@ static inline long long atomic_fetch_unlock (m_mutex_t *lock, long long val)
#define ATOMIC_VAR_INIT(val) { val, 0, 0, M_MUTEXI_INIT_VALUE }
/* Initialize an atomic variable */
#define atomic_init(ptr, val) \
#define atomic_init(ptr, val) \
(m_mutex_init((ptr)->_lock), (ptr)->_val = val, (ptr)->_zero = 0)
/* (INTERNAL) Load an atomic variable within a lock
(needed for variable greater than CPU atomic size) */
#define atomic_load_lock(ptr) \
(m_mutex_lock((ptr)->_lock), \
(ptr)->_previous = (ptr)->_val, \
#define atomic_load_lock(ptr) \
(m_mutex_lock((ptr)->_lock), \
(ptr)->_previous = (ptr)->_val, \
atomic_fetch_unlock(&(ptr)->_lock, (long long) ((ptr)->_previous-(ptr)->_zero))+(ptr)->_zero)
/* (INTERNAL) Store an atomic variable within a lock
(needed for variable greater than CPU atomic size) */
#define atomic_store_lock(ptr, val) \
(m_mutex_lock((ptr)->_lock), \
(ptr)->_val = (val), \
#define atomic_store_lock(ptr, val) \
(m_mutex_lock((ptr)->_lock), \
(ptr)->_val = (val), \
m_mutex_unlock((ptr)->_lock))
/* Atomic load of a variable (EMULATION)
If the atomic type size is not greater than the CPU atomic size,
we can perform a direct read of the variable (much faster) */
#define atomic_load(ptr) \
( sizeof ((ptr)->_val) <= ATOMICI_MIN_RW_SIZE \
? (ptr)->_val \
#define atomic_load(ptr) \
( sizeof ((ptr)->_val) <= ATOMICI_MIN_RW_SIZE \
? (ptr)->_val \
: atomic_load_lock(ptr))
/* Atomic store of a variable (EMULATION)
If the atomic type size is not greater than the CPU atomic size,
we can perform a direct write of the variable (much faster) */
#define atomic_store(ptr, val) do { \
if ( sizeof ((ptr)->_val) <= ATOMICI_MIN_RW_SIZE) { \
(ptr)->_val = (val); \
} else { \
long long _offset = (long long) ((val) - (ptr)->_zero); \
atomic_store_lock(ptr, (ptr)->_zero + _offset); \
} \
#define atomic_store(ptr, val) do { \
if ( sizeof ((ptr)->_val) <= ATOMICI_MIN_RW_SIZE) { \
(ptr)->_val = (val); \
} else { \
long long _offset = (long long) ((val) - (ptr)->_zero); \
atomic_store_lock(ptr, (ptr)->_zero + _offset); \
} \
} while (0)
/* Perform a CAS (Compare and swap) operation (EMULATION) */
#define atomic_compare_exchange_strong(ptr, exp, val) \
(m_mutex_lock((ptr)->_lock), \
atomic_fetch_unlock(&(ptr)->_lock, \
(ptr)->_val == *(exp) \
? ((ptr)->_val = (val), true) \
#define atomic_compare_exchange_strong(ptr, exp, val) \
(m_mutex_lock((ptr)->_lock), \
atomic_fetch_unlock(&(ptr)->_lock, \
(ptr)->_val == *(exp) \
? ((ptr)->_val = (val), true) \
: (*(exp) = (ptr)->_val, false)))
+40 -40
View File
@@ -47,13 +47,13 @@ typedef uint64_t bitset_limb_ct;
#define BITSETI_FROM_ALLOC(n) ((n) * BITSET_LIMB_BIT)
// Contract of a bitset
#define BITSETI_CONTRACT(t) do { \
assert (t != NULL); \
assert (t->size <= BITSETI_FROM_ALLOC (t->alloc)); \
assert (t->alloc <= ((size_t)-1) / BITSET_LIMB_BIT); \
assert (t->size < ((size_t)-1) - BITSET_LIMB_BIT); \
assert (t->size == 0 || t->ptr != NULL); \
assert (t->alloc == 0 || t->ptr != NULL); \
#define BITSETI_CONTRACT(t) do { \
assert (t != NULL); \
assert (t->size <= BITSETI_FROM_ALLOC (t->alloc)); \
assert (t->alloc <= ((size_t)-1) / BITSET_LIMB_BIT); \
assert (t->size < ((size_t)-1) - BITSET_LIMB_BIT); \
assert (t->size == 0 || t->ptr != NULL); \
assert (t->alloc == 0 || t->ptr != NULL); \
} while (0)
@@ -754,39 +754,39 @@ bitset_clz(const bitset_t set)
}
/* Oplist for a bitset */
#define BITSET_OPLIST \
(INIT(bitset_init) \
,INIT_SET(bitset_init_set) \
,INIT_WITH(API_1(M_INIT_VAI)) \
,SET(bitset_set) \
,CLEAR(bitset_clear) \
,INIT_MOVE(bitset_init_move) \
,MOVE(bitset_move) \
,SWAP(bitset_swap) \
,TYPE(bitset_t) \
,SUBTYPE(bool) \
,TEST_EMPTY(bitset_empty_p), \
,GET_SIZE(bitset_size) \
,IT_TYPE(bitset_it_t) \
,IT_FIRST(bitset_it) \
,IT_SET(bitset_it_set) \
,IT_LAST(bitset_it_last) \
,IT_END(bitset_it_end) \
,IT_END_P(bitset_end_p) \
,IT_LAST_P(bitset_last_p) \
,IT_EQUAL_P(bitset_it_equal_p) \
,IT_NEXT(bitset_next) \
,IT_PREVIOUS(bitset_previous) \
,IT_CREF(bitset_cref) \
,CLEAN(bitset_clean) \
,PUSH(bitset_push_back) \
,POP(bitset_pop_back) \
,HASH(bitset_hash) \
,GET_STR(bitset_get_str) \
,OUT_STR(bitset_out_str) \
,PARSE_STR(bitset_parse_str) \
,IN_STR(bitset_in_str) \
,EQUAL(bitset_equal_p) \
#define BITSET_OPLIST \
(INIT(bitset_init) \
,INIT_SET(bitset_init_set) \
,INIT_WITH(API_1(M_INIT_VAI)) \
,SET(bitset_set) \
,CLEAR(bitset_clear) \
,INIT_MOVE(bitset_init_move) \
,MOVE(bitset_move) \
,SWAP(bitset_swap) \
,TYPE(bitset_t) \
,SUBTYPE(bool) \
,TEST_EMPTY(bitset_empty_p), \
,GET_SIZE(bitset_size) \
,IT_TYPE(bitset_it_t) \
,IT_FIRST(bitset_it) \
,IT_SET(bitset_it_set) \
,IT_LAST(bitset_it_last) \
,IT_END(bitset_it_end) \
,IT_END_P(bitset_end_p) \
,IT_LAST_P(bitset_last_p) \
,IT_EQUAL_P(bitset_it_equal_p) \
,IT_NEXT(bitset_next) \
,IT_PREVIOUS(bitset_previous) \
,IT_CREF(bitset_cref) \
,CLEAN(bitset_clean) \
,PUSH(bitset_push_back) \
,POP(bitset_pop_back) \
,HASH(bitset_hash) \
,GET_STR(bitset_get_str) \
,OUT_STR(bitset_out_str) \
,PARSE_STR(bitset_parse_str) \
,IN_STR(bitset_in_str) \
,EQUAL(bitset_equal_p) \
)
/* Register the OPLIST as a global one */
+1201 -1201
View File
File diff suppressed because it is too large. Load diff
+924 -924
View File
File diff suppressed because it is too large. Load diff
+394 -394
View File
@@ -34,74 +34,74 @@ M_BEGIN_PROTECTED_CODE
/* Minimum number of nodes per group of nodes */
#define C_MEMPOOL_MIN_NODE_PER_GROUP 16
#define C_MEMPOOL_DEF(name, type_t) \
M_BEGIN_PROTECTED_CODE \
C_MEMPOOL_DEF_SINGLY_LIST(name, type_t) \
C_MEMPOOL_DEF_LF_QUEUE(name, type_t) \
C_MEMPOOL_DEF_LFMP_THREAD_MEMPOOL(name, type_t) \
C_MEMPOOL_DEF_SYSTEM_ALLOC(name, type_t) \
C_MEMPOOL_DEF_LF_MEMPOOL(name, type_t) \
#define C_MEMPOOL_DEF(name, type_t) \
M_BEGIN_PROTECTED_CODE \
C_MEMPOOL_DEF_SINGLY_LIST(name, type_t) \
C_MEMPOOL_DEF_LF_QUEUE(name, type_t) \
C_MEMPOOL_DEF_LFMP_THREAD_MEMPOOL(name, type_t) \
C_MEMPOOL_DEF_SYSTEM_ALLOC(name, type_t) \
C_MEMPOOL_DEF_LF_MEMPOOL(name, type_t) \
M_END_PROTECTED_CODE
/* Classic internal Singly List without allocation */
#define C_MEMPOOL_DEF_SINGLY_LIST(name, type_t) \
\
typedef struct M_C(name, _slist_node_s) { \
struct M_C(name, _slist_node_s) *next; \
type_t data; \
} M_C(name, _slist_node_ct); \
\
typedef struct M_C(name, _slist_node_s) *M_C(name, _slist_ct)[1]; \
\
static inline void \
M_C(name, _slist_init)(M_C(name, _slist_ct) list) \
{ \
*list = NULL; \
} \
\
static inline void \
M_C(name, _slist_push)(M_C(name, _slist_ct) list, \
M_C(name, _slist_node_ct) *node) \
{ \
node->next = *list; \
*list = node; \
} \
\
static inline M_C(name, _slist_node_ct) * \
M_C(name, _slist_pop)(M_C(name, _slist_ct) list) \
{ \
assert (*list != NULL); \
M_C(name, _slist_node_ct) *node = *list; \
*list = node->next; \
M_IF_DEBUG(node->next = NULL;) \
return node; \
} \
\
static inline bool \
M_C(name, _slist_empty_p)(M_C(name, _slist_ct) list) \
{ \
return *list == NULL; \
} \
\
static inline void \
M_C(name, _slist_move)(M_C(name, _slist_ct) list, \
M_C(name, _slist_ct) src) \
{ \
*list = *src; \
*src = NULL; \
} \
\
static inline void \
M_C(name, _slist_clear)(M_C(name, _slist_ct) list) \
{ \
M_C(name, _slist_node_ct) *it = *list, *next; \
while (it) { \
next = it->next; \
M_MEMORY_DEL(it); \
it = next; \
} \
*list = NULL; \
} \
#define C_MEMPOOL_DEF_SINGLY_LIST(name, type_t) \
\
typedef struct M_C(name, _slist_node_s) { \
struct M_C(name, _slist_node_s) *next; \
type_t data; \
} M_C(name, _slist_node_ct); \
\
typedef struct M_C(name, _slist_node_s) *M_C(name, _slist_ct)[1]; \
\
static inline void \
M_C(name, _slist_init)(M_C(name, _slist_ct) list) \
{ \
*list = NULL; \
} \
\
static inline void \
M_C(name, _slist_push)(M_C(name, _slist_ct) list, \
M_C(name, _slist_node_ct) *node) \
{ \
node->next = *list; \
*list = node; \
} \
\
static inline M_C(name, _slist_node_ct) * \
M_C(name, _slist_pop)(M_C(name, _slist_ct) list) \
{ \
assert (*list != NULL); \
M_C(name, _slist_node_ct) *node = *list; \
*list = node->next; \
M_IF_DEBUG(node->next = NULL;) \
return node; \
} \
\
static inline bool \
M_C(name, _slist_empty_p)(M_C(name, _slist_ct) list) \
{ \
return *list == NULL; \
} \
\
static inline void \
M_C(name, _slist_move)(M_C(name, _slist_ct) list, \
M_C(name, _slist_ct) src) \
{ \
*list = *src; \
*src = NULL; \
} \
\
static inline void \
M_C(name, _slist_clear)(M_C(name, _slist_ct) list) \
{ \
M_C(name, _slist_node_ct) *it = *list, *next; \
while (it) { \
next = it->next; \
M_MEMORY_DEL(it); \
it = next; \
} \
*list = NULL; \
} \
/* Lock Free free queue list (not generic one) of lists without allocation
@@ -123,212 +123,212 @@ M_BEGIN_PROTECTED_CODE
*/
/* TODO: Optimize alignement to reduce memory consumption. NIL object can use []
to reduce memory consumption too (non compatible with C++ ...) */
#define C_MEMPOOL_DEF_LF_QUEUE(name, type_t) \
\
typedef struct M_C(name, _lf_node_s) { \
M_ATTR_EXTENSION _Atomic(struct M_C(name, _lf_node_s) *) next; \
m_gc_atomic_ticket_ct cpt; \
M_C(name, _slist_ct) list; \
} M_C(name, _lf_node_t); \
\
typedef struct M_C(name, _lflist_s) { \
M_ATTR_EXTENSION _Atomic(M_C(name, _lf_node_t) *) head; \
char align1[M_ALIGN_FOR_CACHELINE_EXCLUSION]; \
M_ATTR_EXTENSION _Atomic(M_C(name, _lf_node_t) *) tail; \
char align2[M_ALIGN_FOR_CACHELINE_EXCLUSION]; \
M_C(name, _lf_node_t) nil; \
} M_C(name, _lflist_ct)[1]; \
\
static inline void \
M_C(name, _lflist_init)(M_C(name, _lflist_ct) list, \
M_C(name, _lf_node_t) *node) \
{ \
atomic_init(&list->head, node); \
atomic_init(&list->tail, node); \
atomic_store_explicit(&node->next, &list->nil, memory_order_relaxed); \
} \
\
static inline bool \
M_C(name, _lflist_empty_p)(M_C(name, _lflist_ct) list) \
{ \
return atomic_load(&list->tail) == atomic_load(&list->head); \
} \
\
static inline void \
M_C(name, _lflist_push)(M_C(name, _lflist_ct) list, \
#define C_MEMPOOL_DEF_LF_QUEUE(name, type_t) \
\
typedef struct M_C(name, _lf_node_s) { \
M_ATTR_EXTENSION _Atomic(struct M_C(name, _lf_node_s) *) next; \
m_gc_atomic_ticket_ct cpt; \
M_C(name, _slist_ct) list; \
} M_C(name, _lf_node_t); \
\
typedef struct M_C(name, _lflist_s) { \
M_ATTR_EXTENSION _Atomic(M_C(name, _lf_node_t) *) head; \
char align1[M_ALIGN_FOR_CACHELINE_EXCLUSION]; \
M_ATTR_EXTENSION _Atomic(M_C(name, _lf_node_t) *) tail; \
char align2[M_ALIGN_FOR_CACHELINE_EXCLUSION]; \
M_C(name, _lf_node_t) nil; \
} M_C(name, _lflist_ct)[1]; \
\
static inline void \
M_C(name, _lflist_init)(M_C(name, _lflist_ct) list, \
M_C(name, _lf_node_t) *node) \
{ \
atomic_init(&list->head, node); \
atomic_init(&list->tail, node); \
atomic_store_explicit(&node->next, &list->nil, memory_order_relaxed); \
} \
\
static inline bool \
M_C(name, _lflist_empty_p)(M_C(name, _lflist_ct) list) \
{ \
return atomic_load(&list->tail) == atomic_load(&list->head); \
} \
\
static inline void \
M_C(name, _lflist_push)(M_C(name, _lflist_ct) list, \
M_C(name, _lf_node_t) *node, m_core_backoff_ct bkoff) \
{ \
M_C(name, _lf_node_t) *tail; \
M_C(name, _lf_node_t) *next; \
\
atomic_store_explicit(&node->next, &list->nil, memory_order_relaxed); \
m_core_backoff_reset(bkoff); \
while (true) { \
tail = atomic_load(&list->tail); \
next = atomic_load_explicit(&tail->next, memory_order_acquire); \
if (M_UNLIKELY(next != &list->nil)) { \
/* Tail was not pointing to the last node \
Try to swing Tail to the next node */ \
atomic_compare_exchange_weak_explicit(&list->tail, \
&tail, next, \
memory_order_release, \
memory_order_relaxed); \
} else { \
/* Try to link node at the end of the linked list */ \
if (atomic_compare_exchange_strong_explicit(&tail->next, \
&next, node, \
memory_order_release, \
memory_order_relaxed)) \
break; \
m_core_backoff_wait(bkoff); \
} \
} \
/* Enqueue is done. Try to swing Tail to the inserted node \
If it fails, someone else will do it or has already did it. */ \
atomic_compare_exchange_strong_explicit(&list->tail, &tail, node, \
memory_order_acq_rel, \
memory_order_relaxed); \
} \
\
static inline M_C(name, _lf_node_t) * \
{ \
M_C(name, _lf_node_t) *tail; \
M_C(name, _lf_node_t) *next; \
\
atomic_store_explicit(&node->next, &list->nil, memory_order_relaxed); \
m_core_backoff_reset(bkoff); \
while (true) { \
tail = atomic_load(&list->tail); \
next = atomic_load_explicit(&tail->next, memory_order_acquire); \
if (M_UNLIKELY(next != &list->nil)) { \
/* Tail was not pointing to the last node \
Try to swing Tail to the next node */ \
atomic_compare_exchange_weak_explicit(&list->tail, \
&tail, next, \
memory_order_release, \
memory_order_relaxed); \
} else { \
/* Try to link node at the end of the linked list */ \
if (atomic_compare_exchange_strong_explicit(&tail->next, \
&next, node, \
memory_order_release, \
memory_order_relaxed)) \
break; \
m_core_backoff_wait(bkoff); \
} \
} \
/* Enqueue is done. Try to swing Tail to the inserted node \
If it fails, someone else will do it or has already did it. */ \
atomic_compare_exchange_strong_explicit(&list->tail, &tail, node, \
memory_order_acq_rel, \
memory_order_relaxed); \
} \
\
static inline M_C(name, _lf_node_t) * \
M_C(name, _lflist_pop)(M_C(name, _lflist_ct) list, m_core_backoff_ct bkoff) \
{ \
M_C(name, _lf_node_t) *head; \
M_C(name, _lf_node_t) *tail; \
M_C(name, _lf_node_t) *next; \
\
/* Reinitialize backoff */ \
m_core_backoff_reset(bkoff); \
while (true) { \
head = atomic_load(&list->head); \
tail = atomic_load(&list->tail); \
next = atomic_load(&head->next); \
/* Are head, tail, and next consistent?*/ \
if (M_LIKELY(head == \
atomic_load_explicit(&list->head, memory_order_relaxed))) \
{ \
/* Is queue empty or Tail falling behind? */ \
if (head == tail) { \
/* Is queue empty? */ \
if (next == &list->nil) \
return NULL; \
/* Tail is falling behind. Try to advance it */ \
atomic_compare_exchange_strong_explicit(&list->tail, &tail, \
next, \
memory_order_release, \
memory_order_relaxed); \
} else { \
/* Try to swing Head to the next node */ \
if (atomic_compare_exchange_strong_explicit(&list->head, \
&head, next, \
{ \
M_C(name, _lf_node_t) *head; \
M_C(name, _lf_node_t) *tail; \
M_C(name, _lf_node_t) *next; \
\
/* Reinitialize backoff */ \
m_core_backoff_reset(bkoff); \
while (true) { \
head = atomic_load(&list->head); \
tail = atomic_load(&list->tail); \
next = atomic_load(&head->next); \
/* Are head, tail, and next consistent?*/ \
if (M_LIKELY(head == \
atomic_load_explicit(&list->head, memory_order_relaxed))) \
{ \
/* Is queue empty or Tail falling behind? */ \
if (head == tail) { \
/* Is queue empty? */ \
if (next == &list->nil) \
return NULL; \
/* Tail is falling behind. Try to advance it */ \
atomic_compare_exchange_strong_explicit(&list->tail, &tail, \
next, \
memory_order_release, \
memory_order_relaxed); \
} else { \
/* Try to swing Head to the next node */ \
if (atomic_compare_exchange_strong_explicit(&list->head, \
&head, next, \
memory_order_release, \
memory_order_relaxed)) { \
break; \
} \
/* Failure: perform a random exponential backoff */ \
m_core_backoff_wait(bkoff); \
} \
} \
} \
break; \
} \
/* Failure: perform a random exponential backoff */ \
m_core_backoff_wait(bkoff); \
} \
} \
} \
/* dequeue returns an element that becomes the new dummy element (the new head), \
and the former dummy element (the former head) is removed: \
and the former dummy element (the former head) is removed: \
Since we want a link of free list, and we don't care about the content itsef, \
provided that the node we return is older than the one we should return, \
Therefore, we return the previous dummy head. \
As such, it is not the original MSqueue algorithm. */ \
M_IF_DEBUG(atomic_store(&head->next, (M_C(name, _lf_node_t) *) 0);) \
return head; \
} \
\
/* Dequeue a node if the node is old enough */ \
static inline M_C(name, _lf_node_t) * \
M_C(name, _lflist_pop_if)(M_C(name, _lflist_ct) list, \
m_gc_ticket_ct age, m_core_backoff_ct bkoff) \
{ \
M_C(name, _lf_node_t) *head; \
M_C(name, _lf_node_t) *tail; \
M_C(name, _lf_node_t) *next; \
\
m_core_backoff_reset(bkoff); \
while (true) { \
head = atomic_load(&list->head); \
tail = atomic_load(&list->tail); \
next = atomic_load(&head->next); \
Therefore, we return the previous dummy head. \
As such, it is not the original MSqueue algorithm. */ \
M_IF_DEBUG(atomic_store(&head->next, (M_C(name, _lf_node_t) *) 0);) \
return head; \
} \
\
/* Dequeue a node if the node is old enough */ \
static inline M_C(name, _lf_node_t) * \
M_C(name, _lflist_pop_if)(M_C(name, _lflist_ct) list, \
m_gc_ticket_ct age, m_core_backoff_ct bkoff) \
{ \
M_C(name, _lf_node_t) *head; \
M_C(name, _lf_node_t) *tail; \
M_C(name, _lf_node_t) *next; \
\
m_core_backoff_reset(bkoff); \
while (true) { \
head = atomic_load(&list->head); \
tail = atomic_load(&list->tail); \
next = atomic_load(&head->next); \
if (M_LIKELY(head == atomic_load_explicit(&list->head, memory_order_relaxed))) \
{ \
if (head == tail) { \
if (next == &list->nil) \
return NULL; \
{ \
if (head == tail) { \
if (next == &list->nil) \
return NULL; \
atomic_compare_exchange_strong_explicit(&list->tail, &tail, next, \
memory_order_release, \
memory_order_relaxed); \
} else { \
/* Test if the node is old enought to be popped */ \
memory_order_release, \
memory_order_relaxed); \
} else { \
/* Test if the node is old enought to be popped */ \
if (atomic_load_explicit(&next->cpt, memory_order_relaxed) >= age) \
return NULL; \
/* Try to swing Head to the next node */ \
if (atomic_compare_exchange_strong_explicit(&list->head, \
&head, next, \
return NULL; \
/* Try to swing Head to the next node */ \
if (atomic_compare_exchange_strong_explicit(&list->head, \
&head, next, \
memory_order_release, \
memory_order_relaxed)) { \
break; \
} \
m_core_backoff_wait(bkoff); \
} \
} \
} \
M_IF_DEBUG(atomic_store(&head->next, (M_C(name, _lf_node_t) *) 0);) \
return head; \
} \
\
static inline void \
M_C(name, _lflist_clear)(M_C(name, _lflist_ct) list) \
{ \
m_core_backoff_ct bkoff; \
m_core_backoff_init(bkoff); \
while (true) { \
M_C(name, _lf_node_t) *node = M_C(name, _lflist_pop)(list, bkoff); \
if (node == NULL) break; \
M_C(name, _lf_node_t) *next = atomic_load_explicit(&node->next, \
break; \
} \
m_core_backoff_wait(bkoff); \
} \
} \
} \
M_IF_DEBUG(atomic_store(&head->next, (M_C(name, _lf_node_t) *) 0);) \
return head; \
} \
\
static inline void \
M_C(name, _lflist_clear)(M_C(name, _lflist_ct) list) \
{ \
m_core_backoff_ct bkoff; \
m_core_backoff_init(bkoff); \
while (true) { \
M_C(name, _lf_node_t) *node = M_C(name, _lflist_pop)(list, bkoff); \
if (node == NULL) break; \
M_C(name, _lf_node_t) *next = atomic_load_explicit(&node->next, \
memory_order_relaxed); \
M_C(name, _slist_clear)(node->list); \
M_MEMORY_DEL(node); \
node = next; \
} \
/* Dummy node to free too */ \
M_C(name, _lf_node_t) *dummy; \
dummy = atomic_load_explicit(&list->head, memory_order_relaxed); \
M_C(name, _slist_clear)(dummy->list); \
M_MEMORY_DEL(dummy); \
} \
M_C(name, _slist_clear)(node->list); \
M_MEMORY_DEL(node); \
node = next; \
} \
/* Dummy node to free too */ \
M_C(name, _lf_node_t) *dummy; \
dummy = atomic_load_explicit(&list->head, memory_order_relaxed); \
M_C(name, _slist_clear)(dummy->list); \
M_MEMORY_DEL(dummy); \
} \
/* System node allocator: request memory to the system.
As such it is a non Lock-Free path. */
#define C_MEMPOOL_DEF_SYSTEM_ALLOC(name, type_t) \
\
static inline M_C(name, _lf_node_t) * \
M_C(name, _alloc_node)(unsigned int initial) \
{ \
M_C(name, _lf_node_t) * node; \
node = M_MEMORY_ALLOC(M_C(name, _lf_node_t)); \
if (M_UNLIKELY(node == NULL)) { \
M_MEMORY_FULL(sizeof(M_C(name, _lf_node_t))); \
return NULL; \
} \
atomic_init(&node->next, (M_C(name, _lf_node_t) *) 0); \
atomic_init(&node->cpt, 0UL); \
M_C(name, _slist_init)(node->list); \
for(unsigned i = 0; i < initial; i++) { \
M_C(name, _slist_node_ct) *n; \
n = M_MEMORY_ALLOC(M_C(name, _slist_node_ct)); \
if (M_UNLIKELY(n == NULL)) { \
M_MEMORY_FULL(sizeof(M_C(name, _lf_node_t))); \
return NULL; \
} \
M_C(name, _slist_push)(node->list, n); \
} \
return node; \
} \
#define C_MEMPOOL_DEF_SYSTEM_ALLOC(name, type_t) \
\
static inline M_C(name, _lf_node_t) * \
M_C(name, _alloc_node)(unsigned int initial) \
{ \
M_C(name, _lf_node_t) * node; \
node = M_MEMORY_ALLOC(M_C(name, _lf_node_t)); \
if (M_UNLIKELY(node == NULL)) { \
M_MEMORY_FULL(sizeof(M_C(name, _lf_node_t))); \
return NULL; \
} \
atomic_init(&node->next, (M_C(name, _lf_node_t) *) 0); \
atomic_init(&node->cpt, 0UL); \
M_C(name, _slist_init)(node->list); \
for(unsigned i = 0; i < initial; i++) { \
M_C(name, _slist_node_ct) *n; \
n = M_MEMORY_ALLOC(M_C(name, _slist_node_ct)); \
if (M_UNLIKELY(n == NULL)) { \
M_MEMORY_FULL(sizeof(M_C(name, _lf_node_t))); \
return NULL; \
} \
M_C(name, _slist_push)(node->list, n); \
} \
return node; \
} \
/* Concurrent Memory pool
The data structure is the following.
@@ -386,161 +386,161 @@ M_BEGIN_PROTECTED_CODE
As such it won't support more than ULONG_MAX sleep for all threads.
*/
#define C_MEMPOOL_DEF_LFMP_THREAD_MEMPOOL(name, type_t) \
\
typedef struct M_C(name, _lfmp_thread_s) { \
M_C(name, _slist_ct) free; \
M_C(name, _slist_ct) to_be_reclaimed; \
M_CACHELINE_ALIGN(align1, M_C(name, _slist_ct), M_C(name, _slist_ct)); \
} M_C(name, _lfmp_thread_ct); \
\
static inline void \
M_C(name, _lfmp_thread_init)(M_C(name, _lfmp_thread_ct) *t) \
{ \
M_C(name, _slist_init)(t->free); \
M_C(name, _slist_init)(t->to_be_reclaimed); \
} \
\
static inline void \
M_C(name, _lfmp_thread_clear)(M_C(name, _lfmp_thread_ct) *t) \
{ \
assert(M_C(name, _slist_empty_p)(t->to_be_reclaimed)); \
M_C(name, _slist_clear)(t->free); \
M_C(name, _slist_clear)(t->to_be_reclaimed); \
} \
#define C_MEMPOOL_DEF_LFMP_THREAD_MEMPOOL(name, type_t) \
\
typedef struct M_C(name, _lfmp_thread_s) { \
M_C(name, _slist_ct) free; \
M_C(name, _slist_ct) to_be_reclaimed; \
M_CACHELINE_ALIGN(align1, M_C(name, _slist_ct), M_C(name, _slist_ct)); \
} M_C(name, _lfmp_thread_ct); \
\
static inline void \
M_C(name, _lfmp_thread_init)(M_C(name, _lfmp_thread_ct) *t) \
{ \
M_C(name, _slist_init)(t->free); \
M_C(name, _slist_init)(t->to_be_reclaimed); \
} \
\
static inline void \
M_C(name, _lfmp_thread_clear)(M_C(name, _lfmp_thread_ct) *t) \
{ \
assert(M_C(name, _slist_empty_p)(t->to_be_reclaimed)); \
M_C(name, _slist_clear)(t->free); \
M_C(name, _slist_clear)(t->to_be_reclaimed); \
} \
/* NOTE: once a node is deleted, its data are kept readable until the future GC */
#define C_MEMPOOL_DEF_LF_MEMPOOL(name, type_t) \
\
typedef struct M_C(name, _s) { \
unsigned initial; \
M_C(name, _lfmp_thread_ct) *thread_data; \
M_C(name, _lflist_ct) free; \
M_C(name, _lflist_ct) to_be_reclaimed; \
M_C(name, _lflist_ct) empty; \
m_gc_mempool_list_ct mempool_node; \
struct m_gc_s *gc_mem; \
} M_C(name, _t)[1]; \
\
/* Garbage collect of the nodes of the mempool on sleep */ \
static inline void \
M_C(name, _int_gc_on_sleep)(m_gc_t gc_mem, m_gc_mempool_list_ct *data, \
m_gc_tid_t id, m_gc_ticket_ct ticket, m_gc_ticket_ct min_ticket) \
{ \
/* Get back the mempool from the node */ \
struct M_C(name, _s) *mempool = \
#define C_MEMPOOL_DEF_LF_MEMPOOL(name, type_t) \
\
typedef struct M_C(name, _s) { \
unsigned initial; \
M_C(name, _lfmp_thread_ct) *thread_data; \
M_C(name, _lflist_ct) free; \
M_C(name, _lflist_ct) to_be_reclaimed; \
M_C(name, _lflist_ct) empty; \
m_gc_mempool_list_ct mempool_node; \
struct m_gc_s *gc_mem; \
} M_C(name, _t)[1]; \
\
/* Garbage collect of the nodes of the mempool on sleep */ \
static inline void \
M_C(name, _int_gc_on_sleep)(m_gc_t gc_mem, m_gc_mempool_list_ct *data, \
m_gc_tid_t id, m_gc_ticket_ct ticket, m_gc_ticket_ct min_ticket) \
{ \
/* Get back the mempool from the node */ \
struct M_C(name, _s) *mempool = \
M_TYPE_FROM_FIELD(struct M_C(name, _s), data, m_gc_mempool_list_ct, mempool_node); \
\
\
/* Move the local nodes of the mempool to be reclaimed to the thread into the global pool */ \
if (!M_C(name, _slist_empty_p)(mempool->thread_data[id].to_be_reclaimed)) { \
M_C(name, _lf_node_t) *node; \
/* Get a new empty group of nodes */ \
M_C(name, _lf_node_t) *node; \
/* Get a new empty group of nodes */ \
node = M_C(name, _lflist_pop)(mempool->empty, gc_mem->thread_data[id].bkoff); \
if (M_UNLIKELY (node == NULL)) { \
/* Fail to get an empty group of node. \
Alloc a new one from the system */ \
node = M_C(name, _alloc_node)(0); \
assert(node != NULL); \
} \
assert(M_C(name, _slist_empty_p)(node->list)); \
if (M_UNLIKELY (node == NULL)) { \
/* Fail to get an empty group of node. \
Alloc a new one from the system */ \
node = M_C(name, _alloc_node)(0); \
assert(node != NULL); \
} \
assert(M_C(name, _slist_empty_p)(node->list)); \
M_C(name, _slist_move)(node->list, mempool->thread_data[id].to_be_reclaimed); \
atomic_store_explicit(&node->cpt, ticket, memory_order_relaxed); \
atomic_store_explicit(&node->cpt, ticket, memory_order_relaxed); \
M_C(name, _lflist_push)(mempool->to_be_reclaimed, node, gc_mem->thread_data[id].bkoff); \
} \
\
/* Perform a GC of the freelist of nodes */ \
while (true) { \
M_C(name, _lf_node_t) *node; \
node = M_C(name, _lflist_pop_if)(mempool->to_be_reclaimed, \
} \
\
/* Perform a GC of the freelist of nodes */ \
while (true) { \
M_C(name, _lf_node_t) *node; \
node = M_C(name, _lflist_pop_if)(mempool->to_be_reclaimed, \
min_ticket, gc_mem->thread_data[id].bkoff); \
if (node == NULL) break; \
if (node == NULL) break; \
M_C(name, _lflist_push)(mempool->free, node, gc_mem->thread_data[id].bkoff); \
} \
} \
\
static inline void \
M_C(name, _init)(M_C(name, _t) mem, m_gc_t gc_mem, \
unsigned init_node_count, unsigned init_group_count) \
{ \
const size_t max_thread = gc_mem->max_thread; \
/* Initialize the thread data of the mempool */ \
} \
} \
\
static inline void \
M_C(name, _init)(M_C(name, _t) mem, m_gc_t gc_mem, \
unsigned init_node_count, unsigned init_group_count) \
{ \
const size_t max_thread = gc_mem->max_thread; \
/* Initialize the thread data of the mempool */ \
mem->thread_data = M_MEMORY_REALLOC(M_C(name, _lfmp_thread_ct), NULL, max_thread); \
if (mem->thread_data == NULL) { \
M_MEMORY_FULL(max_thread * sizeof(M_C(name, _lfmp_thread_ct))); \
return; \
} \
for(unsigned i = 0; i < max_thread;i++) { \
M_C(name, _lfmp_thread_init)(&mem->thread_data[i]); \
} \
/* Preallocate some group of nodes for the mempool */ \
mem->initial = M_MAX(C_MEMPOOL_MIN_NODE_PER_GROUP, init_node_count); \
if (mem->thread_data == NULL) { \
M_MEMORY_FULL(max_thread * sizeof(M_C(name, _lfmp_thread_ct))); \
return; \
} \
for(unsigned i = 0; i < max_thread;i++) { \
M_C(name, _lfmp_thread_init)(&mem->thread_data[i]); \
} \
/* Preallocate some group of nodes for the mempool */ \
mem->initial = M_MAX(C_MEMPOOL_MIN_NODE_PER_GROUP, init_node_count); \
M_C(name, _lflist_init)(mem->free, M_C(name, _alloc_node)(init_node_count)); \
M_C(name, _lflist_init)(mem->to_be_reclaimed, M_C(name, _alloc_node)(init_node_count)); \
M_C(name, _lflist_init)(mem->empty, M_C(name, _alloc_node)(0)); \
for(unsigned i = 1; i < init_group_count; i++) { \
M_C(name, _lflist_init)(mem->empty, M_C(name, _alloc_node)(0)); \
for(unsigned i = 1; i < init_group_count; i++) { \
M_C(name, _lflist_push)(mem->free, M_C(name, _alloc_node)(init_node_count), \
gc_mem->thread_data[0].bkoff); \
M_C(name, _lflist_push)(mem->empty, M_C(name, _alloc_node)(0), \
gc_mem->thread_data[0].bkoff); \
} \
/* Register the mempool in the GC */ \
mem->mempool_node.gc_on_sleep = M_C(name, _int_gc_on_sleep); \
mem->mempool_node.next = gc_mem->mempool_list; \
gc_mem->mempool_list = &mem->mempool_node; \
mem->gc_mem = gc_mem; \
} \
\
static inline void \
M_C(name, _clear)(M_C(name, _t) mem) \
{ \
const unsigned max_thread = mem->gc_mem->max_thread; \
for(unsigned i = 0; i < max_thread;i++) { \
M_C(name, _lfmp_thread_clear)(&mem->thread_data[i]); \
} \
M_MEMORY_FREE(mem->thread_data); \
mem->thread_data = NULL; \
M_C(name, _lflist_clear)(mem->empty); \
M_C(name, _lflist_clear)(mem->free); \
assert(M_C(name, _lflist_empty_p)(mem->to_be_reclaimed)); \
M_C(name, _lflist_clear)(mem->to_be_reclaimed); \
/* TODO: Unregister from the GC? */ \
} \
\
static inline type_t * \
M_C(name, _new)(M_C(name, _t) mem, m_gc_tid_t id) \
{ \
M_C(name, _slist_node_ct) *snode; \
M_C(name, _lf_node_t) *node; \
while (true) { \
/* Fast & likely path where we access the thread pool of nodes */ \
if (M_LIKELY(!M_C(name, _slist_empty_p)(mem->thread_data[id].free))) { \
snode = M_C(name, _slist_pop)(mem->thread_data[id].free); \
return &snode->data; \
} \
/* Request a group node to the freelist of groups */ \
gc_mem->thread_data[0].bkoff); \
M_C(name, _lflist_push)(mem->empty, M_C(name, _alloc_node)(0), \
gc_mem->thread_data[0].bkoff); \
} \
/* Register the mempool in the GC */ \
mem->mempool_node.gc_on_sleep = M_C(name, _int_gc_on_sleep); \
mem->mempool_node.next = gc_mem->mempool_list; \
gc_mem->mempool_list = &mem->mempool_node; \
mem->gc_mem = gc_mem; \
} \
\
static inline void \
M_C(name, _clear)(M_C(name, _t) mem) \
{ \
const unsigned max_thread = mem->gc_mem->max_thread; \
for(unsigned i = 0; i < max_thread;i++) { \
M_C(name, _lfmp_thread_clear)(&mem->thread_data[i]); \
} \
M_MEMORY_FREE(mem->thread_data); \
mem->thread_data = NULL; \
M_C(name, _lflist_clear)(mem->empty); \
M_C(name, _lflist_clear)(mem->free); \
assert(M_C(name, _lflist_empty_p)(mem->to_be_reclaimed)); \
M_C(name, _lflist_clear)(mem->to_be_reclaimed); \
/* TODO: Unregister from the GC? */ \
} \
\
static inline type_t * \
M_C(name, _new)(M_C(name, _t) mem, m_gc_tid_t id) \
{ \
M_C(name, _slist_node_ct) *snode; \
M_C(name, _lf_node_t) *node; \
while (true) { \
/* Fast & likely path where we access the thread pool of nodes */ \
if (M_LIKELY(!M_C(name, _slist_empty_p)(mem->thread_data[id].free))) { \
snode = M_C(name, _slist_pop)(mem->thread_data[id].free); \
return &snode->data; \
} \
/* Request a group node to the freelist of groups */ \
node = M_C(name, _lflist_pop)(mem->free, mem->gc_mem->thread_data[id].bkoff); \
if (M_UNLIKELY (node == NULL)) { \
/* Request a new group to the system. Non Lock Free path */ \
assert(mem->initial > 0); \
node = M_C(name, _alloc_node)(mem->initial); \
assert(node != NULL); \
assert(!M_C(name, _slist_empty_p)(node->list)); \
} \
M_C(name, _slist_move)(mem->thread_data[id].free, node->list); \
/* Push back the empty group */ \
assert (M_C(name, _slist_empty_p)(node->list)); \
if (M_UNLIKELY (node == NULL)) { \
/* Request a new group to the system. Non Lock Free path */ \
assert(mem->initial > 0); \
node = M_C(name, _alloc_node)(mem->initial); \
assert(node != NULL); \
assert(!M_C(name, _slist_empty_p)(node->list)); \
} \
M_C(name, _slist_move)(mem->thread_data[id].free, node->list); \
/* Push back the empty group */ \
assert (M_C(name, _slist_empty_p)(node->list)); \
M_C(name, _lflist_push)(mem->empty, node, mem->gc_mem->thread_data[id].bkoff); \
} \
} \
\
static inline void \
M_C(name, _del)(M_C(name, _t) mem, type_t *d, m_gc_tid_t id) \
{ \
M_C(name, _slist_node_ct) *snode; \
assert( d != NULL); \
snode = M_TYPE_FROM_FIELD(M_C(name, _slist_node_ct), d, type_t, data); \
M_C(name, _slist_push)(mem->thread_data[id].to_be_reclaimed, snode); \
} \
} \
} \
\
static inline void \
M_C(name, _del)(M_C(name, _t) mem, type_t *d, m_gc_tid_t id) \
{ \
M_C(name, _slist_node_ct) *snode; \
assert( d != NULL); \
snode = M_TYPE_FROM_FIELD(M_C(name, _slist_node_ct), d, type_t, data); \
M_C(name, _slist_push)(mem->thread_data[id].to_be_reclaimed, snode); \
} \
/***********************************************************************/
+692 -692
View File
File diff suppressed because it is too large. Load diff
+323 -323
View File
File diff suppressed because it is too large. Load diff
+933 -933
View File
File diff suppressed because it is too large. Load diff
+1574 -1574
View File
File diff suppressed because it is too large. Load diff
+180 -180
View File
@@ -32,8 +32,8 @@
* USAGE:
* FUNC_OBJ_ITF_DEF(name, retcode type, type of param1, type of param 2, ...)
*/
#define FUNC_OBJ_ITF_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
#define FUNC_OBJ_ITF_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
M_IF_NARGS_EQ1(__VA_ARGS__)(FUNCOBJI_ITF_NO_PARAM_DEF, FUNCOBJI_ITF_PARAM_DEF)(name, M_C(name, _t), __VA_ARGS__) \
M_END_PROTECTED_CODE
@@ -43,8 +43,8 @@
* USAGE:
* FUNC_OBJ_ITF_DEF_AS(name, name_t, retcode type, type of param1, type of param 2, ...)
*/
#define FUNC_OBJ_ITF_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
#define FUNC_OBJ_ITF_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
M_IF_NARGS_EQ1(__VA_ARGS__)(FUNCOBJI_ITF_NO_PARAM_DEF, FUNCOBJI_ITF_PARAM_DEF)(name, name_t, __VA_ARGS__) \
M_END_PROTECTED_CODE
@@ -67,8 +67,8 @@
* USAGE/EXAMPLE:
* FUNC_OBJ_INS_DEF(name, base_name, (param1, ...), { return param1 * self->member1 }, (member1, int), ...)
*/
#define FUNC_OBJ_INS_DEF(name, base_name, param_list, ...) \
M_BEGIN_PROTECTED_CODE \
#define FUNC_OBJ_INS_DEF(name, base_name, param_list, ...) \
M_BEGIN_PROTECTED_CODE \
M_IF_NARGS_EQ1(__VA_ARGS__)(FUNCOBJI_INS_NO_ATTR_DEF, FUNCOBJI_INS_ATTR_DEF)(name, M_C(name, _t), base_name, param_list, __VA_ARGS__) \
M_END_PROTECTED_CODE
@@ -80,8 +80,8 @@
* USAGE/EXAMPLE:
* FUNC_OBJ_INS_DEF_AS(name, name_t, base_name, (param1, ...), { return param1 * self->member1 }, (member1, int), ...)
*/
#define FUNC_OBJ_INS_DEF_AS(name, name_t, base_name, param_list, ...) \
M_BEGIN_PROTECTED_CODE \
#define FUNC_OBJ_INS_DEF_AS(name, name_t, base_name, param_list, ...) \
M_BEGIN_PROTECTED_CODE \
M_IF_NARGS_EQ1(__VA_ARGS__)(FUNCOBJI_INS_NO_ATTR_DEF, FUNCOBJI_INS_ATTR_DEF)(name, name_t, base_name, param_list, __VA_ARGS__) \
M_END_PROTECTED_CODE
@@ -90,7 +90,7 @@
* USAGE:
* FUNC_OBJ_INS_OPLIST(name, oplist of the attr1, ...)
*/
#define FUNC_OBJ_INS_OPLIST(...) \
#define FUNC_OBJ_INS_OPLIST(...) \
M_IF_NARGS_EQ1(__VA_ARGS__)(FUNCOBJI_INS_NO_ATTR_OPLIST, FUNCOBJI_INS_ATTR_OPLIST_P1)( __VA_ARGS__)
@@ -113,28 +113,28 @@
*/
/* Specialization of the OPLIST in function if there is at least one member or not */
#define FUNCOBJI_INS_NO_ATTR_OPLIST(name) ( \
NAME(name), \
TYPE(M_C(name, _ct)), \
CLEAR(M_C(name, _clear)), \
INIT(M_C(name,_init)) \
#define FUNCOBJI_INS_NO_ATTR_OPLIST(name) ( \
NAME(name), \
TYPE(M_C(name, _ct)), \
CLEAR(M_C(name, _clear)), \
INIT(M_C(name,_init)) \
)
/* Validate the oplist before going further */
#define FUNCOBJI_INS_ATTR_OPLIST_P1(name, ...) \
#define FUNCOBJI_INS_ATTR_OPLIST_P1(name, ...) \
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(FUNCOBJI_INS_ATTR_OPLIST_P3, FUNCOBJI_INS_ATTR_OPLIST_FAILURE)(name, __VA_ARGS__)
/* Prepare a clean compilation failure */
#define FUNCOBJI_INS_ATTR_OPLIST_FAILURE(name, ...) \
#define FUNCOBJI_INS_ATTR_OPLIST_FAILURE(name, ...) \
((M_LIB_ERROR(ONE_ARGUMENT_OF_FUNC_OBJ_INS_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__)))
/* Define the oplist of the instance */
#define FUNCOBJI_INS_ATTR_OPLIST_P3(name, ...) ( \
NAME(name), \
TYPE(M_C(name, _ct)), \
INIT_WITH(M_C(name, _init_with)), \
CLEAR(M_C(name, _clear)), \
M_IF_METHOD_ALL(INIT, __VA_ARGS__)(INIT(M_C(name,_init)),), \
#define FUNCOBJI_INS_ATTR_OPLIST_P3(name, ...) ( \
NAME(name), \
TYPE(M_C(name, _ct)), \
INIT_WITH(M_C(name, _init_with)), \
CLEAR(M_C(name, _clear)), \
M_IF_METHOD_ALL(INIT, __VA_ARGS__)(INIT(M_C(name,_init)),), \
)
@@ -145,28 +145,28 @@
* - M_C(name, _callback_ct): internal type of the callback.
* - M_C(name, _ct): synonym of main type used by oplist.
*/
#define FUNCOBJI_ITF_NO_PARAM_DEF(name, interface_t, retcode) \
\
/* Forward declaration */ \
struct M_C(name, _s); \
\
/* Internal type for instance */ \
typedef retcode M_C(name, _retcode_ct); \
/* No parameters to the callback */ \
typedef retcode(*M_C(name, _callback_ct))(struct M_C(name, _s) *); \
\
typedef struct M_C(name, _s) { \
M_C(name, _callback_ct) callback; \
} interface_t[1]; \
\
/* Internal type for oplist & instance */ \
typedef interface_t M_C(name, _ct); \
\
static inline retcode \
M_C(name, _call)(interface_t funcobj) \
{ \
M_IF(M_KEYWORD_P(void, retcode)) ( /* nothing */,return) \
funcobj->callback(funcobj); \
#define FUNCOBJI_ITF_NO_PARAM_DEF(name, interface_t, retcode) \
\
/* Forward declaration */ \
struct M_C(name, _s); \
\
/* Internal type for instance */ \
typedef retcode M_C(name, _retcode_ct); \
/* No parameters to the callback */ \
typedef retcode(*M_C(name, _callback_ct))(struct M_C(name, _s) *); \
\
typedef struct M_C(name, _s) { \
M_C(name, _callback_ct) callback; \
} interface_t[1]; \
\
/* Internal type for oplist & instance */ \
typedef interface_t M_C(name, _ct); \
\
static inline retcode \
M_C(name, _call)(interface_t funcobj) \
{ \
M_IF(M_KEYWORD_P(void, retcode)) ( /* nothing */,return) \
funcobj->callback(funcobj); \
}
@@ -179,31 +179,31 @@
* - M_C4(name, _param_, num, _ct) for each parameter defined
* - M_C(name, _ct): synonym of main type used by oplist.
*/
#define FUNCOBJI_ITF_PARAM_DEF(name, interface_t, retcode, ...) \
\
/* Forward declaration */ \
struct M_C(name, _s); \
\
/* Internal types for instance */ \
typedef retcode M_C(name, _retcode_ct); \
/* Define types for all parameters */ \
M_MAP3(FUNCOBJI_BASE_TYPE, name, __VA_ARGS__) \
/* Define callback type with all parameters */ \
#define FUNCOBJI_ITF_PARAM_DEF(name, interface_t, retcode, ...) \
\
/* Forward declaration */ \
struct M_C(name, _s); \
\
/* Internal types for instance */ \
typedef retcode M_C(name, _retcode_ct); \
/* Define types for all parameters */ \
M_MAP3(FUNCOBJI_BASE_TYPE, name, __VA_ARGS__) \
/* Define callback type with all parameters */ \
typedef retcode(*M_C(name, _callback_ct))(struct M_C(name, _s) *, __VA_ARGS__); \
\
typedef struct M_C(name, _s) { \
M_C(name, _callback_ct) callback; \
} interface_t[1]; \
\
/* Internal type for oplist & instance */ \
typedef interface_t M_C(name, _ct); \
\
static inline retcode \
M_C(name, _call)(interface_t funcobj \
M_MAP3(FUNCOBJI_BASE_ARGLIST, name, __VA_ARGS__) ) \
{ \
/* If the retcode is 'void', don't return the value of the callback */ \
M_IF(M_KEYWORD_P(void, retcode)) ( /* nothing */,return) \
\
typedef struct M_C(name, _s) { \
M_C(name, _callback_ct) callback; \
} interface_t[1]; \
\
/* Internal type for oplist & instance */ \
typedef interface_t M_C(name, _ct); \
\
static inline retcode \
M_C(name, _call)(interface_t funcobj \
M_MAP3(FUNCOBJI_BASE_ARGLIST, name, __VA_ARGS__) ) \
{ \
/* If the retcode is 'void', don't return the value of the callback */ \
M_IF(M_KEYWORD_P(void, retcode)) ( /* nothing */,return) \
funcobj->callback(funcobj M_MAP3(FUNCOBJI_BASE_ARGCALL, name, __VA_ARGS__) ); \
}
@@ -212,49 +212,49 @@
* with no member attribute.
*/
#define FUNCOBJI_INS_NO_ATTR_DEF(name, instance_t, base_name, param_list, callback_core) \
typedef struct M_C(name, _s) { \
M_C(base_name, _callback_ct) callback; \
} instance_t[1]; \
\
/* Internal type for oplist */ \
typedef instance_t M_C(name, _ct); \
\
static inline M_C(base_name, _retcode_ct) \
M_C(name, _callback)(M_C(base_name, _ct) _self \
M_IF_EMPTY(M_OPFLAT param_list)( \
/* No param */, \
typedef struct M_C(name, _s) { \
M_C(base_name, _callback_ct) callback; \
} instance_t[1]; \
\
/* Internal type for oplist */ \
typedef instance_t M_C(name, _ct); \
\
static inline M_C(base_name, _retcode_ct) \
M_C(name, _callback)(M_C(base_name, _ct) _self \
M_IF_EMPTY(M_OPFLAT param_list)( \
/* No param */, \
M_MAP3(FUNCOBJI_INS_ARGLIST, base_name, M_OPFLAT param_list)\
) \
) \
{ \
struct M_C(name, _s) *self = (struct M_C(name, _s) *)_self; \
(void) self; /* maybe unused */ \
callback_core; \
} \
\
static inline void \
M_C(name, _init_with)(instance_t obj) \
{ \
obj->callback = M_C(name, _callback); \
} \
\
static inline void \
M_C(name, _clear)(instance_t obj) \
{ \
(void) obj; /* nothing to do */ \
} \
\
static inline struct M_C(base_name, _s) * \
M_C(name, _as_interface)(instance_t obj) \
{ \
return (struct M_C(base_name, _s) *) obj; \
} \
\
static inline void \
M_C(name, _init)(instance_t obj) \
{ \
obj->callback = M_C(name, _callback); \
} \
) \
) \
{ \
struct M_C(name, _s) *self = (struct M_C(name, _s) *)_self; \
(void) self; /* maybe unused */ \
callback_core; \
} \
\
static inline void \
M_C(name, _init_with)(instance_t obj) \
{ \
obj->callback = M_C(name, _callback); \
} \
\
static inline void \
M_C(name, _clear)(instance_t obj) \
{ \
(void) obj; /* nothing to do */ \
} \
\
static inline struct M_C(base_name, _s) * \
M_C(name, _as_interface)(instance_t obj) \
{ \
return (struct M_C(base_name, _s) *) obj; \
} \
\
static inline void \
M_C(name, _init)(instance_t obj) \
{ \
obj->callback = M_C(name, _callback); \
} \
/* Specialization of the definition a function object instance of name 'name'
@@ -265,22 +265,22 @@
FUNCOBJI_INS_ATTR_DEF_P2(name, instance_t, base_name, param_list, callback_core, FUNCOBJI_INJECT_GLOBAL(__VA_ARGS__) )
/* Inject the oplist within the list of arguments */
#define FUNCOBJI_INJECT_GLOBAL(...) \
#define FUNCOBJI_INJECT_GLOBAL(...) \
M_MAP_C(FUNCOBJI_INJECT_OPLIST_A, __VA_ARGS__)
/* Transform (x, type) into (x, type, oplist) if there is global registered oplist
or (x, type, M_DEFAULT_OPLIST) if there is no global one,
or keep (x, type, oplist) if oplist was already present */
#define FUNCOBJI_INJECT_OPLIST_A( duo_or_trio ) \
#define FUNCOBJI_INJECT_OPLIST_A( duo_or_trio ) \
FUNCOBJI_INJECT_OPLIST_B duo_or_trio
#define FUNCOBJI_INJECT_OPLIST_B( f, ... ) \
#define FUNCOBJI_INJECT_OPLIST_B( f, ... ) \
M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) )
// Test if all third argument of all arguments is an oplist
#define FUNCOBJI_IF_ALL_OPLIST(...) \
#define FUNCOBJI_IF_ALL_OPLIST(...) \
M_IF(M_REDUCE(FUNCOBJI_IS_OPLIST_P, M_AND, __VA_ARGS__))
// Test if the third argument is an oplist. a is a trio (name, type, oplist)
#define FUNCOBJI_IS_OPLIST_P(a) \
#define FUNCOBJI_IS_OPLIST_P(a) \
M_OPLIST_P(M_RET_ARG3 a)
/* Validate the oplist before going further */
@@ -293,109 +293,109 @@
/* Expand the Function Object with members */
#define FUNCOBJI_INS_ATTR_DEF_P3(name, instance_t, base_name, param_list, callback_core, ...) \
typedef struct M_C(name, _s) { \
/* Callback is the mandatory first argument */ \
M_C(base_name, _callback_ct) callback; \
/* All the member attribute of the Function Object */ \
M_MAP(FUNCOBJI_INS_ATTR_STRUCT, __VA_ARGS__) \
} instance_t[1]; \
\
/* Internal type for oplist */ \
typedef instance_t M_C(name, _ct); \
\
FUNCOBJI_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
\
static inline M_C(base_name, _retcode_ct) \
M_C(name, _callback)(M_C(base_name, _ct) _self \
M_IF_EMPTY(M_OPFLAT param_list)( \
/* No param */, \
typedef struct M_C(name, _s) { \
/* Callback is the mandatory first argument */ \
M_C(base_name, _callback_ct) callback; \
/* All the member attribute of the Function Object */ \
M_MAP(FUNCOBJI_INS_ATTR_STRUCT, __VA_ARGS__) \
} instance_t[1]; \
\
/* Internal type for oplist */ \
typedef instance_t M_C(name, _ct); \
\
FUNCOBJI_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
\
static inline M_C(base_name, _retcode_ct) \
M_C(name, _callback)(M_C(base_name, _ct) _self \
M_IF_EMPTY(M_OPFLAT param_list)( \
/* No param */, \
M_MAP3(FUNCOBJI_INS_ARGLIST, base_name, M_OPFLAT param_list)\
) \
) \
{ \
struct M_C(name, _s) *self = (struct M_C(name, _s) *)_self; \
(void) self; /* maybe unused */ \
callback_core; \
} \
\
static inline void \
) \
) \
{ \
struct M_C(name, _s) *self = (struct M_C(name, _s) *)_self; \
(void) self; /* maybe unused */ \
callback_core; \
} \
\
static inline void \
M_C(name, _init_with)(instance_t obj M_MAP(FUNCOBJI_INS_ATTR_LIST, __VA_ARGS__)) \
{ \
obj->callback = M_C(name, _callback); \
M_MAP(FUNCOBJI_INS_ATTR_INIT_SET, __VA_ARGS__); \
} \
\
static inline void \
M_C(name, _clear)(instance_t obj) \
{ \
M_MAP(FUNCOBJI_INS_ATTR_CLEAR, __VA_ARGS__); \
} \
\
static inline struct M_C(base_name, _s) * \
M_C(name, _as_interface)(instance_t obj) \
{ \
return (struct M_C(base_name, _s) *) obj; \
} \
\
M_IF(FUNCOBJI_TEST_METHOD_P(INIT, __VA_ARGS)) \
( \
static inline void \
M_C(name, _init)(instance_t obj) \
{ \
obj->callback = M_C(name, _callback); \
M_MAP(FUNCOBJI_INS_ATTR_INIT, __VA_ARGS__); \
} \
, /* END OF INIT METHOD */ ) \
{ \
obj->callback = M_C(name, _callback); \
M_MAP(FUNCOBJI_INS_ATTR_INIT_SET, __VA_ARGS__); \
} \
\
static inline void \
M_C(name, _clear)(instance_t obj) \
{ \
M_MAP(FUNCOBJI_INS_ATTR_CLEAR, __VA_ARGS__); \
} \
\
static inline struct M_C(base_name, _s) * \
M_C(name, _as_interface)(instance_t obj) \
{ \
return (struct M_C(base_name, _s) *) obj; \
} \
\
M_IF(FUNCOBJI_TEST_METHOD_P(INIT, __VA_ARGS)) \
( \
static inline void \
M_C(name, _init)(instance_t obj) \
{ \
obj->callback = M_C(name, _callback); \
M_MAP(FUNCOBJI_INS_ATTR_INIT, __VA_ARGS__); \
} \
, /* END OF INIT METHOD */ ) \
/* Define a numbered type of a parameter of the callback*/
#define FUNCOBJI_BASE_TYPE(name, num, type) \
#define FUNCOBJI_BASE_TYPE(name, num, type) \
typedef type M_C4(name, _param_, num, _ct);
/* Define a list of the type of arguments for a function definition */
#define FUNCOBJI_BASE_ARGLIST(name, num, type) \
#define FUNCOBJI_BASE_ARGLIST(name, num, type) \
M_DEFERRED_COMMA type M_C(param_, num)
/* Define a list of arguments for a function call */
#define FUNCOBJI_BASE_ARGCALL(name, num, type) \
#define FUNCOBJI_BASE_ARGCALL(name, num, type) \
M_DEFERRED_COMMA M_C(param_, num)
/* Helper macros */
/* arg = (name, type [, oplist]) */
#define FUNCOBJI_INS_ATTR_STRUCT(arg) \
#define FUNCOBJI_INS_ATTR_STRUCT(arg) \
M_RET_ARG2 arg M_RET_ARG1 arg;
#define FUNCOBJI_INS_ATTR_LIST(arg) \
#define FUNCOBJI_INS_ATTR_LIST(arg) \
M_DEFERRED_COMMA M_RET_ARG2 arg const M_RET_ARG1 arg
#define FUNCOBJI_INS_ATTR_INIT(arg) \
#define FUNCOBJI_INS_ATTR_INIT(arg) \
M_CALL_INIT(M_RET_ARG3 arg, obj -> M_RET_ARG1 arg);
#define FUNCOBJI_INS_ATTR_INIT_SET(arg) \
#define FUNCOBJI_INS_ATTR_INIT_SET(arg) \
M_CALL_INIT_SET(M_RET_ARG3 arg, obj -> M_RET_ARG1 arg, M_RET_ARG1 arg);
#define FUNCOBJI_INS_ATTR_CLEAR(arg) \
#define FUNCOBJI_INS_ATTR_CLEAR(arg) \
M_CALL_CLEAR(M_RET_ARG3 arg, obj -> M_RET_ARG1 arg);
/* Define the list of arguments of the instance of the callback */
#define FUNCOBJI_INS_ARGLIST(name, num, param) \
#define FUNCOBJI_INS_ARGLIST(name, num, param) \
M_DEFERRED_COMMA M_C4(name, _param_, num, _ct) param
/* Macros for testing for a method presence in all the attributes */
#define FUNCOBJI_TEST_METHOD2_P(method, op) \
#define FUNCOBJI_TEST_METHOD2_P(method, op) \
M_TEST_METHOD_P(method, op)
#define FUNCOBJI_TEST_METHOD1_P(method, arg) \
#define FUNCOBJI_TEST_METHOD1_P(method, arg) \
M_APPLY(FUNCOBJI_TEST_METHOD2_P, method, M_RET_ARG3 arg)
#define FUNCOBJI_TEST_METHOD_P(method, ...) \
#define FUNCOBJI_TEST_METHOD_P(method, ...) \
M_IF(M_REDUCE2(FUNCOBJI_TEST_METHOD1_P, M_AND, method, __VA_ARGS__))
/* Macro for checking compatible type and oplist for all the attributes */
#define FUNCOBJI_CONTROL_ALL_OPLIST(name, ...) \
#define FUNCOBJI_CONTROL_ALL_OPLIST(name, ...) \
M_MAP2(FUNCOBJI_CONTROL_OPLIST, name, __VA_ARGS__)
#define FUNCOBJI_CONTROL_OPLIST(name, a) \
#define FUNCOBJI_CONTROL_OPLIST(name, a) \
M_CHECK_COMPATIBLE_OPLIST(name, M_RET_ARG1 a, M_RET_ARG2 a, M_RET_ARG3 a)
+7 -7
View File
@@ -67,11 +67,11 @@ typedef struct genint_s {
#define GENINT_LIMBSIZE ((unsigned)(sizeof(genint_limb_ct) * CHAR_BIT))
// Define the contract of a genint
#define GENINT_CONTRACT(s) do { \
assert (s != NULL); \
assert (s->n > 0 && s->n <= GENINT_MAX_ALLOC); \
assert ((s->max+1) * GENINT_LIMBSIZE >= s->n); \
assert (s->data != NULL); \
#define GENINT_CONTRACT(s) do { \
assert (s != NULL); \
assert (s->n > 0 && s->n <= GENINT_MAX_ALLOC); \
assert ((s->max+1) * GENINT_LIMBSIZE >= s->n); \
assert (s->data != NULL); \
} while (0)
// Define the limb one
@@ -89,12 +89,12 @@ typedef struct genint_s {
#define GENINT_ABA_CPT_T uint32_t
// Set the bit 'i' of the master limb, and increase ABA counter.
#define GENINT_MASTER_SET(master, i) \
#define GENINT_MASTER_SET(master, i) \
((((master)& (~((GENINT_ONE<< GENINT_ABA_CPT)-1))) | (GENINT_ONE << (GENINT_LIMBSIZE - 1 - i))) \
|((GENINT_ABA_CPT_T)((master) + 1)))
// Reset the bit i of the master limb, and increase ABA counter.
#define GENINT_MASTER_RESET(master, i) \
#define GENINT_MASTER_RESET(master, i) \
(((master) & (~((GENINT_ONE<< GENINT_ABA_CPT)-1)) & ~(GENINT_ONE << (GENINT_LIMBSIZE - 1 - i))) \
|((GENINT_ABA_CPT_T)((master) + 1)))
+547 -547
View File
File diff suppressed because it is too large. Load diff
+118 -118
View File
@@ -32,9 +32,9 @@ M_BEGIN_PROTECTED_CODE
/* Define the oplist of a intrusive shared pointer.
USAGE: ISHARED_OPLIST(name [, oplist_of_the_type]) */
#define ISHARED_PTR_OPLIST(...) \
ISHAREDI_PTR_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST), \
#define ISHARED_PTR_OPLIST(...) \
ISHAREDI_PTR_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST), \
(__VA_ARGS__ )))
@@ -42,15 +42,15 @@ M_BEGIN_PROTECTED_CODE
name: name of the intrusive shared pointer.
type: name of the type of the structure (aka. struct test_s) - not used currently.
NOTE: There can be only one interface of this kind in a type! */
#define ISHARED_PTR_INTERFACE(name, type) \
#define ISHARED_PTR_INTERFACE(name, type) \
atomic_int M_C(name, _cpt)
/* Define the intrusive shared pointer type and its static inline functions.
USAGE: ISHARED_PTR_DEF(name, type, [, oplist]) */
#define ISHARED_PTR_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define ISHARED_PTR_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t) ), \
(name, __VA_ARGS__ , M_C(name, _t) ))) \
M_END_PROTECTED_CODE
@@ -59,9 +59,9 @@ M_BEGIN_PROTECTED_CODE
/* Define the intrusive shared pointer type and its static inline functions
as the name name_t
USAGE: ISHARED_PTR_DEF_AS(name, name_t, type, [, oplist]) */
#define ISHARED_PTR_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define ISHARED_PTR_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t ), \
(name, __VA_ARGS__ , name_t ))) \
M_END_PROTECTED_CODE
@@ -73,131 +73,131 @@ M_BEGIN_PROTECTED_CODE
#define ISHAREDI_PTR_OPLIST_P1(arg) ISHAREDI_PTR_OPLIST_P2 arg
/* Validation of the given oplist */
#define ISHAREDI_PTR_OPLIST_P2(name, oplist) \
#define ISHAREDI_PTR_OPLIST_P2(name, oplist) \
M_IF_OPLIST(oplist)(ISHAREDI_PTR_OPLIST_P3, ISHAREDI_PTR_OPLIST_FAILURE)(name, oplist)
/* Prepare a clean compilation failure */
#define ISHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
#define ISHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
((M_LIB_ERROR(ARGUMENT_OF_ISHARED_PTR_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
// Define the oplist
#define ISHAREDI_PTR_OPLIST_P3(name, oplist) ( \
INIT(M_INIT_DEFAULT), \
INIT_SET(API_4(M_C(name, _init_set))), \
SET(M_C(name, _set) M_IPTR), \
CLEAR(M_C(name, _clear)), \
CLEAN(M_C(name, _clean) M_IPTR), \
TYPE(M_C(name, _ct)), \
OPLIST(oplist), \
SUBTYPE(M_C(name, _subtype_ct)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
#define ISHAREDI_PTR_OPLIST_P3(name, oplist) ( \
INIT(M_INIT_DEFAULT), \
INIT_SET(API_4(M_C(name, _init_set))), \
SET(M_C(name, _set) M_IPTR), \
CLEAR(M_C(name, _clear)), \
CLEAN(M_C(name, _clean) M_IPTR), \
TYPE(M_C(name, _ct)), \
OPLIST(oplist), \
SUBTYPE(M_C(name, _subtype_ct)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
// Deferred evaluatioin
#define ISHAREDI_PTR_DEF_P1(arg) ISHAREDI_PTR_DEF_P2 arg
/* Validate the oplist before going further */
#define ISHAREDI_PTR_DEF_P2(name, type, oplist, shared_t) \
#define ISHAREDI_PTR_DEF_P2(name, type, oplist, shared_t) \
M_IF_OPLIST(oplist)(ISHAREDI_PTR_DEF_P3, ISHAREDI_PTR_DEF_FAILURE)(name, type, oplist, shared_t)
/* Stop processing with a compilation failure */
#define ISHAREDI_PTR_DEF_FAILURE(name, type, oplist, shared_t) \
#define ISHAREDI_PTR_DEF_FAILURE(name, type, oplist, shared_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(ISHARED_PTR_DEF): the given argument is not a valid oplist: " #oplist)
#define ISHAREDI_PTR_DEF_P3(name, type, oplist, shared_t) \
\
/* The shared pointer is only a pointer to the type */ \
typedef type *shared_t; \
\
/* Define internal types for oplist */ \
typedef shared_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline shared_t \
M_C(name, _init)(type *ptr) \
{ \
/* Initialize the type referenced by the pointer */ \
if (M_LIKELY (ptr != NULL)) { \
atomic_init(&ptr->M_C(name, _cpt), 1); \
} \
return ptr; \
} \
\
static inline shared_t \
M_C(name, _init_set)(shared_t shared) \
{ \
if (M_LIKELY (shared != NULL)) { \
int n = atomic_fetch_add(&(shared->M_C(name, _cpt)), 1); \
(void) n; \
} \
return shared; \
} \
\
static inline void M_ATTR_DEPRECATED \
M_C(name, _init_set2)(shared_t *ptr, shared_t shared) \
{ \
assert (ptr != NULL); \
*ptr = M_C(name, _init_set)(shared); \
} \
\
M_IF_DISABLED_METHOD(NEW, oplist) \
( /* Nothing to do */, M_IF_METHOD(INIT, oplist) \
( \
static inline shared_t \
M_C(name, _init_new)(void) \
{ \
type *ptr = M_CALL_NEW(oplist, type); \
if (ptr == NULL) { \
M_MEMORY_FULL(sizeof(type)); \
return NULL; \
} \
M_CALL_INIT(oplist, *ptr); \
atomic_init (&ptr->M_C(name, _cpt), 1); \
return ptr; \
} \
, /* End of INIT */) \
/* End of NEW */) \
\
static inline void \
M_C(name, _clear)(shared_t shared) \
{ \
if (shared != NULL) { \
if (atomic_fetch_sub(&(shared->M_C(name, _cpt)), 1) == 1) { \
M_CALL_CLEAR(oplist, *shared); \
M_IF_DISABLED_METHOD(DEL, oplist)(, M_CALL_DEL(oplist, shared);) \
} \
} \
} \
\
static inline void \
M_C(name, _clear_ptr)(shared_t *shared) \
{ \
assert(shared != NULL); \
M_C(name, _clear)(*shared); \
*shared = NULL; \
} \
\
static inline void \
M_C(name, _clean)(shared_t *shared) \
{ \
M_C(name, _clear)(*shared); \
*shared = NULL; \
} \
\
static inline void \
M_C(name, _set)(shared_t *ptr, shared_t shared) \
{ \
assert (ptr != NULL); \
if (M_LIKELY (*ptr != shared)) { \
M_C(name, _clear)(*ptr); \
*ptr = M_C(name, _init_set)(shared); \
} \
} \
\
#define ISHAREDI_PTR_DEF_P3(name, type, oplist, shared_t) \
\
/* The shared pointer is only a pointer to the type */ \
typedef type *shared_t; \
\
/* Define internal types for oplist */ \
typedef shared_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline shared_t \
M_C(name, _init)(type *ptr) \
{ \
/* Initialize the type referenced by the pointer */ \
if (M_LIKELY (ptr != NULL)) { \
atomic_init(&ptr->M_C(name, _cpt), 1); \
} \
return ptr; \
} \
\
static inline shared_t \
M_C(name, _init_set)(shared_t shared) \
{ \
if (M_LIKELY (shared != NULL)) { \
int n = atomic_fetch_add(&(shared->M_C(name, _cpt)), 1); \
(void) n; \
} \
return shared; \
} \
\
static inline void M_ATTR_DEPRECATED \
M_C(name, _init_set2)(shared_t *ptr, shared_t shared) \
{ \
assert (ptr != NULL); \
*ptr = M_C(name, _init_set)(shared); \
} \
\
M_IF_DISABLED_METHOD(NEW, oplist) \
( /* Nothing to do */, M_IF_METHOD(INIT, oplist) \
( \
static inline shared_t \
M_C(name, _init_new)(void) \
{ \
type *ptr = M_CALL_NEW(oplist, type); \
if (ptr == NULL) { \
M_MEMORY_FULL(sizeof(type)); \
return NULL; \
} \
M_CALL_INIT(oplist, *ptr); \
atomic_init (&ptr->M_C(name, _cpt), 1); \
return ptr; \
} \
, /* End of INIT */) \
/* End of NEW */) \
\
static inline void \
M_C(name, _clear)(shared_t shared) \
{ \
if (shared != NULL) { \
if (atomic_fetch_sub(&(shared->M_C(name, _cpt)), 1) == 1) { \
M_CALL_CLEAR(oplist, *shared); \
M_IF_DISABLED_METHOD(DEL, oplist)(, M_CALL_DEL(oplist, shared);) \
} \
} \
} \
\
static inline void \
M_C(name, _clear_ptr)(shared_t *shared) \
{ \
assert(shared != NULL); \
M_C(name, _clear)(*shared); \
*shared = NULL; \
} \
\
static inline void \
M_C(name, _clean)(shared_t *shared) \
{ \
M_C(name, _clear)(*shared); \
*shared = NULL; \
} \
\
static inline void \
M_C(name, _set)(shared_t *ptr, shared_t shared) \
{ \
assert (ptr != NULL); \
if (M_LIKELY (*ptr != shared)) { \
M_C(name, _clear)(*ptr); \
*ptr = M_C(name, _init_set)(shared); \
} \
} \
\
M_END_PROTECTED_CODE
+1275 -1275
View File
File diff suppressed because it is too large. Load diff
+112 -112
View File
@@ -39,9 +39,9 @@
mempool_uint_clear(m); // Give back memory to system
NOTE: Can not use m-list since it may be expanded from LIST_DEF
*/
#define MEMPOOL_DEF(name, type) \
M_BEGIN_PROTECTED_CODE \
MEMPOOL_DEF_P2(name, type, M_C(name, _t) ) \
#define MEMPOOL_DEF(name, type) \
M_BEGIN_PROTECTED_CODE \
MEMPOOL_DEF_P2(name, type, M_C(name, _t) ) \
M_END_PROTECTED_CODE
@@ -49,9 +49,9 @@
USAGE:
MEMPOOL_DEF_AS(memppol_uint, name_t, unsigned int)
*/
#define MEMPOOL_DEF_AS(name, name_t, type) \
M_BEGIN_PROTECTED_CODE \
MEMPOOL_DEF_P2(name, type, name_t ) \
#define MEMPOOL_DEF_AS(name, name_t, type) \
M_BEGIN_PROTECTED_CODE \
MEMPOOL_DEF_P2(name, type, name_t ) \
M_END_PROTECTED_CODE
@@ -60,121 +60,121 @@
The default is the number of elements that fits in 16KB.
*/
#ifndef MEMPOOL_MAX_PER_SEGMENT
#define MEMPOOL_MAX_PER_SEGMENT(type) \
#define MEMPOOL_MAX_PER_SEGMENT(type) \
M_MAX((16*1024-sizeof(unsigned int) - 2*sizeof(void*)) / sizeof (type), 256U)
#endif
/********************************** INTERNAL ************************************/
#define MEMPOOL_DEF_P2(name, type, name_t) \
\
/* Define the type of element in a segment of the mempool. \
Either it is the basic type or a pointer to another one. */ \
typedef union M_C(name,_union_s) { \
type t; \
union M_C(name,_union_s) *next; \
} M_C(name,_union_ct); \
\
/* Define a segment of a mempool. \
It is an array of basic type, each segment is in a linked list */ \
typedef struct M_C(name,_segment_s) { \
unsigned int count; \
struct M_C(name,_segment_s) *next; \
M_C(name,_union_ct) tab[MEMPOOL_MAX_PER_SEGMENT(type)]; \
} M_C(name,_segment_ct); \
\
/* Define a mempool. \
It is a pointer to the first free object within the segments \
and the segments themselves */ \
typedef struct M_C(name, _s) { \
M_C(name,_union_ct) *free_list; \
M_C(name,_segment_ct) *current_segment; \
} name_t[1]; \
\
static inline void \
M_C(name,_init)(name_t mem) \
{ \
mem->free_list = NULL; \
mem->current_segment = M_MEMORY_ALLOC(M_C(name,_segment_ct)); \
if (mem->current_segment == NULL) { \
M_MEMORY_FULL(sizeof (M_C(name,_segment_ct))); \
return; \
} \
mem->current_segment->next = NULL; \
mem->current_segment->count = 0; \
MEMPOOLI_CONTRACT(mem, type); \
} \
\
static inline void \
M_C(name,_clear)(name_t mem) \
{ \
MEMPOOLI_CONTRACT(mem, type); \
M_C(name,_segment_ct) *segment = mem->current_segment; \
while (segment != NULL) { \
M_C(name,_segment_ct) *next = segment->next; \
M_MEMORY_DEL (segment); \
segment = next; \
} \
/* Clean pointers to be safer */ \
mem->free_list = NULL; \
mem->current_segment = NULL; \
} \
\
static inline type * \
M_C(name,_alloc)(name_t mem) \
{ \
MEMPOOLI_CONTRACT(mem, type); \
/* Test if one object is in the free list */ \
M_C(name,_union_ct) *ret = mem->free_list; \
if (ret != NULL) { \
/* Yes, so return it, and pop it from the free list */ \
mem->free_list = ret->next; \
return &ret->t; \
} \
/* No cheap free object exist. Test within a segment */ \
M_C(name,_segment_ct) *segment = mem->current_segment; \
assert(segment != NULL); \
unsigned int count = segment->count; \
/* If segment is full, allocate a new one from the system */ \
if (M_UNLIKELY (count >= MEMPOOL_MAX_PER_SEGMENT(type))) { \
#define MEMPOOL_DEF_P2(name, type, name_t) \
\
/* Define the type of element in a segment of the mempool. \
Either it is the basic type or a pointer to another one. */ \
typedef union M_C(name,_union_s) { \
type t; \
union M_C(name,_union_s) *next; \
} M_C(name,_union_ct); \
\
/* Define a segment of a mempool. \
It is an array of basic type, each segment is in a linked list */ \
typedef struct M_C(name,_segment_s) { \
unsigned int count; \
struct M_C(name,_segment_s) *next; \
M_C(name,_union_ct) tab[MEMPOOL_MAX_PER_SEGMENT(type)]; \
} M_C(name,_segment_ct); \
\
/* Define a mempool. \
It is a pointer to the first free object within the segments \
and the segments themselves */ \
typedef struct M_C(name, _s) { \
M_C(name,_union_ct) *free_list; \
M_C(name,_segment_ct) *current_segment; \
} name_t[1]; \
\
static inline void \
M_C(name,_init)(name_t mem) \
{ \
mem->free_list = NULL; \
mem->current_segment = M_MEMORY_ALLOC(M_C(name,_segment_ct)); \
if (mem->current_segment == NULL) { \
M_MEMORY_FULL(sizeof (M_C(name,_segment_ct))); \
return; \
} \
mem->current_segment->next = NULL; \
mem->current_segment->count = 0; \
MEMPOOLI_CONTRACT(mem, type); \
} \
\
static inline void \
M_C(name,_clear)(name_t mem) \
{ \
MEMPOOLI_CONTRACT(mem, type); \
M_C(name,_segment_ct) *segment = mem->current_segment; \
while (segment != NULL) { \
M_C(name,_segment_ct) *next = segment->next; \
M_MEMORY_DEL (segment); \
segment = next; \
} \
/* Clean pointers to be safer */ \
mem->free_list = NULL; \
mem->current_segment = NULL; \
} \
\
static inline type * \
M_C(name,_alloc)(name_t mem) \
{ \
MEMPOOLI_CONTRACT(mem, type); \
/* Test if one object is in the free list */ \
M_C(name,_union_ct) *ret = mem->free_list; \
if (ret != NULL) { \
/* Yes, so return it, and pop it from the free list */ \
mem->free_list = ret->next; \
return &ret->t; \
} \
/* No cheap free object exist. Test within a segment */ \
M_C(name,_segment_ct) *segment = mem->current_segment; \
assert(segment != NULL); \
unsigned int count = segment->count; \
/* If segment is full, allocate a new one from the system */ \
if (M_UNLIKELY (count >= MEMPOOL_MAX_PER_SEGMENT(type))) { \
M_C(name,_segment_ct) *new_segment = M_MEMORY_ALLOC (M_C(name,_segment_ct)); \
if (M_UNLIKELY (new_segment == NULL)) { \
M_MEMORY_FULL(sizeof (M_C(name,_segment_ct))); \
return NULL; \
} \
new_segment->next = segment; \
new_segment->count = 0; \
mem->current_segment = new_segment; \
segment = new_segment; \
count = 0; \
} \
/* Return the object as the last element of the current segment */ \
ret = &segment->tab[count]; \
segment->count = count + 1; \
MEMPOOLI_CONTRACT(mem, type); \
return &ret->t; \
} \
\
static inline void \
M_C(name,_free)(name_t mem, type *ptr) \
{ \
MEMPOOLI_CONTRACT(mem, type); \
/* NOTE: Unsafe cast: suppose that the given pointer \
was allocated by the previous alloc function. */ \
M_C(name,_union_ct) *ret = (M_C(name,_union_ct) *)(uintptr_t)ptr; \
/* Add the object back in the free list */ \
ret->next = mem->free_list; \
mem->free_list = ret; \
/* NOTE: the objects are NOT given back to the system until the mempool \
is fully cleared */ \
MEMPOOLI_CONTRACT(mem, type); \
} \
if (M_UNLIKELY (new_segment == NULL)) { \
M_MEMORY_FULL(sizeof (M_C(name,_segment_ct))); \
return NULL; \
} \
new_segment->next = segment; \
new_segment->count = 0; \
mem->current_segment = new_segment; \
segment = new_segment; \
count = 0; \
} \
/* Return the object as the last element of the current segment */ \
ret = &segment->tab[count]; \
segment->count = count + 1; \
MEMPOOLI_CONTRACT(mem, type); \
return &ret->t; \
} \
\
static inline void \
M_C(name,_free)(name_t mem, type *ptr) \
{ \
MEMPOOLI_CONTRACT(mem, type); \
/* NOTE: Unsafe cast: suppose that the given pointer \
was allocated by the previous alloc function. */ \
M_C(name,_union_ct) *ret = (M_C(name,_union_ct) *)(uintptr_t)ptr; \
/* Add the object back in the free list */ \
ret->next = mem->free_list; \
mem->free_list = ret; \
/* NOTE: the objects are NOT given back to the system until the mempool \
is fully cleared */ \
MEMPOOLI_CONTRACT(mem, type); \
} \
/* MEMPOOL contract */
#define MEMPOOLI_CONTRACT(mempool, type) do { \
assert((mempool) != NULL); \
assert((mempool)->current_segment != NULL); \
#define MEMPOOLI_CONTRACT(mempool, type) do { \
assert((mempool) != NULL); \
assert((mempool)->current_segment != NULL); \
assert((mempool)->current_segment->count <= MEMPOOL_MAX_PER_SEGMENT(type)); \
} while (0)
+13 -13
View File
@@ -27,7 +27,7 @@
/* Auto-detect the thread backend to use if the user has not override it */
#ifndef M_USE_THREAD_BACKEND
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
&& !defined(__STDC_NO_THREADS__)
# define M_USE_THREAD_BACKEND 1
# elif defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
@@ -503,25 +503,25 @@ M_END_PROTECTED_CODE
or using C11's ONCE mechanism */
#ifdef M_MUTEXI_INIT_VALUE
# define M_LOCK_DECL(name) m_mutex_t name = M_MUTEXI_INIT_VALUE
# define M_LOCK(name) \
# define M_LOCK(name) \
M_LOCKI_DO(name, M_C(local_cont_, __LINE__), m_mutexi_lazy_lock, m_mutex_unlock)
#else
# define M_LOCK_DECL(name) \
m_mutex_t name; \
static void M_C(m_mutex_init_, name)(void) { \
m_mutex_init(name); \
} \
# define M_LOCK_DECL(name) \
m_mutex_t name; \
static void M_C(m_mutex_init_, name)(void) { \
m_mutex_init(name); \
} \
m_once_ct M_C(m_once_, name) = M_ONCEI_INIT_VALUE
# define M_LOCKI_BY_ONCE(name) \
(m_oncei_call(M_C(m_once_, name), M_C(m_mutex_init_, name)), \
# define M_LOCKI_BY_ONCE(name) \
(m_oncei_call(M_C(m_once_, name), M_C(m_mutex_init_, name)), \
m_mutex_lock(name), (void) 0 )
# define M_LOCK(name) \
# define M_LOCK(name) \
M_LOCKI_DO(name, M_C(local_cont_, __LINE__), M_LOCKI_BY_ONCE, m_mutex_unlock)
#endif
#define M_LOCKI_DO(name, cont, lock_func, unlock_func) \
for(bool cont = true \
; cont && (lock_func (name), true); \
#define M_LOCKI_DO(name, cont, lock_func, unlock_func) \
for(bool cont = true \
; cont && (lock_func (name), true); \
(unlock_func (name), cont = false))
#endif
+330 -330
View File
@@ -32,9 +32,9 @@
/* Define a prioqueue of a given type and its associated functions.
USAGE: PRIOQUEUE_DEF(name, type [, oplist_of_the_type]) */
#define PRIOQUEUE_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
PRIOQUEUEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define PRIOQUEUE_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
PRIOQUEUEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name,_it_t) ), \
(name, __VA_ARGS__, M_C(name,_t), M_C(name,_it_t)))) \
M_END_PROTECTED_CODE
@@ -43,9 +43,9 @@
/* Define a prioqueue of a given type and its associated functions.
as the name name_t with an iterator named it_t
USAGE: PRIOQUEUE_DEF_AS(name, name_t, it_t, type [, oplist_of_the_type]) */
#define PRIOQUEUE_DEF_AS(name, name_t, it_t, ...) \
M_BEGIN_PROTECTED_CODE \
PRIOQUEUEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define PRIOQUEUE_DEF_AS(name, name_t, it_t, ...) \
M_BEGIN_PROTECTED_CODE \
PRIOQUEUEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t, it_t ), \
(name, __VA_ARGS__, name_t, it_t ))) \
M_END_PROTECTED_CODE
@@ -53,9 +53,9 @@
/* Define the oplist of a prioqueue of type.
USAGE: PRIOQUEUE_OPLIST(name[, oplist of the type]) */
#define PRIOQUEUE_OPLIST(...) \
PRIOQUEUEI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST), \
#define PRIOQUEUE_OPLIST(...) \
PRIOQUEUEI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST), \
(__VA_ARGS__ )))
@@ -67,40 +67,40 @@
#define PRIOQUEUEI_OPLIST_P1(arg) PRIOQUEUEI_OPLIST_P2 arg
/* Validation of the given oplist */
#define PRIOQUEUEI_OPLIST_P2(name, oplist) \
#define PRIOQUEUEI_OPLIST_P2(name, oplist) \
M_IF_OPLIST(oplist)(PRIOQUEUEI_OPLIST_P3, PRIOQUEUEI_OPLIST_FAILURE)(name, oplist)
/* Prepare a clean compilation failure */
#define PRIOQUEUEI_OPLIST_FAILURE(name, oplist) \
#define PRIOQUEUEI_OPLIST_FAILURE(name, oplist) \
((M_LIB_ERROR(ARGUMENT_OF_PRIOQUEUE_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
/* Define oplist of a priority queue */
#define PRIOQUEUEI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _init)) \
,INIT_SET(M_C(name, _init_set)) \
,INIT_WITH(API_1(M_INIT_VAI)) \
,SET(M_C(name, _set)) \
,CLEAR(M_C(name, _clear)) \
,INIT_MOVE(M_C(name, _init_move)) \
,MOVE(M_C(name, _move)) \
,SWAP(M_C(name, _swap)) \
,TYPE(M_C(name,_ct)) \
,SUBTYPE(M_C(name, _subtype_ct)) \
,CLEAN(M_C(name,_clean)) \
,PUSH(M_C(name,_push)) \
,POP(M_C(name,_pop)) \
,OPLIST(oplist) \
,TEST_EMPTY(M_C(name, _empty_p)), \
,GET_SIZE(M_C(name, _size)) \
,IT_TYPE(M_C(name, _it_ct)), \
IT_FIRST(M_C(name,_it)), \
IT_END(M_C(name,_it_end)), \
IT_SET(M_C(name,_it_set)), \
IT_END_P(M_C(name,_end_p)), \
IT_EQUAL_P(M_C(name,_it_equal_p)), \
IT_LAST_P(M_C(name,_last_p)), \
IT_NEXT(M_C(name,_next)), \
IT_CREF(M_C(name,_cref)), \
#define PRIOQUEUEI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _init)) \
,INIT_SET(M_C(name, _init_set)) \
,INIT_WITH(API_1(M_INIT_VAI)) \
,SET(M_C(name, _set)) \
,CLEAR(M_C(name, _clear)) \
,INIT_MOVE(M_C(name, _init_move)) \
,MOVE(M_C(name, _move)) \
,SWAP(M_C(name, _swap)) \
,TYPE(M_C(name,_ct)) \
,SUBTYPE(M_C(name, _subtype_ct)) \
,CLEAN(M_C(name,_clean)) \
,PUSH(M_C(name,_push)) \
,POP(M_C(name,_pop)) \
,OPLIST(oplist) \
,TEST_EMPTY(M_C(name, _empty_p)), \
,GET_SIZE(M_C(name, _size)) \
,IT_TYPE(M_C(name, _it_ct)), \
IT_FIRST(M_C(name,_it)), \
IT_END(M_C(name,_it_end)), \
IT_SET(M_C(name,_it_set)), \
IT_END_P(M_C(name,_end_p)), \
IT_EQUAL_P(M_C(name,_it_equal_p)), \
IT_LAST_P(M_C(name,_last_p)), \
IT_NEXT(M_C(name,_next)), \
IT_CREF(M_C(name,_cref)), \
)
@@ -109,11 +109,11 @@
#define PRIOQUEUEI_DEF_P1(arg) PRIOQUEUEI_DEF_P2 arg
/* Validate the oplist before going further */
#define PRIOQUEUEI_DEF_P2(name, type, oplist, prioqueue_t, it_t) \
#define PRIOQUEUEI_DEF_P2(name, type, oplist, prioqueue_t, it_t) \
M_IF_OPLIST(oplist)(PRIOQUEUEI_DEF_P3, PRIOQUEUEI_DEF_FAILURE)(name, type, oplist, prioqueue_t, it_t)
/* Stop processing with a compilation failure */
#define PRIOQUEUEI_DEF_FAILURE(name, type, oplist, prioqueue_t, it_t) \
#define PRIOQUEUEI_DEF_FAILURE(name, type, oplist, prioqueue_t, it_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(PRIOQUEUE_DEF): the given argument is not a valid oplist: " #oplist)
/* Define the priority queue:
@@ -123,299 +123,299 @@
- prioqueue_t: type of the container,
- it_t: iterator of the container
*/
#define PRIOQUEUEI_DEF_P3(name, type, oplist, prioqueue_t, it_t) \
\
#define PRIOQUEUEI_DEF_P3(name, type, oplist, prioqueue_t, it_t) \
\
/* Definition of the internal array used to construct the priority queue */ \
ARRAY_DEF(M_C(name, _array), type, oplist) \
\
/* Define the priority queue over the defined array */ \
typedef struct M_C(name, _s) { \
M_C(name, _array_t) array; \
} prioqueue_t[1]; \
/* Define the pointer references to the priority queue */ \
typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
\
/* The iterator is the same one as the one of the internal array */ \
typedef M_C(name, _array_it_t) it_t; \
\
/* Definition of the internal types used by the oplist */ \
typedef prioqueue_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
typedef it_t M_C(name, _it_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(prioqueue_t p) \
{ \
M_C(name, _array_init)(p->array); \
} \
\
static inline void \
M_C(name, _init_set)(prioqueue_t p, prioqueue_t const o) \
{ \
M_C(name, _array_init_set)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _set)(prioqueue_t p, prioqueue_t const o) \
{ \
M_C(name, _array_set)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _clear)(prioqueue_t p) \
{ \
M_C(name, _array_clear)(p->array); \
} \
\
static inline void \
M_C(name, _init_move)(prioqueue_t p, prioqueue_t o) \
{ \
M_C(name, _array_init_move)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _move)(prioqueue_t p, prioqueue_t o) \
{ \
M_C(name, _array_move)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _swap)(prioqueue_t p, prioqueue_t o) \
{ \
M_C(name, _array_swap)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _clean)(prioqueue_t p) \
{ \
M_C(name, _array_clean)(p->array); \
} \
\
static inline size_t \
M_C(name, _i_parent)(size_t i) \
{ \
assert (i > 0); \
return (i - 1) / 2; \
} \
\
static inline size_t \
M_C(name, _i_lchild)(size_t i) \
{ \
assert(i <= ((SIZE_MAX)-2)/2); \
return 2*i + 1; \
} \
\
static inline size_t \
M_C(name, _i_rchild)(size_t i) \
{ \
assert(i <= ((SIZE_MAX)-2)/2); \
return 2*i + 2; \
} \
\
static inline int \
M_C(name, _i_cmp)(const prioqueue_t p, size_t i, size_t j) \
{ \
return M_CALL_CMP(oplist, *M_C(name, _array_cget)(p->array, i), \
*M_C(name, _array_cget)(p->array, j)); \
} \
\
static inline bool \
M_C(name, _empty_p)(prioqueue_t const p) \
{ \
return M_C(name, _array_empty_p)(p->array); \
} \
\
static inline size_t \
M_C(name, _size)(prioqueue_t const p) \
{ \
return M_C(name, _array_size)(p->array); \
} \
\
static inline void \
M_C(name, _push)(prioqueue_t p, type const x) \
{ \
/* Push back the new element at the end of the array */ \
M_C(name, _array_push_back)(p->array, x); \
\
/* Reorder the array by swapping with its parent \
* until it reaches the right position */ \
size_t i = M_C(name, _array_size)(p->array)-1; \
while (i > 0) { \
size_t j = M_C(name, _i_parent)(i); \
if (M_C(name, _i_cmp)(p, j, i) <= 0) \
break; \
M_C(name, _array_swap_at) (p->array, i, j); \
i = j; \
} \
} \
\
static inline type const * \
M_C(name, _front)(prioqueue_t const p) \
{ \
return M_C(name, _array_cget)(p->array, 0); \
} \
\
static inline void \
M_C(name, _pop)(type *x, prioqueue_t p) \
{ \
/* Swap the front element with the last element */ \
size_t size = M_C(name, _array_size)(p->array)-1; \
M_C(name, _array_swap_at) (p->array, 0, size); \
/* Swap the new last element */ \
M_C(name, _array_pop_back)(x, p->array); \
\
/* Reorder the heap */ \
size_t i = 0; \
while (true) { \
size_t child = M_C(name, _i_lchild)(i); \
if (child >= size) \
break; \
size_t otherChild = M_C(name, _i_rchild)(i); \
if (otherChild < size \
&& M_C(name, _i_cmp)(p, otherChild, child) < 0 ) { \
child = otherChild; \
} \
if (M_C(name, _i_cmp)(p, i, child) <= 0) \
break; \
M_C(name, _array_swap_at) (p->array, i, child); \
i = child; \
} \
} \
\
/* Define iterators over the array iterator */ \
static inline void \
M_C(name, _it)(it_t it, prioqueue_t const v) \
{ \
M_C(name, _array_it)(it, v->array); \
} \
\
static inline void \
M_C(name, _it_last)(it_t it, prioqueue_t const v) \
{ \
M_C(name, _array_it_last)(it, v->array); \
} \
\
static inline void \
M_C(name, _it_end)(it_t it, prioqueue_t const v) \
{ \
M_C(name, _array_it_end)(it, v->array); \
} \
\
static inline void \
M_C(name, _it_set)(it_t it, const it_t org) \
{ \
M_C(name, _array_it_set)(it, org); \
} \
\
static inline bool \
M_C(name, _end_p)(const it_t it) \
{ \
return M_C(name, _array_end_p)(it); \
} \
\
static inline bool \
M_C(name, _last_p)(const it_t it) \
{ \
return M_C(name, _array_last_p)(it); \
} \
\
static inline bool \
M_C(name, _it_equal_p)(const it_t it1, \
const it_t it2) \
{ \
return M_C(name, _array_it_equal_p)(it1, it2); \
} \
\
static inline void \
M_C(name, _next)(it_t it) \
{ \
M_C(name, _array_next)(it); \
} \
\
static inline void \
M_C(name, _previous)(it_t it) \
{ \
M_C(name, _array_previous)(it); \
} \
\
static inline type const * \
M_C(name, _cref)(const it_t it) \
{ \
return M_C(name, _array_cref)(it); \
} \
\
M_IF_METHOD(EQUAL, oplist) \
( \
/* EQUAL & CMP may be uncorrelated */ \
static inline bool \
M_C(name, _erase)(prioqueue_t p, type x) \
{ \
/* First pass: search for an item EQUAL to x */ \
/* NOTE: An HASHMAP may be a good idea to optimize this pass. */ \
size_t size = M_C(name, _array_size)(p->array); \
size_t i = 0; \
for(i = 0; i < size; i++) { \
if (M_CALL_EQUAL(oplist, *M_C(name, _array_cget)(p->array, i), x)) \
break; \
} \
/* If x is not found, then stop */ \
if (i >= size) \
return false; \
/* Swap the found item and the last element */ \
size--; \
M_C(name, _array_swap_at) (p->array, i, size); \
M_C(name, _array_pop_back)(NULL, p->array); \
ARRAY_DEF(M_C(name, _array), type, oplist) \
\
/* Define the priority queue over the defined array */ \
typedef struct M_C(name, _s) { \
M_C(name, _array_t) array; \
} prioqueue_t[1]; \
/* Define the pointer references to the priority queue */ \
typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
\
/* The iterator is the same one as the one of the internal array */ \
typedef M_C(name, _array_it_t) it_t; \
\
/* Definition of the internal types used by the oplist */ \
typedef prioqueue_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
typedef it_t M_C(name, _it_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(prioqueue_t p) \
{ \
M_C(name, _array_init)(p->array); \
} \
\
static inline void \
M_C(name, _init_set)(prioqueue_t p, prioqueue_t const o) \
{ \
M_C(name, _array_init_set)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _set)(prioqueue_t p, prioqueue_t const o) \
{ \
M_C(name, _array_set)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _clear)(prioqueue_t p) \
{ \
M_C(name, _array_clear)(p->array); \
} \
\
static inline void \
M_C(name, _init_move)(prioqueue_t p, prioqueue_t o) \
{ \
M_C(name, _array_init_move)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _move)(prioqueue_t p, prioqueue_t o) \
{ \
M_C(name, _array_move)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _swap)(prioqueue_t p, prioqueue_t o) \
{ \
M_C(name, _array_swap)(p->array, o->array); \
} \
\
static inline void \
M_C(name, _clean)(prioqueue_t p) \
{ \
M_C(name, _array_clean)(p->array); \
} \
\
static inline size_t \
M_C(name, _i_parent)(size_t i) \
{ \
assert (i > 0); \
return (i - 1) / 2; \
} \
\
static inline size_t \
M_C(name, _i_lchild)(size_t i) \
{ \
assert(i <= ((SIZE_MAX)-2)/2); \
return 2*i + 1; \
} \
\
static inline size_t \
M_C(name, _i_rchild)(size_t i) \
{ \
assert(i <= ((SIZE_MAX)-2)/2); \
return 2*i + 2; \
} \
\
static inline int \
M_C(name, _i_cmp)(const prioqueue_t p, size_t i, size_t j) \
{ \
return M_CALL_CMP(oplist, *M_C(name, _array_cget)(p->array, i), \
*M_C(name, _array_cget)(p->array, j)); \
} \
\
static inline bool \
M_C(name, _empty_p)(prioqueue_t const p) \
{ \
return M_C(name, _array_empty_p)(p->array); \
} \
\
static inline size_t \
M_C(name, _size)(prioqueue_t const p) \
{ \
return M_C(name, _array_size)(p->array); \
} \
\
static inline void \
M_C(name, _push)(prioqueue_t p, type const x) \
{ \
/* Push back the new element at the end of the array */ \
M_C(name, _array_push_back)(p->array, x); \
\
/* Reorder the array by swapping with its parent \
* until it reaches the right position */ \
size_t i = M_C(name, _array_size)(p->array)-1; \
while (i > 0) { \
size_t j = M_C(name, _i_parent)(i); \
if (M_C(name, _i_cmp)(p, j, i) <= 0) \
break; \
M_C(name, _array_swap_at) (p->array, i, j); \
i = j; \
} \
} \
\
static inline type const * \
M_C(name, _front)(prioqueue_t const p) \
{ \
return M_C(name, _array_cget)(p->array, 0); \
} \
\
static inline void \
M_C(name, _pop)(type *x, prioqueue_t p) \
{ \
/* Swap the front element with the last element */ \
size_t size = M_C(name, _array_size)(p->array)-1; \
M_C(name, _array_swap_at) (p->array, 0, size); \
/* Swap the new last element */ \
M_C(name, _array_pop_back)(x, p->array); \
\
/* Reorder the heap */ \
size_t i = 0; \
while (true) { \
size_t child = M_C(name, _i_lchild)(i); \
if (child >= size) \
break; \
size_t otherChild = M_C(name, _i_rchild)(i); \
if (otherChild < size \
&& M_C(name, _i_cmp)(p, otherChild, child) < 0 ) { \
child = otherChild; \
} \
if (M_C(name, _i_cmp)(p, i, child) <= 0) \
break; \
M_C(name, _array_swap_at) (p->array, i, child); \
i = child; \
} \
} \
\
/* Define iterators over the array iterator */ \
static inline void \
M_C(name, _it)(it_t it, prioqueue_t const v) \
{ \
M_C(name, _array_it)(it, v->array); \
} \
\
static inline void \
M_C(name, _it_last)(it_t it, prioqueue_t const v) \
{ \
M_C(name, _array_it_last)(it, v->array); \
} \
\
static inline void \
M_C(name, _it_end)(it_t it, prioqueue_t const v) \
{ \
M_C(name, _array_it_end)(it, v->array); \
} \
\
static inline void \
M_C(name, _it_set)(it_t it, const it_t org) \
{ \
M_C(name, _array_it_set)(it, org); \
} \
\
static inline bool \
M_C(name, _end_p)(const it_t it) \
{ \
return M_C(name, _array_end_p)(it); \
} \
\
static inline bool \
M_C(name, _last_p)(const it_t it) \
{ \
return M_C(name, _array_last_p)(it); \
} \
\
static inline bool \
M_C(name, _it_equal_p)(const it_t it1, \
const it_t it2) \
{ \
return M_C(name, _array_it_equal_p)(it1, it2); \
} \
\
static inline void \
M_C(name, _next)(it_t it) \
{ \
M_C(name, _array_next)(it); \
} \
\
static inline void \
M_C(name, _previous)(it_t it) \
{ \
M_C(name, _array_previous)(it); \
} \
\
static inline type const * \
M_C(name, _cref)(const it_t it) \
{ \
return M_C(name, _array_cref)(it); \
} \
\
M_IF_METHOD(EQUAL, oplist) \
( \
/* EQUAL & CMP may be uncorrelated */ \
static inline bool \
M_C(name, _erase)(prioqueue_t p, type x) \
{ \
/* First pass: search for an item EQUAL to x */ \
/* NOTE: An HASHMAP may be a good idea to optimize this pass. */ \
size_t size = M_C(name, _array_size)(p->array); \
size_t i = 0; \
for(i = 0; i < size; i++) { \
if (M_CALL_EQUAL(oplist, *M_C(name, _array_cget)(p->array, i), x)) \
break; \
} \
/* If x is not found, then stop */ \
if (i >= size) \
return false; \
/* Swap the found item and the last element */ \
size--; \
M_C(name, _array_swap_at) (p->array, i, size); \
M_C(name, _array_pop_back)(NULL, p->array); \
/* Move back the last swapped element to its right position in the heap */ \
while (true) { \
size_t child = M_C(name, _i_lchild)(i); \
if (child >= size) break; \
size_t otherChild = M_C(name, _i_rchild)(i); \
if (otherChild < size \
&& M_C(name, _i_cmp)(p, otherChild, child) < 0 ) { \
child = otherChild; \
} \
if (M_C(name, _i_cmp)(p, i, child) <= 0) break; \
M_C(name, _array_swap_at) (p->array, i, child); \
i = child; \
} \
return true; \
} \
\
static inline void \
M_C(name, _update_further)(prioqueue_t p, type xold, type xnew) \
{ \
/* This update assumes that the new position is further in the heap */ \
assert (M_CALL_CMP(oplist, xold, xnew) > 0); \
/* First pass: search for an item EQUAL to x */ \
size_t size = M_C(name, _array_size)(p->array); \
size_t i = 0; \
for(i = 0; i < size; i++) { \
if (M_CALL_EQUAL(oplist, *M_C(name, _array_cget)(p->array, i), xold)) \
break; \
} \
/* We shall have found the item */ \
assert (i < size); \
/* Set the found item to the new element */ \
M_C(name, _array_set_at) (p->array, i, xnew); \
/* Move back the updated element to its right position in the heap */ \
while (true) { \
size_t child = M_C(name, _i_lchild)(i); \
if (child >= size) break; \
size_t otherChild = M_C(name, _i_rchild)(i); \
if (otherChild < size \
&& M_C(name, _i_cmp)(p, otherChild, child) < 0 ) { \
child = otherChild; \
} \
if (M_C(name, _i_cmp)(p, i, child) <= 0) break; \
M_C(name, _array_swap_at) (p->array, i, child); \
i = child; \
} \
} \
\
, /* No EQUAL */ ) \
while (true) { \
size_t child = M_C(name, _i_lchild)(i); \
if (child >= size) break; \
size_t otherChild = M_C(name, _i_rchild)(i); \
if (otherChild < size \
&& M_C(name, _i_cmp)(p, otherChild, child) < 0 ) { \
child = otherChild; \
} \
if (M_C(name, _i_cmp)(p, i, child) <= 0) break; \
M_C(name, _array_swap_at) (p->array, i, child); \
i = child; \
} \
return true; \
} \
\
static inline void \
M_C(name, _update_further)(prioqueue_t p, type xold, type xnew) \
{ \
/* This update assumes that the new position is further in the heap */ \
assert (M_CALL_CMP(oplist, xold, xnew) > 0); \
/* First pass: search for an item EQUAL to x */ \
size_t size = M_C(name, _array_size)(p->array); \
size_t i = 0; \
for(i = 0; i < size; i++) { \
if (M_CALL_EQUAL(oplist, *M_C(name, _array_cget)(p->array, i), xold)) \
break; \
} \
/* We shall have found the item */ \
assert (i < size); \
/* Set the found item to the new element */ \
M_C(name, _array_set_at) (p->array, i, xnew); \
/* Move back the updated element to its right position in the heap */ \
while (true) { \
size_t child = M_C(name, _i_lchild)(i); \
if (child >= size) break; \
size_t otherChild = M_C(name, _i_rchild)(i); \
if (otherChild < size \
&& M_C(name, _i_cmp)(p, otherChild, child) < 0 ) { \
child = otherChild; \
} \
if (M_C(name, _i_cmp)(p, i, child) <= 0) break; \
M_C(name, _array_swap_at) (p->array, i, child); \
i = child; \
} \
} \
\
, /* No EQUAL */ ) \
// TODO: set all & remove all function
+1004 -1004
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -271,7 +271,7 @@ static inline void m_serial_json_write_clear(m_serial_write_t serial)
/* Define a synonym to the JSON serializer with a proper OPLIST */
typedef m_serial_write_t m_serial_json_write_t;
#define M_OPL_m_serial_json_write_t() \
#define M_OPL_m_serial_json_write_t() \
(INIT_WITH(m_serial_json_write_init), CLEAR(m_serial_json_write_clear), TYPE(m_serial_json_write_t) )
@@ -572,7 +572,7 @@ static inline void m_serial_json_read_clear(m_serial_read_t serial)
/* Define a synonym of m_serial_read_t
to the JSON serializer with its proper OPLIST */
typedef m_serial_read_t m_serial_json_read_t;
#define M_OPL_m_serial_json_read_t() \
#define M_OPL_m_serial_json_read_t() \
(INIT_WITH(m_serial_json_read_init), CLEAR(m_serial_json_read_clear), TYPE(m_serial_json_read_t) )
M_END_PROTECTED_CODE
+362 -362
View File
@@ -33,17 +33,17 @@ M_BEGIN_PROTECTED_CODE
/* Define the oplist of a shared pointer.
USAGE: SHARED_OPLIST(name [, oplist_of_the_type]) */
#define SHARED_PTR_OPLIST(...) \
SHAREDI_PTR_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST ), \
#define SHARED_PTR_OPLIST(...) \
SHAREDI_PTR_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST ), \
(__VA_ARGS__ )))
/* Define shared pointer and its function.
USAGE: SHARED_PTR_DEF(name, type, [, oplist]) */
#define SHARED_PTR_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SHARED_PTR_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_ATOMIC_OPLIST, M_C(name, _t) ), \
(name, __VA_ARGS__ , SHAREDI_ATOMIC_OPLIST, M_C(name, _t) ))) \
M_END_PROTECTED_CODE
@@ -52,9 +52,9 @@ M_BEGIN_PROTECTED_CODE
/* Define shared pointer and its function
as the given name name_t
USAGE: SHARED_PTR_DEF_AS(name, name_t, type, [, oplist]) */
#define SHARED_PTR_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SHARED_PTR_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_ATOMIC_OPLIST, name_t ), \
(name, __VA_ARGS__ , SHAREDI_ATOMIC_OPLIST, name_t ))) \
M_END_PROTECTED_CODE
@@ -62,9 +62,9 @@ M_BEGIN_PROTECTED_CODE
/* Define relaxed shared pointer and its function (thread unsafe).
USAGE: SHARED_PTR_RELAXED_DEF(name, type, [, oplist]) */
#define SHARED_PTR_RELAXED_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SHARED_PTR_RELAXED_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_INTEGER_OPLIST, M_C(name, _t) ), \
(name, __VA_ARGS__, SHAREDI_INTEGER_OPLIST, M_C(name, _t) ))) \
M_END_PROTECTED_CODE
@@ -73,9 +73,9 @@ M_BEGIN_PROTECTED_CODE
/* Define relaxed shared pointer and its function (thread unsafe)
as the given name name_t
USAGE: SHARED_PTR_RELAXED_DEF(name, type, [, oplist]) */
#define SHARED_PTR_RELAXED_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SHARED_PTR_RELAXED_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_INTEGER_OPLIST, name_t ), \
(name, __VA_ARGS__, SHAREDI_INTEGER_OPLIST, name_t ))) \
M_END_PROTECTED_CODE
@@ -84,9 +84,9 @@ M_BEGIN_PROTECTED_CODE
/* Define shared resource and its function.
This is a bounded pool of resource shared by multiple owners.
USAGE: SHARED_RESOURCE_DEF(name, type, [, oplist]) */
#define SHARED_RESOURCE_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_RESOURCE_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SHARED_RESOURCE_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_RESOURCE_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t), M_C(name, _it_t) ), \
(name, __VA_ARGS__, M_C(name, _t), M_C(name, _it_t) ))) \
M_END_PROTECTED_CODE
@@ -96,9 +96,9 @@ M_BEGIN_PROTECTED_CODE
as the given name named_t and the iterator it_t
This is a bounded pool of resource shared by multiple owners.
USAGE: SHARED_RESOURCE_DEF_AS(name, name_t, it_t, type, [, oplist]) */
#define SHARED_RESOURCE_DEF_AS(name, name_t, it_t, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_RESOURCE_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SHARED_RESOURCE_DEF_AS(name, name_t, it_t, ...) \
M_BEGIN_PROTECTED_CODE \
SHAREDI_RESOURCE_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t, it_t ), \
(name, __VA_ARGS__, name_t, it_t ))) \
M_END_PROTECTED_CODE
@@ -111,40 +111,40 @@ M_BEGIN_PROTECTED_CODE
#define SHAREDI_PTR_OPLIST_P1(arg) SHAREDI_PTR_OPLIST_P2 arg
/* Validation of the given, shared_t oplist */
#define SHAREDI_PTR_OPLIST_P2(name, oplist) \
#define SHAREDI_PTR_OPLIST_P2(name, oplist) \
M_IF_OPLIST(oplist)(SHAREDI_PTR_OPLIST_P3, SHAREDI_PTR_OPLIST_FAILURE)(name, oplist)
/* Prepare a clean compilation failure */
#define SHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
#define SHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
((M_LIB_ERROR(ARGUMENT_OF_SHARED_PTR_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
#define SHAREDI_PTR_OPLIST_P3(name, oplist) ( \
INIT(M_C(name, _init)), \
CLEAR(M_C(name, _clear)), \
INIT_SET(M_C(name, _init_set)), \
SET(M_C(name, _set)) \
INIT_MOVE(M_C(name, _init_move)), \
CLEAN(M_C(name, _clean)), \
MOVE(M_C(name, _move)), \
SWAP(M_C(name, _swap)) \
,TYPE(M_C(name, _ct)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
#define SHAREDI_PTR_OPLIST_P3(name, oplist) ( \
INIT(M_C(name, _init)), \
CLEAR(M_C(name, _clear)), \
INIT_SET(M_C(name, _init_set)), \
SET(M_C(name, _set)) \
INIT_MOVE(M_C(name, _init_move)), \
CLEAN(M_C(name, _clean)), \
MOVE(M_C(name, _move)), \
SWAP(M_C(name, _swap)) \
,TYPE(M_C(name, _ct)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
// OPLIST to handle a counter of atomic type
#define SHAREDI_ATOMIC_OPLIST (TYPE(atomic_int), \
INIT_SET(atomic_init), \
ADD(atomic_fetch_add), \
SUB(atomic_fetch_sub), \
#define SHAREDI_ATOMIC_OPLIST (TYPE(atomic_int), \
INIT_SET(atomic_init), \
ADD(atomic_fetch_add), \
SUB(atomic_fetch_sub), \
IT_CREF(atomic_load))
// OPLIST to handle a counter of non-atomic type
#define SHAREDI_INTEGER_OPLIST (TYPE(int), \
INIT_SET(sharedi_integer_init_set), \
ADD(sharedi_integer_add), \
SUB(sharedi_integer_sub), \
#define SHAREDI_INTEGER_OPLIST (TYPE(int), \
INIT_SET(sharedi_integer_init_set), \
ADD(sharedi_integer_add), \
SUB(sharedi_integer_sub), \
IT_CREF(sharedi_integer_cref))
/* Atomic like interface for basic integers */
@@ -154,8 +154,8 @@ static inline int sharedi_integer_sub(int *p, int val) { int r = *p; *p -= val;
static inline int sharedi_integer_cref(int *p) { return *p; }
/* Contract of a shared pointer */
#define SHAREDI_CONTRACT(shared, cpt_oplist) do { \
assert(shared != NULL); \
#define SHAREDI_CONTRACT(shared, cpt_oplist) do { \
assert(shared != NULL); \
assert(*shared == NULL || M_CALL_IT_CREF(cpt_oplist, &(*shared)->cpt) >= 1); \
} while (0)
@@ -163,344 +163,344 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
#define SHAREDI_PTR_DEF_P1(arg) SHAREDI_PTR_DEF_P2 arg
/* Validate the oplist before going further */
#define SHAREDI_PTR_DEF_P2(name, type, oplist, cpt_oplist, shared_t) \
#define SHAREDI_PTR_DEF_P2(name, type, oplist, cpt_oplist, shared_t) \
M_IF_OPLIST(oplist)(SHAREDI_PTR_DEF_P3, SHAREDI_PTR_DEF_FAILURE)(name, type, oplist, cpt_oplist, shared_t)
/* Stop processing with a compilation failure */
#define SHAREDI_PTR_DEF_FAILURE(name, type, oplist, cpt_oplist, shared_t) \
#define SHAREDI_PTR_DEF_FAILURE(name, type, oplist, cpt_oplist, shared_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SHARED_PTR_DEF): the given argument is not a valid oplist: " #oplist)
/* Code generation */
#define SHAREDI_PTR_DEF_P3(name, type, oplist, cpt_oplist, shared_t) \
\
typedef struct M_C(name, _s){ \
type *data; /* Pointer to the data */ \
M_GET_TYPE cpt_oplist cpt; /* Counter of how many refs the data */ \
bool combineAlloc; /* Does the data and the ptr share the slot? */ \
} *shared_t[1]; \
typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
\
/* Internal type for oplist */ \
typedef shared_t M_C(name, _ct); \
\
typedef struct M_C(name, combine_s) { \
type data; \
struct M_C(name, _s) ptr; \
} M_C(name, combine_ct)[1]; \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(shared_t shared) \
{ \
*shared = NULL; \
} \
\
static inline void \
M_C(name, _init2)(shared_t shared, type *data) \
{ \
assert (shared != NULL); \
/* The shared ptr get exclusive access to data */ \
struct M_C(name, _s) *ptr; \
if (M_UNLIKELY (data == NULL)) { \
*shared = NULL; \
return; \
} \
ptr = M_CALL_NEW(oplist, struct M_C(name, _s)); \
if (M_UNLIKELY (ptr == NULL)) { \
M_MEMORY_FULL(sizeof(struct M_C(name, _s))); \
return; \
} \
ptr->data = data; \
M_CALL_INIT_SET(cpt_oplist, &ptr->cpt, 1); \
ptr->combineAlloc = false; \
*shared = ptr; \
SHAREDI_CONTRACT(shared, cpt_oplist); \
} \
\
static inline void \
M_C(name, _init_new)(shared_t shared) \
{ \
/* NOTE: Alloc 1 struct with both structures. */ \
struct M_C(name, combine_s) *p = \
M_CALL_NEW(oplist, struct M_C(name, combine_s)); \
if (M_UNLIKELY (p == NULL)) { \
M_MEMORY_FULL(sizeof(struct M_C(name, combine_s))); \
return; \
} \
struct M_C(name, _s) *ptr = &p->ptr; \
type *data = &p->data; \
M_CALL_INIT( oplist, *data); \
ptr->data = data; \
M_CALL_INIT_SET(cpt_oplist, &ptr->cpt, 1); \
ptr->combineAlloc = true; \
*shared = ptr; \
SHAREDI_CONTRACT(shared, cpt_oplist); \
} \
\
static inline bool \
M_C(name, _NULL_p)(const shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
return *shared == NULL; \
} \
\
static inline void \
M_C(name, _init_set)(shared_t dest, \
const shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert (dest != shared); \
*dest = *shared; \
if (*dest != NULL) { \
int n = M_CALL_ADD(cpt_oplist, &((*dest)->cpt), 1); \
(void) n; /* unused return value */ \
} \
SHAREDI_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_C(name, _clear)(shared_t dest) \
{ \
SHAREDI_CONTRACT(dest, cpt_oplist); \
if (*dest != NULL) { \
if (M_CALL_SUB(cpt_oplist, &((*dest)->cpt), 1) == 1) { \
bool combineAlloc = (*dest)->combineAlloc; \
/* Note: if combineAlloc is true, the address of the slot \
combining both data & ptr is the same as the address of the \
first element, aka data itself. Static analyzer tools don't \
seem to detect this and report error. */ \
M_CALL_CLEAR(oplist, *(*dest)->data); \
M_CALL_DEL(oplist, (*dest)->data); \
if (combineAlloc == false) \
M_CALL_DEL(oplist, *dest); \
} \
*dest = NULL; \
} \
SHAREDI_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_C(name, _clean)(shared_t dest) \
{ \
/* NOTE: Clear will also set dest to NULL */ \
M_C(name, _clear)(dest); \
} \
\
static inline void \
M_C(name, _set)(shared_t dest, \
const shared_t shared) \
{ \
SHAREDI_CONTRACT(dest, cpt_oplist); \
SHAREDI_CONTRACT(shared, cpt_oplist); \
M_C(name, _clear)(dest); \
M_C(name, _init_set)(dest, shared); \
} \
\
static inline void \
M_C(name, _init_move)(shared_t dest, \
shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert (dest != NULL && dest != shared); \
*dest = *shared; \
*shared = NULL; \
SHAREDI_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_C(name, _move)(shared_t dest, \
shared_t shared) \
{ \
SHAREDI_CONTRACT(dest, cpt_oplist); \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert (dest != shared); \
M_C(name, _clear)(dest); \
M_C(name, _init_move)(dest, shared); \
} \
\
static inline void \
M_C(name, _swap)(shared_t p1, \
shared_t p2) \
{ \
SHAREDI_CONTRACT(p1, cpt_oplist); \
SHAREDI_CONTRACT(p2, cpt_oplist); \
/* NOTE: SWAP is not atomic */ \
M_SWAP (struct M_C(name, _s)*, *p1, *p2); \
SHAREDI_CONTRACT(p1, cpt_oplist); \
SHAREDI_CONTRACT(p2, cpt_oplist); \
} \
\
static inline bool \
M_C(name, _equal_p)(const shared_t p1, \
const shared_t p2) \
{ \
SHAREDI_CONTRACT(p1, cpt_oplist); \
SHAREDI_CONTRACT(p2, cpt_oplist); \
return *p1 == *p2; \
} \
\
static inline type const * \
M_C(name, _cref)(const shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert(*shared != NULL); \
type *data = (*shared)->data; \
assert (data != NULL); \
return M_CONST_CAST (type, data); \
} \
\
static inline type * \
M_C(name, _ref)(shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert(*shared != NULL); \
type *data = (*shared)->data; \
assert (data != NULL); \
return data; \
} \
#define SHAREDI_PTR_DEF_P3(name, type, oplist, cpt_oplist, shared_t) \
\
typedef struct M_C(name, _s){ \
type *data; /* Pointer to the data */ \
M_GET_TYPE cpt_oplist cpt; /* Counter of how many refs the data */ \
bool combineAlloc; /* Does the data and the ptr share the slot? */ \
} *shared_t[1]; \
typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
\
/* Internal type for oplist */ \
typedef shared_t M_C(name, _ct); \
\
typedef struct M_C(name, combine_s) { \
type data; \
struct M_C(name, _s) ptr; \
} M_C(name, combine_ct)[1]; \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(shared_t shared) \
{ \
*shared = NULL; \
} \
\
static inline void \
M_C(name, _init2)(shared_t shared, type *data) \
{ \
assert (shared != NULL); \
/* The shared ptr get exclusive access to data */ \
struct M_C(name, _s) *ptr; \
if (M_UNLIKELY (data == NULL)) { \
*shared = NULL; \
return; \
} \
ptr = M_CALL_NEW(oplist, struct M_C(name, _s)); \
if (M_UNLIKELY (ptr == NULL)) { \
M_MEMORY_FULL(sizeof(struct M_C(name, _s))); \
return; \
} \
ptr->data = data; \
M_CALL_INIT_SET(cpt_oplist, &ptr->cpt, 1); \
ptr->combineAlloc = false; \
*shared = ptr; \
SHAREDI_CONTRACT(shared, cpt_oplist); \
} \
\
static inline void \
M_C(name, _init_new)(shared_t shared) \
{ \
/* NOTE: Alloc 1 struct with both structures. */ \
struct M_C(name, combine_s) *p = \
M_CALL_NEW(oplist, struct M_C(name, combine_s)); \
if (M_UNLIKELY (p == NULL)) { \
M_MEMORY_FULL(sizeof(struct M_C(name, combine_s))); \
return; \
} \
struct M_C(name, _s) *ptr = &p->ptr; \
type *data = &p->data; \
M_CALL_INIT( oplist, *data); \
ptr->data = data; \
M_CALL_INIT_SET(cpt_oplist, &ptr->cpt, 1); \
ptr->combineAlloc = true; \
*shared = ptr; \
SHAREDI_CONTRACT(shared, cpt_oplist); \
} \
\
static inline bool \
M_C(name, _NULL_p)(const shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
return *shared == NULL; \
} \
\
static inline void \
M_C(name, _init_set)(shared_t dest, \
const shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert (dest != shared); \
*dest = *shared; \
if (*dest != NULL) { \
int n = M_CALL_ADD(cpt_oplist, &((*dest)->cpt), 1); \
(void) n; /* unused return value */ \
} \
SHAREDI_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_C(name, _clear)(shared_t dest) \
{ \
SHAREDI_CONTRACT(dest, cpt_oplist); \
if (*dest != NULL) { \
if (M_CALL_SUB(cpt_oplist, &((*dest)->cpt), 1) == 1) { \
bool combineAlloc = (*dest)->combineAlloc; \
/* Note: if combineAlloc is true, the address of the slot \
combining both data & ptr is the same as the address of the \
first element, aka data itself. Static analyzer tools don't \
seem to detect this and report error. */ \
M_CALL_CLEAR(oplist, *(*dest)->data); \
M_CALL_DEL(oplist, (*dest)->data); \
if (combineAlloc == false) \
M_CALL_DEL(oplist, *dest); \
} \
*dest = NULL; \
} \
SHAREDI_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_C(name, _clean)(shared_t dest) \
{ \
/* NOTE: Clear will also set dest to NULL */ \
M_C(name, _clear)(dest); \
} \
\
static inline void \
M_C(name, _set)(shared_t dest, \
const shared_t shared) \
{ \
SHAREDI_CONTRACT(dest, cpt_oplist); \
SHAREDI_CONTRACT(shared, cpt_oplist); \
M_C(name, _clear)(dest); \
M_C(name, _init_set)(dest, shared); \
} \
\
static inline void \
M_C(name, _init_move)(shared_t dest, \
shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert (dest != NULL && dest != shared); \
*dest = *shared; \
*shared = NULL; \
SHAREDI_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_C(name, _move)(shared_t dest, \
shared_t shared) \
{ \
SHAREDI_CONTRACT(dest, cpt_oplist); \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert (dest != shared); \
M_C(name, _clear)(dest); \
M_C(name, _init_move)(dest, shared); \
} \
\
static inline void \
M_C(name, _swap)(shared_t p1, \
shared_t p2) \
{ \
SHAREDI_CONTRACT(p1, cpt_oplist); \
SHAREDI_CONTRACT(p2, cpt_oplist); \
/* NOTE: SWAP is not atomic */ \
M_SWAP (struct M_C(name, _s)*, *p1, *p2); \
SHAREDI_CONTRACT(p1, cpt_oplist); \
SHAREDI_CONTRACT(p2, cpt_oplist); \
} \
\
static inline bool \
M_C(name, _equal_p)(const shared_t p1, \
const shared_t p2) \
{ \
SHAREDI_CONTRACT(p1, cpt_oplist); \
SHAREDI_CONTRACT(p2, cpt_oplist); \
return *p1 == *p2; \
} \
\
static inline type const * \
M_C(name, _cref)(const shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert(*shared != NULL); \
type *data = (*shared)->data; \
assert (data != NULL); \
return M_CONST_CAST (type, data); \
} \
\
static inline type * \
M_C(name, _ref)(shared_t shared) \
{ \
SHAREDI_CONTRACT(shared, cpt_oplist); \
assert(*shared != NULL); \
type *data = (*shared)->data; \
assert (data != NULL); \
return data; \
} \
/********************************** SHARED RESOURCE ************************************/
#define SHAREDI_RESOURCE_CONTRACT(s) do { \
assert (s != NULL); \
assert (s->buffer != NULL); \
#define SHAREDI_RESOURCE_CONTRACT(s) do { \
assert (s != NULL); \
assert (s->buffer != NULL); \
} while (0)
// deferred
#define SHAREDI_RESOURCE_DEF_P1(arg) SHAREDI_RESOURCE_DEF_P2 arg
/* Validate the oplist before going further */
#define SHAREDI_RESOURCE_DEF_P2(name, type, oplist, shared_t, it_t) \
#define SHAREDI_RESOURCE_DEF_P2(name, type, oplist, shared_t, it_t) \
M_IF_OPLIST(oplist)(SHAREDI_RESOURCE_DEF_P3, SHAREDI_RESOURCE_DEF_FAILURE)(name, type, oplist, shared_t, it_t)
/* Stop processing with a compilation failure */
#define SHAREDI_RESOURCE_DEF_FAILURE(name, type, oplist, shared_t, it_t) \
#define SHAREDI_RESOURCE_DEF_FAILURE(name, type, oplist, shared_t, it_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SHARED_RESOURCE_DEF): the given argument is not a valid oplist: " #oplist)
#define SHAREDI_RESOURCE_DEF_P3(name, type, oplist, shared_t, it_t) \
\
/* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _atype_s) { \
atomic_uint cpt; \
type x; \
M_CACHELINE_ALIGN(align, type, atomic_uint); \
} M_C(name, _atype_ct); \
\
typedef struct M_C(name, _s) { \
genint_t core; \
M_C(name, _atype_ct) *buffer; \
} shared_t[1]; \
\
typedef struct M_C(name, _it_s) { \
unsigned int idx; \
struct M_C(name, _s) *ref; \
} it_t[1]; \
\
/* Internal Types for oplist */ \
typedef shared_t M_C(name, _ct); \
typedef it_t M_C(name, _it__ct); \
\
static inline void \
M_C(name, _init)(shared_t s, size_t n) \
{ \
assert(s != NULL); \
assert (n > 0 && n < UINT_MAX); \
s->buffer = M_CALL_REALLOC(oplist, M_C(name, _atype_ct), NULL, n); \
if (M_UNLIKELY (s->buffer == NULL)) { \
M_MEMORY_FULL(sizeof(M_C(name, _atype_ct)) * n); \
return; \
} \
for(size_t i = 0; i < n; i++) { \
M_CALL_INIT(oplist, s->buffer[i].x); \
atomic_init (&s->buffer[i].cpt, 0U); \
} \
genint_init(s->core, (unsigned int) n); \
SHAREDI_RESOURCE_CONTRACT(s); \
} \
\
static inline void \
M_C(name, _clear)(shared_t s) \
{ \
SHAREDI_RESOURCE_CONTRACT(s); \
size_t n = genint_size(s->core); \
for(size_t i = 0; i < n; i++) { \
M_CALL_CLEAR(oplist, s->buffer[i].x); \
} \
M_CALL_FREE(oplist, s->buffer); \
s->buffer = NULL; \
genint_clear(s->core); \
} \
\
static inline void \
M_C(name, _it)(it_t it, shared_t s) \
{ \
SHAREDI_RESOURCE_CONTRACT(s); \
assert (it != NULL); \
unsigned int idx = genint_pop(s->core); \
it->idx = idx; \
it->ref = s; \
if (M_LIKELY (idx != GENINT_ERROR)) { \
assert(atomic_load(&s->buffer[idx].cpt) == 0); \
atomic_store(&s->buffer[idx].cpt, 1U); \
} \
} \
\
static inline bool \
M_C(name, _end_p)(it_t it) \
{ \
assert (it != NULL); \
return it->idx == GENINT_ERROR; \
} \
\
static inline type * \
M_C(name, _ref)(it_t it) \
{ \
assert (it != NULL && it->ref != NULL && it->idx != GENINT_ERROR); \
SHAREDI_RESOURCE_CONTRACT(it->ref); \
return &it->ref->buffer[it->idx].x; \
} \
\
static inline type const * \
M_C(name, _cref)(it_t it) \
{ \
assert (it != NULL && it->ref != NULL && it->idx != GENINT_ERROR); \
SHAREDI_RESOURCE_CONTRACT(it->ref); \
return M_CONST_CAST (type, &it->ref->buffer[it->idx].x); \
} \
\
static inline void \
M_C(name, _end)(it_t it, shared_t s) \
{ \
SHAREDI_RESOURCE_CONTRACT(s); \
assert (it != NULL); \
assert (it->ref == s); \
unsigned int idx = it->idx; \
if (M_LIKELY (idx != GENINT_ERROR)) { \
unsigned int c = atomic_fetch_sub (&it->ref->buffer[idx].cpt, 1U); \
if (c == 1) { \
genint_push(it->ref->core, idx); \
} \
it->idx = GENINT_ERROR; \
} \
} \
\
static inline void \
M_C(name, _it_set)(it_t itd, it_t its) \
{ \
assert (itd != NULL && its != NULL); \
SHAREDI_RESOURCE_CONTRACT(its->ref); \
itd->ref = its->ref; \
unsigned int idx = its->idx; \
itd->idx = idx; \
if (M_LIKELY (idx != GENINT_ERROR)) { \
unsigned int c = atomic_fetch_add(&itd->ref->buffer[idx].cpt, 1U); \
assert (c >= 1); \
} \
} \
#define SHAREDI_RESOURCE_DEF_P3(name, type, oplist, shared_t, it_t) \
\
/* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _atype_s) { \
atomic_uint cpt; \
type x; \
M_CACHELINE_ALIGN(align, type, atomic_uint); \
} M_C(name, _atype_ct); \
\
typedef struct M_C(name, _s) { \
genint_t core; \
M_C(name, _atype_ct) *buffer; \
} shared_t[1]; \
\
typedef struct M_C(name, _it_s) { \
unsigned int idx; \
struct M_C(name, _s) *ref; \
} it_t[1]; \
\
/* Internal Types for oplist */ \
typedef shared_t M_C(name, _ct); \
typedef it_t M_C(name, _it__ct); \
\
static inline void \
M_C(name, _init)(shared_t s, size_t n) \
{ \
assert(s != NULL); \
assert (n > 0 && n < UINT_MAX); \
s->buffer = M_CALL_REALLOC(oplist, M_C(name, _atype_ct), NULL, n); \
if (M_UNLIKELY (s->buffer == NULL)) { \
M_MEMORY_FULL(sizeof(M_C(name, _atype_ct)) * n); \
return; \
} \
for(size_t i = 0; i < n; i++) { \
M_CALL_INIT(oplist, s->buffer[i].x); \
atomic_init (&s->buffer[i].cpt, 0U); \
} \
genint_init(s->core, (unsigned int) n); \
SHAREDI_RESOURCE_CONTRACT(s); \
} \
\
static inline void \
M_C(name, _clear)(shared_t s) \
{ \
SHAREDI_RESOURCE_CONTRACT(s); \
size_t n = genint_size(s->core); \
for(size_t i = 0; i < n; i++) { \
M_CALL_CLEAR(oplist, s->buffer[i].x); \
} \
M_CALL_FREE(oplist, s->buffer); \
s->buffer = NULL; \
genint_clear(s->core); \
} \
\
static inline void \
M_C(name, _it)(it_t it, shared_t s) \
{ \
SHAREDI_RESOURCE_CONTRACT(s); \
assert (it != NULL); \
unsigned int idx = genint_pop(s->core); \
it->idx = idx; \
it->ref = s; \
if (M_LIKELY (idx != GENINT_ERROR)) { \
assert(atomic_load(&s->buffer[idx].cpt) == 0); \
atomic_store(&s->buffer[idx].cpt, 1U); \
} \
} \
\
static inline bool \
M_C(name, _end_p)(it_t it) \
{ \
assert (it != NULL); \
return it->idx == GENINT_ERROR; \
} \
\
static inline type * \
M_C(name, _ref)(it_t it) \
{ \
assert (it != NULL && it->ref != NULL && it->idx != GENINT_ERROR); \
SHAREDI_RESOURCE_CONTRACT(it->ref); \
return &it->ref->buffer[it->idx].x; \
} \
\
static inline type const * \
M_C(name, _cref)(it_t it) \
{ \
assert (it != NULL && it->ref != NULL && it->idx != GENINT_ERROR); \
SHAREDI_RESOURCE_CONTRACT(it->ref); \
return M_CONST_CAST (type, &it->ref->buffer[it->idx].x); \
} \
\
static inline void \
M_C(name, _end)(it_t it, shared_t s) \
{ \
SHAREDI_RESOURCE_CONTRACT(s); \
assert (it != NULL); \
assert (it->ref == s); \
unsigned int idx = it->idx; \
if (M_LIKELY (idx != GENINT_ERROR)) { \
unsigned int c = atomic_fetch_sub (&it->ref->buffer[idx].cpt, 1U); \
if (c == 1) { \
genint_push(it->ref->core, idx); \
} \
it->idx = GENINT_ERROR; \
} \
} \
\
static inline void \
M_C(name, _it_set)(it_t itd, it_t its) \
{ \
assert (itd != NULL && its != NULL); \
SHAREDI_RESOURCE_CONTRACT(its->ref); \
itd->ref = its->ref; \
unsigned int idx = its->idx; \
itd->idx = idx; \
if (M_LIKELY (idx != GENINT_ERROR)) { \
unsigned int c = atomic_fetch_add(&itd->ref->buffer[idx].cpt, 1U); \
assert (c >= 1); \
} \
} \
M_END_PROTECTED_CODE
+371 -371
View File
@@ -33,9 +33,9 @@ M_BEGIN_PROTECTED_CODE
/* Define a Single Producer Single Consummer snapshot and its functions
USAGE: SNAPSHOT_SPSC_DEF(name, type[, oplist]) */
#define SNAPSHOT_SPSC_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SNAPSHOT_SPSC_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t) ), \
(name, __VA_ARGS__ , M_C(name, _t) ))) \
M_END_PROTECTED_CODE
@@ -44,9 +44,9 @@ M_BEGIN_PROTECTED_CODE
/* Define a Single Producer Single Consummer snapshot and its functions
as the given name name_t
USAGE: SNAPSHOT_SPSC_DEF_AS(name, name_t, type[, oplist]) */
#define SNAPSHOT_SPSC_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SNAPSHOT_SPSC_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t ), \
(name, __VA_ARGS__ , name_t ))) \
M_END_PROTECTED_CODE
@@ -54,9 +54,9 @@ M_BEGIN_PROTECTED_CODE
/* Define a Single Producer Multiple Consummer snapshot and its functions
USAGE: SNAPSHOT_SPMC_DEF(name, type[, oplist]) */
#define SNAPSHOT_SPMC_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_SPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SNAPSHOT_SPMC_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_SPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t) ), \
(name, __VA_ARGS__ , M_C(name, _t) ))) \
M_END_PROTECTED_CODE
@@ -65,9 +65,9 @@ M_BEGIN_PROTECTED_CODE
/* Define a Single Producer Multiple Consummer snapshot and its functions
as the given name name_t
USAGE: SNAPSHOT_SPMC_DEF_AS(name, type[, oplist]) */
#define SNAPSHOT_SPMC_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_SPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SNAPSHOT_SPMC_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_SPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t ), \
(name, __VA_ARGS__ , name_t ))) \
M_END_PROTECTED_CODE
@@ -75,9 +75,9 @@ M_BEGIN_PROTECTED_CODE
/* Define a Multiple Producer Multiple Consummer snapshot and its functions
USAGE: SNAPSHOT_MPMC_DEF(name, type[, oplist]) */
#define SNAPSHOT_MPMC_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SNAPSHOT_MPMC_DEF(name, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t) ), \
(name, __VA_ARGS__ , M_C(name, _t) ))) \
M_END_PROTECTED_CODE
@@ -86,9 +86,9 @@ M_BEGIN_PROTECTED_CODE
/* Define a Multiple Producer Multiple Consummer snapshot and its functions
as the given name name_t
USAGE: SNAPSHOT_MPMC_DEF_AS(name, name_t, type[, oplist]) */
#define SNAPSHOT_MPMC_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SNAPSHOT_MPMC_DEF_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
SNAPSHOTI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t ), \
(name, __VA_ARGS__ , name_t ))) \
M_END_PROTECTED_CODE
@@ -96,8 +96,8 @@ M_BEGIN_PROTECTED_CODE
/* Define the oplist of a snapshot (SPSC, SPMC or MPMC).
USAGE: SNAPSHOT_OPLIST(name[, oplist]) */
#define SNAPSHOT_OPLIST(...) \
SNAPSHOTI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
#define SNAPSHOT_OPLIST(...) \
SNAPSHOTI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \
(__VA_ARGS__ )))
@@ -108,24 +108,24 @@ M_BEGIN_PROTECTED_CODE
#define SNAPSHOTI_OPLIST_P1(arg) SNAPSHOTI_OPLIST_P2 arg
/* Validation of the given oplist */
#define SNAPSHOTI_OPLIST_P2(name, oplist) \
#define SNAPSHOTI_OPLIST_P2(name, oplist) \
M_IF_OPLIST(oplist)(SNAPSHOTI_OPLIST_P3, SNAPSHOTI_OPLIST_FAILURE)(name, oplist)
/* Prepare a clean compilation failure */
#define SNAPSHOTI_OPLIST_FAILURE(name, oplist) \
#define SNAPSHOTI_OPLIST_FAILURE(name, oplist) \
((M_LIB_ERROR(ARGUMENT_OF_SNAPSHOT_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
/* Define the oplist of a snapshot */
#define SNAPSHOTI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _init)) \
,INIT_SET(M_C(name, _init_set)) \
,SET(M_C(name, _set)) \
,CLEAR(M_C(name, _clear)) \
,TYPE(M_C(name, _ct)) \
,SUBTYPE(M_C(name, _subtype_ct)) \
,OPLIST(oplist) \
,M_IF_METHOD(INIT_MOVE, oplist)(INIT_MOVE(M_C(name, _init_move)),) \
,M_IF_METHOD(MOVE, oplist)(MOVE(M_C(name, _move)),) \
#define SNAPSHOTI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _init)) \
,INIT_SET(M_C(name, _init_set)) \
,SET(M_C(name, _set)) \
,CLEAR(M_C(name, _clear)) \
,TYPE(M_C(name, _ct)) \
,SUBTYPE(M_C(name, _subtype_ct)) \
,OPLIST(oplist) \
,M_IF_METHOD(INIT_MOVE, oplist)(INIT_MOVE(M_C(name, _init_move)),) \
,M_IF_METHOD(MOVE, oplist)(MOVE(M_C(name, _move)),) \
)
@@ -138,28 +138,28 @@ M_BEGIN_PROTECTED_CODE
* - b: Boolean indicating that the read buffer shall be updated
* all fields packed in an unsigned char type.
*/
#define SNAPSHOTI_SPSC_FLAG(r, w, f, b) \
#define SNAPSHOTI_SPSC_FLAG(r, w, f, b) \
((unsigned char)( ( (r) << 4) | ((w) << 2) | ((f)) | ((b) << 6)))
#define SNAPSHOTI_SPSC_R(flags) \
#define SNAPSHOTI_SPSC_R(flags) \
(((unsigned int) (flags) >> 4) & 0x03u)
#define SNAPSHOTI_SPSC_W(flags) \
#define SNAPSHOTI_SPSC_W(flags) \
(((unsigned int) (flags) >> 2) & 0x03u)
#define SNAPSHOTI_SPSC_F(flags) \
#define SNAPSHOTI_SPSC_F(flags) \
(((unsigned int) (flags) >> 0) & 0x03u)
#define SNAPSHOTI_SPSC_B(flags) \
#define SNAPSHOTI_SPSC_B(flags) \
(((unsigned int) (flags) >> 6) & 0x01u)
/* NOTE: Due to atomic_load only accepting non-const pointer,
we can't have any const in the interface. */
#define SNAPSHOTI_SPSC_FLAGS_CONTRACT(flags) \
assert(SNAPSHOTI_SPSC_R(flags) != SNAPSHOTI_SPSC_W(flags) \
&& SNAPSHOTI_SPSC_R(flags) != SNAPSHOTI_SPSC_F(flags) \
#define SNAPSHOTI_SPSC_FLAGS_CONTRACT(flags) \
assert(SNAPSHOTI_SPSC_R(flags) != SNAPSHOTI_SPSC_W(flags) \
&& SNAPSHOTI_SPSC_R(flags) != SNAPSHOTI_SPSC_F(flags) \
&& SNAPSHOTI_SPSC_W(flags) != SNAPSHOTI_SPSC_F(flags))
#define SNAPSHOTI_SPSC_CONTRACT(snap) do { \
assert((snap) != NULL); \
unsigned char f = atomic_load (&(snap)->flags); \
SNAPSHOTI_SPSC_FLAGS_CONTRACT(f); \
#define SNAPSHOTI_SPSC_CONTRACT(snap) do { \
assert((snap) != NULL); \
unsigned char f = atomic_load (&(snap)->flags); \
SNAPSHOTI_SPSC_FLAGS_CONTRACT(f); \
} while (0)
// A snapshot is basically an atomic triple buffer (Lock Free)
@@ -170,182 +170,182 @@ M_BEGIN_PROTECTED_CODE
#define SNAPSHOTI_SPSC_DEF_P1(arg) SNAPSHOTI_SPSC_DEF_P2 arg
/* Validate the oplist before going further */
#define SNAPSHOTI_SPSC_DEF_P2(name, type, oplist, snapshot_t) \
#define SNAPSHOTI_SPSC_DEF_P2(name, type, oplist, snapshot_t) \
M_IF_OPLIST(oplist)(SNAPSHOTI_SPSC_DEF_P3, SNAPSHOTI_SPSC_DEF_FAILURE)(name, type, oplist, snapshot_t)
/* Stop processing with a compilation failure */
#define SNAPSHOTI_SPSC_DEF_FAILURE(name, type, oplist, snapshot_t) \
#define SNAPSHOTI_SPSC_DEF_FAILURE(name, type, oplist, snapshot_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_SPSC_DEF): the given argument is not a valid oplist: " #oplist)
/* Expand the type and the functions of a SPSC snapshot */
#define SNAPSHOTI_SPSC_DEF_P3(name, type, oplist, snapshot_t) \
\
/* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _aligned_type_s) { \
type x; \
M_CACHELINE_ALIGN(align, type); \
} M_C(name, _aligned_type_ct); \
\
typedef struct M_C(name, _s) { \
M_C(name, _aligned_type_ct) data[SNAPSHOTI_SPSC_MAX_BUFFER]; \
atomic_uchar flags; \
} snapshot_t[1]; \
typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
\
/* Define internal types for oplist */ \
typedef snapshot_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(snapshot_t snap) \
{ \
assert(snap != NULL); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_INIT(oplist, snap->data[i].x); \
} \
atomic_init (&snap->flags, SNAPSHOTI_SPSC_FLAG(0, 1, 2, 0)); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
\
static inline void \
M_C(name, _clear)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_CLEAR(oplist, snap->data[i].x); \
} \
} \
\
/* const is missing for org due to use of atomic_load of org */ \
static inline void \
M_C(name, _init_set)(snapshot_t snap, snapshot_t org) \
{ \
SNAPSHOTI_SPSC_CONTRACT(org); \
assert(snap != NULL && snap != org); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_INIT_SET(oplist, snap->data[i].x, org->data[i].x); \
} \
atomic_init (&snap->flags, atomic_load(&org->flags)); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
\
/* const is missing for org due to use of atomic_load of org */ \
static inline void \
M_C(name, _set)(snapshot_t snap, snapshot_t org) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
SNAPSHOTI_SPSC_CONTRACT(org); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_SET(oplist, snap->data[i].x, org->data[i].x); \
} \
atomic_init (&snap->flags, atomic_load(&org->flags)); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
\
M_IF_METHOD(INIT_MOVE, oplist)( \
static inline void \
M_C(name, _init_move)(snapshot_t snap, snapshot_t org) \
{ \
SNAPSHOTI_SPSC_CONTRACT(org); \
assert(snap != NULL && snap != org); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_INIT_MOVE(oplist, snap->data[i].x, org->data[i].x); \
} \
atomic_store (&snap->flags, atomic_load(&org->flags)); \
atomic_store (&org->flags, SNAPSHOTI_SPSC_FLAG(0,0,0,0) ); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
,) /* IF_METHOD (INIT_MOVE) */ \
\
M_IF_METHOD(MOVE, oplist)( \
static inline void \
M_C(name, _move)(snapshot_t snap, \
snapshot_t org) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
SNAPSHOTI_SPSC_CONTRACT(org); \
assert(snap != org); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_MOVE(oplist, snap->data[i].x, org->data[i].x); \
} \
atomic_store (&snap->flags, atomic_load(&org->flags)); \
atomic_store (&org->flags, SNAPSHOTI_SPSC_FLAG(0,0,0,0) ); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
,) /* IF_METHOD (MOVE) */ \
\
static inline type * \
M_C(name, _write)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \
/* Atomic CAS operation */ \
do { \
/* Swap F and W buffer, setting exchange flag */ \
nextFlags = SNAPSHOTI_SPSC_FLAG(SNAPSHOTI_SPSC_R(origFlags), \
SNAPSHOTI_SPSC_F(origFlags), \
SNAPSHOTI_SPSC_W(origFlags), 1); \
/* exponential backoff is not needed as there can't be more \
than 2 threads which try to update the data. */ \
} while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \
nextFlags)); \
/* Return new write buffer for new updating */ \
return &snap->data[SNAPSHOTI_SPSC_W(nextFlags)].x; \
} \
\
static inline type const * \
M_C(name, _read)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \
/* Atomic CAS operation */ \
do { \
/* If no exchange registered, do nothing and keep the same */ \
if (!SNAPSHOTI_SPSC_B(origFlags)) { \
nextFlags = origFlags; \
break; \
} \
/* Swap R and F buffer, clearing exchange flag */ \
nextFlags = SNAPSHOTI_SPSC_FLAG(SNAPSHOTI_SPSC_F(origFlags), \
SNAPSHOTI_SPSC_W(origFlags), \
SNAPSHOTI_SPSC_R(origFlags), 0); \
/* exponential backoff is not needed as there can't be more \
than 2 threads which try to update the data. */ \
} while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \
nextFlags)); \
/* Return current read buffer */ \
return M_CONST_CAST(type, &snap->data[SNAPSHOTI_SPSC_R(nextFlags)].x); \
} \
\
/* Non const due to use of atomic_load */ \
static inline bool \
M_C(name, _updated_p)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char flags = atomic_load (&snap->flags); \
return SNAPSHOTI_SPSC_B(flags); \
} \
\
/* Non const due to use of atomic_load */ \
static inline type * \
M_C(name, _get_write_buffer)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char flags = atomic_load(&snap->flags); \
return &snap->data[SNAPSHOTI_SPSC_W(flags)].x; \
} \
\
/* Non const due to use of atomic_load */ \
static inline type const * \
M_C(name, _get_read_buffer)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char flags = atomic_load(&snap->flags); \
return M_CONST_CAST(type, &snap->data[SNAPSHOTI_SPSC_R(flags)].x); \
} \
#define SNAPSHOTI_SPSC_DEF_P3(name, type, oplist, snapshot_t) \
\
/* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _aligned_type_s) { \
type x; \
M_CACHELINE_ALIGN(align, type); \
} M_C(name, _aligned_type_ct); \
\
typedef struct M_C(name, _s) { \
M_C(name, _aligned_type_ct) data[SNAPSHOTI_SPSC_MAX_BUFFER]; \
atomic_uchar flags; \
} snapshot_t[1]; \
typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
\
/* Define internal types for oplist */ \
typedef snapshot_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(snapshot_t snap) \
{ \
assert(snap != NULL); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_INIT(oplist, snap->data[i].x); \
} \
atomic_init (&snap->flags, SNAPSHOTI_SPSC_FLAG(0, 1, 2, 0)); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
\
static inline void \
M_C(name, _clear)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_CLEAR(oplist, snap->data[i].x); \
} \
} \
\
/* const is missing for org due to use of atomic_load of org */ \
static inline void \
M_C(name, _init_set)(snapshot_t snap, snapshot_t org) \
{ \
SNAPSHOTI_SPSC_CONTRACT(org); \
assert(snap != NULL && snap != org); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_INIT_SET(oplist, snap->data[i].x, org->data[i].x); \
} \
atomic_init (&snap->flags, atomic_load(&org->flags)); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
\
/* const is missing for org due to use of atomic_load of org */ \
static inline void \
M_C(name, _set)(snapshot_t snap, snapshot_t org) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
SNAPSHOTI_SPSC_CONTRACT(org); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_SET(oplist, snap->data[i].x, org->data[i].x); \
} \
atomic_init (&snap->flags, atomic_load(&org->flags)); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
\
M_IF_METHOD(INIT_MOVE, oplist)( \
static inline void \
M_C(name, _init_move)(snapshot_t snap, snapshot_t org) \
{ \
SNAPSHOTI_SPSC_CONTRACT(org); \
assert(snap != NULL && snap != org); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_INIT_MOVE(oplist, snap->data[i].x, org->data[i].x); \
} \
atomic_store (&snap->flags, atomic_load(&org->flags)); \
atomic_store (&org->flags, SNAPSHOTI_SPSC_FLAG(0,0,0,0) ); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
,) /* IF_METHOD (INIT_MOVE) */ \
\
M_IF_METHOD(MOVE, oplist)( \
static inline void \
M_C(name, _move)(snapshot_t snap, \
snapshot_t org) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
SNAPSHOTI_SPSC_CONTRACT(org); \
assert(snap != org); \
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
M_CALL_MOVE(oplist, snap->data[i].x, org->data[i].x); \
} \
atomic_store (&snap->flags, atomic_load(&org->flags)); \
atomic_store (&org->flags, SNAPSHOTI_SPSC_FLAG(0,0,0,0) ); \
SNAPSHOTI_SPSC_CONTRACT(snap); \
} \
,) /* IF_METHOD (MOVE) */ \
\
static inline type * \
M_C(name, _write)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \
/* Atomic CAS operation */ \
do { \
/* Swap F and W buffer, setting exchange flag */ \
nextFlags = SNAPSHOTI_SPSC_FLAG(SNAPSHOTI_SPSC_R(origFlags), \
SNAPSHOTI_SPSC_F(origFlags), \
SNAPSHOTI_SPSC_W(origFlags), 1); \
/* exponential backoff is not needed as there can't be more \
than 2 threads which try to update the data. */ \
} while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \
nextFlags)); \
/* Return new write buffer for new updating */ \
return &snap->data[SNAPSHOTI_SPSC_W(nextFlags)].x; \
} \
\
static inline type const * \
M_C(name, _read)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \
/* Atomic CAS operation */ \
do { \
/* If no exchange registered, do nothing and keep the same */ \
if (!SNAPSHOTI_SPSC_B(origFlags)) { \
nextFlags = origFlags; \
break; \
} \
/* Swap R and F buffer, clearing exchange flag */ \
nextFlags = SNAPSHOTI_SPSC_FLAG(SNAPSHOTI_SPSC_F(origFlags), \
SNAPSHOTI_SPSC_W(origFlags), \
SNAPSHOTI_SPSC_R(origFlags), 0); \
/* exponential backoff is not needed as there can't be more \
than 2 threads which try to update the data. */ \
} while (!atomic_compare_exchange_weak (&snap->flags, &origFlags, \
nextFlags)); \
/* Return current read buffer */ \
return M_CONST_CAST(type, &snap->data[SNAPSHOTI_SPSC_R(nextFlags)].x); \
} \
\
/* Non const due to use of atomic_load */ \
static inline bool \
M_C(name, _updated_p)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char flags = atomic_load (&snap->flags); \
return SNAPSHOTI_SPSC_B(flags); \
} \
\
/* Non const due to use of atomic_load */ \
static inline type * \
M_C(name, _get_write_buffer)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char flags = atomic_load(&snap->flags); \
return &snap->data[SNAPSHOTI_SPSC_W(flags)].x; \
} \
\
/* Non const due to use of atomic_load */ \
static inline type const * \
M_C(name, _get_read_buffer)(snapshot_t snap) \
{ \
SNAPSHOTI_SPSC_CONTRACT(snap); \
unsigned char flags = atomic_load(&snap->flags); \
return M_CONST_CAST(type, &snap->data[SNAPSHOTI_SPSC_R(flags)].x); \
} \
@@ -376,12 +376,12 @@ typedef struct snapshot_mrsw_int_s {
} snapshot_mrsw_int_ct[1];
// can't check currentWrite due to potential data race on it
#define SNAPSHOTI_SPMC_INT_CONTRACT(s) do { \
assert (s != NULL); \
assert (s->n_reader > 0 && s->n_reader <= SNAPSHOTI_SPMC_MAX_READER); \
assert ((size_t)SNAPSHOTI_SPMC_INT_FLAG_W(atomic_load(&s->lastNext)) \
<= s->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER); \
assert (s->cptTab != NULL); \
#define SNAPSHOTI_SPMC_INT_CONTRACT(s) do { \
assert (s != NULL); \
assert (s->n_reader > 0 && s->n_reader <= SNAPSHOTI_SPMC_MAX_READER); \
assert ((size_t)SNAPSHOTI_SPMC_INT_FLAG_W(atomic_load(&s->lastNext)) \
<= s->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER); \
assert (s->cptTab != NULL); \
} while (0)
/* Initialize snapshot_mrsw_int_ct for n readers (constructor) */
@@ -595,9 +595,9 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
/* Contract of a SPMC snapshot.
Nothing notable as it can be accessed concurrently */
#define SNAPSHOTI_SPMC_CONTRACT(snap) do { \
assert (snap != NULL); \
assert (snap->data != NULL); \
#define SNAPSHOTI_SPMC_CONTRACT(snap) do { \
assert (snap != NULL); \
assert (snap->data != NULL); \
} while (0)
@@ -605,102 +605,102 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
#define SNAPSHOTI_SPMC_DEF_P1(arg) SNAPSHOTI_SPMC_DEF_P2 arg
/* Validate the oplist before going further */
#define SNAPSHOTI_SPMC_DEF_P2(name, type, oplist, snapshot_t) \
#define SNAPSHOTI_SPMC_DEF_P2(name, type, oplist, snapshot_t) \
M_IF_OPLIST(oplist)(SNAPSHOTI_SPMC_DEF_P3, SNAPSHOTI_SPMC_DEF_FAILURE)(name, type, oplist, snapshot_t)
/* Stop processing with a compilation failure */
#define SNAPSHOTI_SPMC_DEF_FAILURE(name, type, oplist, snapshot_t) \
#define SNAPSHOTI_SPMC_DEF_FAILURE(name, type, oplist, snapshot_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_SPMC_DEF): the given argument is not a valid oplist: " #oplist)
/* Expand the type and the functions of a SPMC snapshot */
#define SNAPSHOTI_SPMC_DEF_P3(name, type, oplist, snapshot_t) \
\
/* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _aligned_type_s) { \
type x; \
M_CACHELINE_ALIGN(align, type); \
} M_C(name, _aligned_type_ct); \
\
typedef struct M_C(name, _s) { \
M_C(name, _aligned_type_ct) *data; \
snapshot_mrsw_int_ct core; \
} snapshot_t[1]; \
\
/* Define internal types for oplist */ \
typedef snapshot_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(snapshot_t snap, size_t nReader) \
{ \
assert (snap != NULL); \
assert (nReader > 0 && nReader <= SNAPSHOTI_SPMC_MAX_READER); \
snap->data = M_CALL_REALLOC(oplist, M_C(name, _aligned_type_ct), \
NULL, nReader+SNAPSHOTI_SPMC_EXTRA_BUFFER); \
if (M_UNLIKELY (snap->data == NULL)) { \
M_MEMORY_FULL(sizeof(M_C(name, _aligned_type_ct)) * \
(nReader+SNAPSHOTI_SPMC_EXTRA_BUFFER)); \
return; \
} \
for(size_t i = 0; i < nReader + SNAPSHOTI_SPMC_EXTRA_BUFFER; i++) { \
M_CALL_INIT(oplist, snap->data[i].x); \
} \
snapshot_mrsw_int_init(snap->core, nReader); \
SNAPSHOTI_SPMC_CONTRACT(snap); \
} \
\
static inline void \
M_C(name, _clear)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
size_t nReader = snapshot_mrsw_int_size(snap->core); \
for(size_t i = 0; i < nReader + SNAPSHOTI_SPMC_EXTRA_BUFFER; i++) { \
M_CALL_CLEAR(oplist, snap->data[i].x); \
} \
M_CALL_FREE(oplist, snap->data); \
snapshot_mrsw_int_clear(snap->core); \
} \
\
static inline type * \
M_C(name, _write)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
const unsigned int idx = snapshot_mrsw_int_write(snap->core); \
return &snap->data[idx].x; \
} \
\
static inline type const * \
M_C(name, _read_start)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
const unsigned int idx = snapshot_mrsw_int_read_start(snap->core); \
return M_CONST_CAST(type, &snap->data[idx].x); \
} \
\
static inline void \
M_C(name, _read_end)(snapshot_t snap, type const *old) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
assert (old != NULL); \
const M_C(name, _aligned_type_ct) *oldx; \
oldx = M_CTYPE_FROM_FIELD(M_C(name, _aligned_type_ct), old, type, x); \
assert (oldx >= snap->data); \
#define SNAPSHOTI_SPMC_DEF_P3(name, type, oplist, snapshot_t) \
\
/* Create an aligned type to avoid false sharing between threads */ \
typedef struct M_C(name, _aligned_type_s) { \
type x; \
M_CACHELINE_ALIGN(align, type); \
} M_C(name, _aligned_type_ct); \
\
typedef struct M_C(name, _s) { \
M_C(name, _aligned_type_ct) *data; \
snapshot_mrsw_int_ct core; \
} snapshot_t[1]; \
\
/* Define internal types for oplist */ \
typedef snapshot_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(snapshot_t snap, size_t nReader) \
{ \
assert (snap != NULL); \
assert (nReader > 0 && nReader <= SNAPSHOTI_SPMC_MAX_READER); \
snap->data = M_CALL_REALLOC(oplist, M_C(name, _aligned_type_ct), \
NULL, nReader+SNAPSHOTI_SPMC_EXTRA_BUFFER); \
if (M_UNLIKELY (snap->data == NULL)) { \
M_MEMORY_FULL(sizeof(M_C(name, _aligned_type_ct)) * \
(nReader+SNAPSHOTI_SPMC_EXTRA_BUFFER)); \
return; \
} \
for(size_t i = 0; i < nReader + SNAPSHOTI_SPMC_EXTRA_BUFFER; i++) { \
M_CALL_INIT(oplist, snap->data[i].x); \
} \
snapshot_mrsw_int_init(snap->core, nReader); \
SNAPSHOTI_SPMC_CONTRACT(snap); \
} \
\
static inline void \
M_C(name, _clear)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
size_t nReader = snapshot_mrsw_int_size(snap->core); \
for(size_t i = 0; i < nReader + SNAPSHOTI_SPMC_EXTRA_BUFFER; i++) { \
M_CALL_CLEAR(oplist, snap->data[i].x); \
} \
M_CALL_FREE(oplist, snap->data); \
snapshot_mrsw_int_clear(snap->core); \
} \
\
static inline type * \
M_C(name, _write)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
const unsigned int idx = snapshot_mrsw_int_write(snap->core); \
return &snap->data[idx].x; \
} \
\
static inline type const * \
M_C(name, _read_start)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
const unsigned int idx = snapshot_mrsw_int_read_start(snap->core); \
return M_CONST_CAST(type, &snap->data[idx].x); \
} \
\
static inline void \
M_C(name, _read_end)(snapshot_t snap, type const *old) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
assert (old != NULL); \
const M_C(name, _aligned_type_ct) *oldx; \
oldx = M_CTYPE_FROM_FIELD(M_C(name, _aligned_type_ct), old, type, x); \
assert (oldx >= snap->data); \
assert (oldx < snap->data + snap->core->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER); \
assert(snap->core->n_reader +SNAPSHOTI_SPMC_EXTRA_BUFFER < UINT_MAX); \
const unsigned int idx = (unsigned int) (oldx - snap->data); \
snapshot_mrsw_int_read_end(snap->core, idx); \
} \
\
static inline type * \
M_C(name, _get_write_buffer)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
const unsigned int idx = snapshot_mrsw_int_get_write_idx(snap->core); \
return &snap->data[idx].x; \
} \
\
assert(snap->core->n_reader +SNAPSHOTI_SPMC_EXTRA_BUFFER < UINT_MAX); \
const unsigned int idx = (unsigned int) (oldx - snap->data); \
snapshot_mrsw_int_read_end(snap->core, idx); \
} \
\
static inline type * \
M_C(name, _get_write_buffer)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap); \
const unsigned int idx = snapshot_mrsw_int_get_write_idx(snap->core); \
return &snap->data[idx].x; \
} \
\
//FIXME: Evaluate the needs for the methods _set_, _init_set.
@@ -714,76 +714,76 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
#define SNAPSHOTI_MPMC_DEF_P1(arg) SNAPSHOTI_MPMC_DEF_P2 arg
/* Validate the oplist before going further */
#define SNAPSHOTI_MPMC_DEF_P2(name, type, oplist, snapshot_t) \
#define SNAPSHOTI_MPMC_DEF_P2(name, type, oplist, snapshot_t) \
M_IF_OPLIST(oplist)(SNAPSHOTI_MPMC_DEF_P3, SNAPSHOTI_MPMC_DEF_FAILURE)(name, type, oplist, snapshot_t)
/* Stop processing with a compilation failure */
#define SNAPSHOTI_MPMC_DEF_FAILURE(name, type, oplist, snapshot_t) \
#define SNAPSHOTI_MPMC_DEF_FAILURE(name, type, oplist, snapshot_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_MPMC_DEF): the given argument is not a valid oplist: " #oplist)
/* Expand the type and the functions of a MPMC snapshot */
#define SNAPSHOTI_MPMC_DEF_P3(name, type, oplist, snapshot_t) \
\
#define SNAPSHOTI_MPMC_DEF_P3(name, type, oplist, snapshot_t) \
\
SNAPSHOTI_SPMC_DEF_P1((M_C(name, _mrsw), type, oplist, M_C(name, _mrsw_pct))) \
\
typedef struct M_C(name, _s) { \
M_C(name, _mrsw_pct) core; \
} snapshot_t[1]; \
\
/* Define internal types for oplist */ \
typedef snapshot_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(snapshot_t snap, size_t nReader, size_t nWriter) \
{ \
M_C(name, _mrsw_init)(snap->core, nReader + nWriter -1 ); \
unsigned int idx = snap->core->core->currentWrite; \
snap->core->core->currentWrite = GENINT_ERROR; \
snapshot_mrsw_int_write_end(snap->core->core, idx); \
} \
\
static inline void \
M_C(name, _clear)(snapshot_t snap) \
{ \
M_C(name, _mrsw_clear)(snap->core); \
} \
\
static inline type * \
M_C(name, _write_start)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap->core); \
\
typedef struct M_C(name, _s) { \
M_C(name, _mrsw_pct) core; \
} snapshot_t[1]; \
\
/* Define internal types for oplist */ \
typedef snapshot_t M_C(name, _ct); \
typedef type M_C(name, _subtype_ct); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline void \
M_C(name, _init)(snapshot_t snap, size_t nReader, size_t nWriter) \
{ \
M_C(name, _mrsw_init)(snap->core, nReader + nWriter -1 ); \
unsigned int idx = snap->core->core->currentWrite; \
snap->core->core->currentWrite = GENINT_ERROR; \
snapshot_mrsw_int_write_end(snap->core->core, idx); \
} \
\
static inline void \
M_C(name, _clear)(snapshot_t snap) \
{ \
M_C(name, _mrsw_clear)(snap->core); \
} \
\
static inline type * \
M_C(name, _write_start)(snapshot_t snap) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap->core); \
const unsigned int idx = snapshot_mrsw_int_write_start(snap->core->core); \
return &snap->core->data[idx].x; \
} \
\
static inline void \
M_C(name, _write_end)(snapshot_t snap, type *old) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap->core); \
const M_C(name, _mrsw_aligned_type_ct) *oldx; \
return &snap->core->data[idx].x; \
} \
\
static inline void \
M_C(name, _write_end)(snapshot_t snap, type *old) \
{ \
SNAPSHOTI_SPMC_CONTRACT(snap->core); \
const M_C(name, _mrsw_aligned_type_ct) *oldx; \
oldx = M_CTYPE_FROM_FIELD(M_C(name, _mrsw_aligned_type_ct), old, type, x); \
assert (oldx >= snap->core->data); \
assert (oldx >= snap->core->data); \
assert (oldx < snap->core->data + snap->core->core->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER); \
assert(snap->core->core->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER < UINT_MAX); \
const unsigned int idx = (unsigned int) (oldx - snap->core->data); \
snapshot_mrsw_int_write_end(snap->core->core, idx); \
} \
\
static inline type const * \
M_C(name, _read_start)(snapshot_t snap) \
{ \
return M_C(name, _mrsw_read_start)(snap->core); \
} \
\
static inline void \
M_C(name, _read_end)(snapshot_t snap, type const *old) \
{ \
M_C(name, _mrsw_read_end)(snap->core, old); \
} \
\
const unsigned int idx = (unsigned int) (oldx - snap->core->data); \
snapshot_mrsw_int_write_end(snap->core->core, idx); \
} \
\
static inline type const * \
M_C(name, _read_start)(snapshot_t snap) \
{ \
return M_C(name, _mrsw_read_start)(snap->core); \
} \
\
static inline void \
M_C(name, _read_end)(snapshot_t snap, type const *old) \
{ \
M_C(name, _mrsw_read_end)(snap->core, old); \
} \
\
//TODO: _set_, _init_set
+460 -460
View File
File diff suppressed because it is too large. Load diff
+287 -287
View File
@@ -32,9 +32,9 @@
/* Define the tuple type and functions.
USAGE:
TUPLE_DEF2(name, [(field1, type1[, oplist1]), (field2, type2[, oplist2]), ...] ) */
#define TUPLE_DEF2(name, ...) \
M_BEGIN_PROTECTED_CODE \
TUPLEI_DEF2_P1( (name, M_C(name, _t) TUPLEI_INJECT_GLOBAL(__VA_ARGS__)) ) \
#define TUPLE_DEF2(name, ...) \
M_BEGIN_PROTECTED_CODE \
TUPLEI_DEF2_P1( (name, M_C(name, _t) TUPLEI_INJECT_GLOBAL(__VA_ARGS__)) ) \
M_END_PROTECTED_CODE
@@ -42,17 +42,17 @@
as the given name.
USAGE:
TUPLE_DEF2_AS(name, name_t, [(field1, type1[, oplist1]), (field2, type2[, oplist2]), ...] ) */
#define TUPLE_DEF2_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
TUPLEI_DEF2_P1( (name, name_t TUPLEI_INJECT_GLOBAL(__VA_ARGS__)) ) \
#define TUPLE_DEF2_AS(name, name_t, ...) \
M_BEGIN_PROTECTED_CODE \
TUPLEI_DEF2_P1( (name, name_t TUPLEI_INJECT_GLOBAL(__VA_ARGS__)) ) \
M_END_PROTECTED_CODE
/* Define the oplist of a tuple.
USAGE: TUPLE_OPLIST(name[, oplist of the first type, ...]) */
#define TUPLE_OPLIST(...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(TUPLEI_OPLIST_P1((__VA_ARGS__, M_DEFAULT_OPLIST )), \
#define TUPLE_OPLIST(...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(TUPLEI_OPLIST_P1((__VA_ARGS__, M_DEFAULT_OPLIST )), \
TUPLEI_OPLIST_P1((__VA_ARGS__ )))
@@ -202,152 +202,152 @@ namespace m_tuple {
/* Define the type of a tuple */
#define TUPLEI_DEFINE_TYPE(name, name_t, ...) \
typedef struct M_C(name, _s) { \
M_MAP(TUPLEI_DEFINE_RECUR_TYPE_ELE , __VA_ARGS__) \
} name_t[1]; \
\
typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
/* Define internal type for oplist */ \
#define TUPLEI_DEFINE_TYPE(name, name_t, ...) \
typedef struct M_C(name, _s) { \
M_MAP(TUPLEI_DEFINE_RECUR_TYPE_ELE , __VA_ARGS__) \
} name_t[1]; \
\
typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
/* Define internal type for oplist */ \
typedef name_t M_C(name, _ct);
#define TUPLEI_DEFINE_RECUR_TYPE_ELE(a) \
#define TUPLEI_DEFINE_RECUR_TYPE_ELE(a) \
TUPLEI_GET_TYPE a TUPLEI_GET_FIELD a ;
/* Define the basic enumerate, identifying a parameter */
#define TUPLEI_DEFINE_ENUM(name, ...) \
typedef enum { \
M_C(name, _first_one_val), \
M_MAP2_C(TUPLEI_DEFINE_ENUM_ELE , name, __VA_ARGS__) \
#define TUPLEI_DEFINE_ENUM(name, ...) \
typedef enum { \
M_C(name, _first_one_val), \
M_MAP2_C(TUPLEI_DEFINE_ENUM_ELE , name, __VA_ARGS__) \
} M_C(name,_field_e);
#define TUPLEI_DEFINE_ENUM_ELE(name, a) \
#define TUPLEI_DEFINE_ENUM_ELE(name, a) \
M_C4(name, _, TUPLEI_GET_FIELD a, _value)
/* Control that all given oplists of all parameters are really oplists */
#define TUPLEI_CONTROL_ALL_OPLIST(name, ...) \
#define TUPLEI_CONTROL_ALL_OPLIST(name, ...) \
M_MAP2(TUPLEI_CONTROL_OPLIST, name, __VA_ARGS__)
#define TUPLEI_CONTROL_OPLIST(name, a) \
M_CHECK_COMPATIBLE_OPLIST(name, TUPLEI_GET_FIELD a, \
#define TUPLEI_CONTROL_OPLIST(name, a) \
M_CHECK_COMPATIBLE_OPLIST(name, TUPLEI_GET_FIELD a, \
TUPLEI_GET_TYPE a, TUPLEI_GET_OPLIST a)
/* Define the INIT method calling the INIT method for all params */
#define TUPLEI_DEFINE_INIT(name, ...) \
static inline void M_C(name, _init)(M_C(name,_ct) my) { \
M_MAP(TUPLEI_DEFINE_INIT_FUNC , __VA_ARGS__) \
#define TUPLEI_DEFINE_INIT(name, ...) \
static inline void M_C(name, _init)(M_C(name,_ct) my) { \
M_MAP(TUPLEI_DEFINE_INIT_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_INIT_FUNC(a) \
#define TUPLEI_DEFINE_INIT_FUNC(a) \
TUPLEI_CALL_INIT(a, my -> TUPLEI_GET_FIELD a );
/* Define the INIT_SET method calling the INIT_SET method for all params */
#define TUPLEI_DEFINE_INIT_SET(name, ...) \
#define TUPLEI_DEFINE_INIT_SET(name, ...) \
static inline void M_C(name, _init_set)(M_C(name,_ct) my , M_C(name,_ct) const org) { \
TUPLEI_CONTRACT(org); \
M_MAP(TUPLEI_DEFINE_INIT_SET_FUNC , __VA_ARGS__) \
TUPLEI_CONTRACT(org); \
M_MAP(TUPLEI_DEFINE_INIT_SET_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_INIT_SET_FUNC(a) \
#define TUPLEI_DEFINE_INIT_SET_FUNC(a) \
TUPLEI_CALL_INIT_SET(a, my -> TUPLEI_GET_FIELD a , org -> TUPLEI_GET_FIELD a );
/* Define the INIT_WITH method calling the INIT_SET method for all params. */
/* FIXME: To rename? */
#define TUPLEI_DEFINE_INIT_SET2(name, ...) \
static inline void M_C(name, _init_set2)(M_C(name,_ct) my \
M_MAP(TUPLEI_DEFINE_INIT_SET2_PROTO, __VA_ARGS__) \
) { \
M_MAP(TUPLEI_DEFINE_INIT_SET2_FUNC , __VA_ARGS__) \
#define TUPLEI_DEFINE_INIT_SET2(name, ...) \
static inline void M_C(name, _init_set2)(M_C(name,_ct) my \
M_MAP(TUPLEI_DEFINE_INIT_SET2_PROTO, __VA_ARGS__) \
) { \
M_MAP(TUPLEI_DEFINE_INIT_SET2_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_INIT_SET2_PROTO(a) \
#define TUPLEI_DEFINE_INIT_SET2_PROTO(a) \
, TUPLEI_GET_TYPE a const TUPLEI_GET_FIELD a
#define TUPLEI_DEFINE_INIT_SET2_FUNC(a) \
#define TUPLEI_DEFINE_INIT_SET2_FUNC(a) \
TUPLEI_CALL_INIT_SET(a, my -> TUPLEI_GET_FIELD a , TUPLEI_GET_FIELD a );
/* Define the SET method calling the SET method for all params. */
#define TUPLEI_DEFINE_SET(name, ...) \
static inline void M_C(name, _set)(M_C(name,_ct) my , \
M_C(name,_ct) const org) { \
TUPLEI_CONTRACT(my); \
TUPLEI_CONTRACT(org); \
M_MAP(TUPLEI_DEFINE_SET_FUNC , __VA_ARGS__) \
#define TUPLEI_DEFINE_SET(name, ...) \
static inline void M_C(name, _set)(M_C(name,_ct) my , \
M_C(name,_ct) const org) { \
TUPLEI_CONTRACT(my); \
TUPLEI_CONTRACT(org); \
M_MAP(TUPLEI_DEFINE_SET_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_SET_FUNC(a) \
#define TUPLEI_DEFINE_SET_FUNC(a) \
TUPLEI_CALL_SET(a, my -> TUPLEI_GET_FIELD a , org -> TUPLEI_GET_FIELD a );
/* Define the SET_WITH method calling the SET method for all params. */
/* FIXME: To rename? */
#define TUPLEI_DEFINE_SET2(name, ...) \
static inline void M_C(name, _set2)(M_C(name,_ct) my \
M_MAP(TUPLEI_DEFINE_SET2_PROTO, __VA_ARGS__) \
) { \
TUPLEI_CONTRACT(my); \
M_MAP(TUPLEI_DEFINE_SET2_FUNC , __VA_ARGS__) \
#define TUPLEI_DEFINE_SET2(name, ...) \
static inline void M_C(name, _set2)(M_C(name,_ct) my \
M_MAP(TUPLEI_DEFINE_SET2_PROTO, __VA_ARGS__) \
) { \
TUPLEI_CONTRACT(my); \
M_MAP(TUPLEI_DEFINE_SET2_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_SET2_PROTO(a) \
#define TUPLEI_DEFINE_SET2_PROTO(a) \
, TUPLEI_GET_TYPE a const TUPLEI_GET_FIELD a
#define TUPLEI_DEFINE_SET2_FUNC(a) \
#define TUPLEI_DEFINE_SET2_FUNC(a) \
TUPLEI_CALL_SET(a, my -> TUPLEI_GET_FIELD a , TUPLEI_GET_FIELD a );
/* Define the CLEAR method calling the CLEAR method for all params. */
#define TUPLEI_DEFINE_CLEAR(name, ...) \
static inline void M_C(name, _clear)(M_C(name,_ct) my) { \
TUPLEI_CONTRACT(my); \
M_MAP(TUPLEI_DEFINE_CLEAR_FUNC , __VA_ARGS__) \
#define TUPLEI_DEFINE_CLEAR(name, ...) \
static inline void M_C(name, _clear)(M_C(name,_ct) my) { \
TUPLEI_CONTRACT(my); \
M_MAP(TUPLEI_DEFINE_CLEAR_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_CLEAR_FUNC(a) \
#define TUPLEI_DEFINE_CLEAR_FUNC(a) \
TUPLEI_CALL_CLEAR(a, my -> TUPLEI_GET_FIELD a );
/* Define the GET_AT_field & CGET_AT methods for all params. */
#define TUPLEI_DEFINE_GETTER_FIELD(name, ...) \
#define TUPLEI_DEFINE_GETTER_FIELD(name, ...) \
M_MAP2(TUPLEI_DEFINE_GETTER_FIELD_PROTO, name, __VA_ARGS__)
#define TUPLEI_DEFINE_GETTER_FIELD_PROTO(name, a) \
static inline TUPLEI_GET_TYPE a * M_C3(name, _get_at_, TUPLEI_GET_FIELD a) \
(M_C(name,_ct) my) { \
TUPLEI_CONTRACT(my); \
return &(my->TUPLEI_GET_FIELD a); \
} \
#define TUPLEI_DEFINE_GETTER_FIELD_PROTO(name, a) \
static inline TUPLEI_GET_TYPE a * M_C3(name, _get_at_, TUPLEI_GET_FIELD a) \
(M_C(name,_ct) my) { \
TUPLEI_CONTRACT(my); \
return &(my->TUPLEI_GET_FIELD a); \
} \
static inline TUPLEI_GET_TYPE a const * M_C3(name, _cget_at_, TUPLEI_GET_FIELD a) \
(M_C(name,_ct) const my) { \
TUPLEI_CONTRACT(my); \
return &(my->TUPLEI_GET_FIELD a); \
(M_C(name,_ct) const my) { \
TUPLEI_CONTRACT(my); \
return &(my->TUPLEI_GET_FIELD a); \
}
/* Define the SET_field methods for all params. */
#define TUPLEI_DEFINE_SETTER_FIELD(name, ...) \
#define TUPLEI_DEFINE_SETTER_FIELD(name, ...) \
M_MAP2(TUPLEI_DEFINE_SETTER_FIELD_PROTO, name, __VA_ARGS__)
#define TUPLEI_DEFINE_SETTER_FIELD_PROTO(name, a) \
static inline void M_C3(name, _set_, TUPLEI_GET_FIELD a) \
(M_C(name,_ct) my, TUPLEI_GET_TYPE a const TUPLEI_GET_FIELD a) { \
TUPLEI_CONTRACT(my); \
TUPLEI_CALL_SET(a, my ->TUPLEI_GET_FIELD a, TUPLEI_GET_FIELD a); \
#define TUPLEI_DEFINE_SETTER_FIELD_PROTO(name, a) \
static inline void M_C3(name, _set_, TUPLEI_GET_FIELD a) \
(M_C(name,_ct) my, TUPLEI_GET_TYPE a const TUPLEI_GET_FIELD a) { \
TUPLEI_CONTRACT(my); \
TUPLEI_CALL_SET(a, my ->TUPLEI_GET_FIELD a, TUPLEI_GET_FIELD a); \
}
/* Define the CMP method by calling CMP methods for all params. */
#define TUPLEI_DEFINE_CMP(name, ...) \
static inline int M_C(name, _cmp)(M_C(name,_ct) const e1 , \
M_C(name,_ct) const e2) { \
int i; \
TUPLEI_CONTRACT(e1); \
TUPLEI_CONTRACT(e2); \
M_MAP(TUPLEI_DEFINE_CMP_FUNC , __VA_ARGS__) \
return 0; \
#define TUPLEI_DEFINE_CMP(name, ...) \
static inline int M_C(name, _cmp)(M_C(name,_ct) const e1 , \
M_C(name,_ct) const e2) { \
int i; \
TUPLEI_CONTRACT(e1); \
TUPLEI_CONTRACT(e2); \
M_MAP(TUPLEI_DEFINE_CMP_FUNC , __VA_ARGS__) \
return 0; \
}
#define TUPLEI_DEFINE_CMP_FUNC(a) \
#define TUPLEI_DEFINE_CMP_FUNC(a) \
i = TUPLEI_CALL_CMP(a, e1 -> TUPLEI_GET_FIELD a , e2 -> TUPLEI_GET_FIELD a ); \
if (i != 0) return i;
@@ -356,321 +356,321 @@ namespace m_tuple {
In the right order
FIXME: _cmp_order is not supported by algorithm yet.
*/
#define TUPLEI_DEFINE_CMP_ORDER(name, ...) \
static inline int M_C(name, _cmp_order)(M_C(name,_ct) const e1 , \
M_C(name,_ct) const e2, \
const int order[]) { \
int i, r; \
TUPLEI_CONTRACT(e1); \
TUPLEI_CONTRACT(e2); \
while (true) { \
i=*order++; \
switch (i) { \
case 0: return 0; \
M_MAP2(TUPLEI_DEFINE_CMP_ORDER_FUNC , name, __VA_ARGS__) \
default: assert(0); \
} \
} \
#define TUPLEI_DEFINE_CMP_ORDER(name, ...) \
static inline int M_C(name, _cmp_order)(M_C(name,_ct) const e1 , \
M_C(name,_ct) const e2, \
const int order[]) { \
int i, r; \
TUPLEI_CONTRACT(e1); \
TUPLEI_CONTRACT(e2); \
while (true) { \
i=*order++; \
switch (i) { \
case 0: return 0; \
M_MAP2(TUPLEI_DEFINE_CMP_ORDER_FUNC , name, __VA_ARGS__) \
default: assert(0); \
} \
} \
}
#define TUPLEI_DEFINE_CMP_ORDER_FUNC(name, a) \
case M_C4(name, _, TUPLEI_GET_FIELD a, _value): \
case -M_C4(name, _, TUPLEI_GET_FIELD a, _value): \
#define TUPLEI_DEFINE_CMP_ORDER_FUNC(name, a) \
case M_C4(name, _, TUPLEI_GET_FIELD a, _value): \
case -M_C4(name, _, TUPLEI_GET_FIELD a, _value): \
r = TUPLEI_CALL_CMP(a, e1 -> TUPLEI_GET_FIELD a , e2 -> TUPLEI_GET_FIELD a ); \
if (r != 0) return i < 0 ? -r : r; \
if (r != 0) return i < 0 ? -r : r; \
break;
/* Define a CMP_field method for all given params that export a CMP method */
#define TUPLEI_DEFINE_CMP_FIELD(name, ...) \
#define TUPLEI_DEFINE_CMP_FIELD(name, ...) \
M_MAP2(TUPLEI_MAP_CMP_FIELD, name, __VA_ARGS__)
#define TUPLEI_MAP_CMP_FIELD(name, a) \
M_IF_METHOD(CMP, TUPLEI_GET_OPLIST a)( \
#define TUPLEI_MAP_CMP_FIELD(name, a) \
M_IF_METHOD(CMP, TUPLEI_GET_OPLIST a)( \
TUPLEI_DEFINE_CMP_FIELD_FUNC(name, TUPLEI_GET_FIELD a, TUPLEI_GET_CMP a), \
)
#define TUPLEI_DEFINE_CMP_FIELD_FUNC(name, field, func_cmp) \
static inline int M_C3(name, _cmp_, field)(M_C(name,_ct) const e1 , \
M_C(name,_ct) const e2) { \
TUPLEI_CONTRACT(e1); \
TUPLEI_CONTRACT(e2); \
return func_cmp ( e1 -> field , e2 -> field ); \
#define TUPLEI_DEFINE_CMP_FIELD_FUNC(name, field, func_cmp) \
static inline int M_C3(name, _cmp_, field)(M_C(name,_ct) const e1 , \
M_C(name,_ct) const e2) { \
TUPLEI_CONTRACT(e1); \
TUPLEI_CONTRACT(e2); \
return func_cmp ( e1 -> field , e2 -> field ); \
}
/* Define a EQUAL method by calling the EQUAL methods for all params */
#define TUPLEI_DEFINE_EQUAL(name, ...) \
static inline bool M_C(name, _equal_p)(M_C(name,_ct) const e1 , \
M_C(name,_ct) const e2) { \
bool b; \
TUPLEI_CONTRACT(e1); \
TUPLEI_CONTRACT(e2); \
M_MAP(TUPLEI_DEFINE_EQUAL_FUNC , __VA_ARGS__) \
return true; \
#define TUPLEI_DEFINE_EQUAL(name, ...) \
static inline bool M_C(name, _equal_p)(M_C(name,_ct) const e1 , \
M_C(name,_ct) const e2) { \
bool b; \
TUPLEI_CONTRACT(e1); \
TUPLEI_CONTRACT(e2); \
M_MAP(TUPLEI_DEFINE_EQUAL_FUNC , __VA_ARGS__) \
return true; \
}
#define TUPLEI_DEFINE_EQUAL_FUNC(a) \
#define TUPLEI_DEFINE_EQUAL_FUNC(a) \
b = TUPLEI_CALL_EQUAL(a, e1 -> TUPLEI_GET_FIELD a , e2 -> TUPLEI_GET_FIELD a ); \
if (!b) return false;
/* Define a HASH method by calling the HASH methods for all params */
#define TUPLEI_DEFINE_HASH(name, ...) \
static inline size_t M_C(name, _hash)(M_C(name,_ct) const e1) { \
TUPLEI_CONTRACT(e1); \
M_HASH_DECL(hash); \
M_MAP(TUPLEI_DEFINE_HASH_FUNC , __VA_ARGS__) \
return M_HASH_FINAL (hash); \
#define TUPLEI_DEFINE_HASH(name, ...) \
static inline size_t M_C(name, _hash)(M_C(name,_ct) const e1) { \
TUPLEI_CONTRACT(e1); \
M_HASH_DECL(hash); \
M_MAP(TUPLEI_DEFINE_HASH_FUNC , __VA_ARGS__) \
return M_HASH_FINAL (hash); \
}
#define TUPLEI_DEFINE_HASH_FUNC(a) \
#define TUPLEI_DEFINE_HASH_FUNC(a) \
M_HASH_UP(hash, TUPLEI_CALL_HASH(a, e1 -> TUPLEI_GET_FIELD a) );
/* Define a GET_STR method by calling the GET_STR methods for all params */
#define TUPLEI_DEFINE_GET_STR(name, ...) \
static inline void M_C(name, _get_str)(string_t str, \
M_C(name,_ct) const el, \
bool append) { \
bool comma = false; \
TUPLEI_CONTRACT(el); \
assert (str != NULL); \
(append ? string_cat_str : string_set_str) (str, "("); \
M_MAP(TUPLEI_DEFINE_GET_STR_FUNC , __VA_ARGS__) \
string_push_back (str, ')'); \
#define TUPLEI_DEFINE_GET_STR(name, ...) \
static inline void M_C(name, _get_str)(string_t str, \
M_C(name,_ct) const el, \
bool append) { \
bool comma = false; \
TUPLEI_CONTRACT(el); \
assert (str != NULL); \
(append ? string_cat_str : string_set_str) (str, "("); \
M_MAP(TUPLEI_DEFINE_GET_STR_FUNC , __VA_ARGS__) \
string_push_back (str, ')'); \
}
#define TUPLEI_DEFINE_GET_STR_FUNC(a) \
if (comma) string_push_back (str, ','); \
comma = true; \
TUPLEI_CALL_GET_STR(a, str, el -> TUPLEI_GET_FIELD a, true); \
#define TUPLEI_DEFINE_GET_STR_FUNC(a) \
if (comma) string_push_back (str, ','); \
comma = true; \
TUPLEI_CALL_GET_STR(a, str, el -> TUPLEI_GET_FIELD a, true); \
/* Define a OUT_STR method by calling the OUT_STR methods for all params */
#define TUPLEI_DEFINE_OUT_STR(name, ...) \
static inline void M_C(name, _out_str)(FILE *f, \
M_C(name,_ct) const el) { \
bool comma = false; \
TUPLEI_CONTRACT(el); \
assert (f != NULL); \
fputc('(', f); \
M_MAP(TUPLEI_DEFINE_OUT_STR_FUNC , __VA_ARGS__) \
fputc (')', f); \
#define TUPLEI_DEFINE_OUT_STR(name, ...) \
static inline void M_C(name, _out_str)(FILE *f, \
M_C(name,_ct) const el) { \
bool comma = false; \
TUPLEI_CONTRACT(el); \
assert (f != NULL); \
fputc('(', f); \
M_MAP(TUPLEI_DEFINE_OUT_STR_FUNC , __VA_ARGS__) \
fputc (')', f); \
}
#define TUPLEI_DEFINE_OUT_STR_FUNC(a) \
if (comma) fputc (',', f); \
comma = true; \
TUPLEI_CALL_OUT_STR(a, f, el -> TUPLEI_GET_FIELD a); \
#define TUPLEI_DEFINE_OUT_STR_FUNC(a) \
if (comma) fputc (',', f); \
comma = true; \
TUPLEI_CALL_OUT_STR(a, f, el -> TUPLEI_GET_FIELD a); \
/* Define a IN_STR method by calling the IN_STR methods for all params */
#define TUPLEI_DEFINE_IN_STR(name, ...) \
static inline bool M_C(name, _in_str)(M_C(name,_ct) el, FILE *f) { \
bool comma = false; \
TUPLEI_CONTRACT(el); \
assert (f != NULL); \
int c = fgetc(f); \
if (c != '(') return false; \
M_MAP(TUPLEI_DEFINE_IN_STR_FUNC , __VA_ARGS__) \
c = fgetc(f); \
return (c == ')'); \
#define TUPLEI_DEFINE_IN_STR(name, ...) \
static inline bool M_C(name, _in_str)(M_C(name,_ct) el, FILE *f) { \
bool comma = false; \
TUPLEI_CONTRACT(el); \
assert (f != NULL); \
int c = fgetc(f); \
if (c != '(') return false; \
M_MAP(TUPLEI_DEFINE_IN_STR_FUNC , __VA_ARGS__) \
c = fgetc(f); \
return (c == ')'); \
}
#define TUPLEI_DEFINE_IN_STR_FUNC(a) \
if (comma) { \
c = fgetc (f); \
if (c != ',' || c == EOF) return false; \
} \
comma = true; \
if (TUPLEI_CALL_IN_STR(a, el -> TUPLEI_GET_FIELD a, f) == false) \
return false ; \
#define TUPLEI_DEFINE_IN_STR_FUNC(a) \
if (comma) { \
c = fgetc (f); \
if (c != ',' || c == EOF) return false; \
} \
comma = true; \
if (TUPLEI_CALL_IN_STR(a, el -> TUPLEI_GET_FIELD a, f) == false) \
return false ; \
/* Define a PARSE_STR method by calling the PARSE_STR methods for all params */
#define TUPLEI_DEFINE_PARSE_STR(name, ...) \
static inline bool M_C(name, _parse_str)(M_C(name,_ct) el, \
const char str[], \
const char **endptr) { \
TUPLEI_CONTRACT(el); \
assert (str != NULL); \
bool success = false; \
bool comma = false; \
int c = *str++; \
if (c != '(') goto exit; \
M_MAP(TUPLEI_DEFINE_PARSE_STR_FUNC , __VA_ARGS__) \
c = *str++; \
success = (c == ')'); \
exit: \
if (endptr) *endptr = str; \
return success; \
#define TUPLEI_DEFINE_PARSE_STR(name, ...) \
static inline bool M_C(name, _parse_str)(M_C(name,_ct) el, \
const char str[], \
const char **endptr) { \
TUPLEI_CONTRACT(el); \
assert (str != NULL); \
bool success = false; \
bool comma = false; \
int c = *str++; \
if (c != '(') goto exit; \
M_MAP(TUPLEI_DEFINE_PARSE_STR_FUNC , __VA_ARGS__) \
c = *str++; \
success = (c == ')'); \
exit: \
if (endptr) *endptr = str; \
return success; \
}
#define TUPLEI_DEFINE_PARSE_STR_FUNC(a) \
if (comma) { \
c = *str++; \
if (c != ',' || c == 0) goto exit; \
} \
comma = true; \
#define TUPLEI_DEFINE_PARSE_STR_FUNC(a) \
if (comma) { \
c = *str++; \
if (c != ',' || c == 0) goto exit; \
} \
comma = true; \
if (TUPLEI_CALL_PARSE_STR(a, el -> TUPLEI_GET_FIELD a, str, &str) == false) \
goto exit ; \
goto exit ; \
/* Return the parameter name as a C string */
#define TUPLEI_STRINGIFY_NAME(a) \
#define TUPLEI_STRINGIFY_NAME(a) \
M_APPLY(M_AS_STR, TUPLEI_GET_FIELD a)
/* Define a OUT_SERIAL method by calling the OUT_SERIAL methods for all params */
#define TUPLEI_DEFINE_OUT_SERIAL(name, ...) \
static inline m_serial_return_code_t \
M_C(name, _out_serial)(m_serial_write_t f, \
M_C(name,_ct) const el) { \
TUPLEI_CONTRACT(el); \
assert (f != NULL && f->m_interface != NULL); \
const int field_max = M_NARGS(__VA_ARGS__); \
/* Define a constant static table of all fields names */ \
static const char *const field_name[] = \
{ M_REDUCE(TUPLEI_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
int index = 0; \
m_serial_local_t local; \
m_serial_return_code_t ret; \
ret = f->m_interface->write_tuple_start(local, f); \
M_MAP(TUPLEI_DEFINE_OUT_SERIAL_FUNC , __VA_ARGS__) \
assert( index == field_max); \
ret |= f->m_interface->write_tuple_end(local, f); \
return ret & M_SERIAL_FAIL; \
#define TUPLEI_DEFINE_OUT_SERIAL(name, ...) \
static inline m_serial_return_code_t \
M_C(name, _out_serial)(m_serial_write_t f, \
M_C(name,_ct) const el) { \
TUPLEI_CONTRACT(el); \
assert (f != NULL && f->m_interface != NULL); \
const int field_max = M_NARGS(__VA_ARGS__); \
/* Define a constant static table of all fields names */ \
static const char *const field_name[] = \
{ M_REDUCE(TUPLEI_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
int index = 0; \
m_serial_local_t local; \
m_serial_return_code_t ret; \
ret = f->m_interface->write_tuple_start(local, f); \
M_MAP(TUPLEI_DEFINE_OUT_SERIAL_FUNC , __VA_ARGS__) \
assert( index == field_max); \
ret |= f->m_interface->write_tuple_end(local, f); \
return ret & M_SERIAL_FAIL; \
}
#define TUPLEI_DEFINE_OUT_SERIAL_FUNC(a) \
f->m_interface->write_tuple_id(local, f, field_name, field_max, index); \
TUPLEI_CALL_OUT_SERIAL(a, f, el -> TUPLEI_GET_FIELD a); \
index++; \
#define TUPLEI_DEFINE_OUT_SERIAL_FUNC(a) \
f->m_interface->write_tuple_id(local, f, field_name, field_max, index); \
TUPLEI_CALL_OUT_SERIAL(a, f, el -> TUPLEI_GET_FIELD a); \
index++; \
/* Define a IN_SERIAL method by calling the IN_SERIAL methods for all params */
#define TUPLEI_DEFINE_IN_SERIAL(name, ...) \
static inline m_serial_return_code_t \
M_C(name, _in_serial)(M_C(name,_ct) el, m_serial_read_t f) { \
TUPLEI_CONTRACT(el); \
assert (f != NULL && f->m_interface != NULL); \
int index = -1; \
const int field_max = M_NARGS(__VA_ARGS__); \
static const char *const field_name[] = \
{ M_REDUCE(TUPLEI_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
m_serial_local_t local; \
m_serial_return_code_t ret; \
ret = f->m_interface->read_tuple_start(local, f); \
while (ret == M_SERIAL_OK_CONTINUE) { \
#define TUPLEI_DEFINE_IN_SERIAL(name, ...) \
static inline m_serial_return_code_t \
M_C(name, _in_serial)(M_C(name,_ct) el, m_serial_read_t f) { \
TUPLEI_CONTRACT(el); \
assert (f != NULL && f->m_interface != NULL); \
int index = -1; \
const int field_max = M_NARGS(__VA_ARGS__); \
static const char *const field_name[] = \
{ M_REDUCE(TUPLEI_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
m_serial_local_t local; \
m_serial_return_code_t ret; \
ret = f->m_interface->read_tuple_start(local, f); \
while (ret == M_SERIAL_OK_CONTINUE) { \
ret = f->m_interface->read_tuple_id(local, f, field_name, field_max, &index); \
if (ret == M_SERIAL_OK_CONTINUE) { \
assert (index >= 0 && index < field_max); \
switch (1+index) { \
M_MAP2(TUPLEI_DEFINE_IN_SERIAL_FUNC , name, __VA_ARGS__) \
default: assert(0); \
} \
if (ret == M_SERIAL_OK_CONTINUE) { \
assert (index >= 0 && index < field_max); \
switch (1+index) { \
M_MAP2(TUPLEI_DEFINE_IN_SERIAL_FUNC , name, __VA_ARGS__) \
default: assert(0); \
} \
ret = (ret == M_SERIAL_OK_DONE) ? M_SERIAL_OK_CONTINUE : M_SERIAL_FAIL; \
} \
} \
return ret; \
} \
} \
return ret; \
}
#define TUPLEI_DEFINE_IN_SERIAL_FUNC(name, a) \
case M_C4(name, _, TUPLEI_GET_FIELD a, _value): \
ret = TUPLEI_CALL_IN_SERIAL(a, el -> TUPLEI_GET_FIELD a, f); \
break; \
#define TUPLEI_DEFINE_IN_SERIAL_FUNC(name, a) \
case M_C4(name, _, TUPLEI_GET_FIELD a, _value): \
ret = TUPLEI_CALL_IN_SERIAL(a, el -> TUPLEI_GET_FIELD a, f); \
break; \
/* Define a INIT_MOVE method by calling the INIT_MOVE methods for all params */
#define TUPLEI_DEFINE_INIT_MOVE(name, ...) \
#define TUPLEI_DEFINE_INIT_MOVE(name, ...) \
static inline void M_C(name, _init_move)(M_C(name,_ct) el, M_C(name,_ct) org) { \
TUPLEI_CONTRACT(el); \
M_MAP(TUPLEI_DEFINE_INIT_MOVE_FUNC , __VA_ARGS__) \
TUPLEI_CONTRACT(el); \
M_MAP(TUPLEI_DEFINE_INIT_MOVE_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_INIT_MOVE_FUNC(a) \
#define TUPLEI_DEFINE_INIT_MOVE_FUNC(a) \
TUPLEI_CALL_INIT_MOVE(a, el -> TUPLEI_GET_FIELD a, org -> TUPLEI_GET_FIELD a);
/* Define a MOVE method by calling the MOVE methods for all params */
#define TUPLEI_DEFINE_MOVE(name, ...) \
static inline void M_C(name, _move)(M_C(name,_ct) el, M_C(name,_ct) org) { \
TUPLEI_CONTRACT(el); \
M_MAP(TUPLEI_DEFINE_MOVE_FUNC , __VA_ARGS__) \
#define TUPLEI_DEFINE_MOVE(name, ...) \
static inline void M_C(name, _move)(M_C(name,_ct) el, M_C(name,_ct) org) { \
TUPLEI_CONTRACT(el); \
M_MAP(TUPLEI_DEFINE_MOVE_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_MOVE_FUNC(a) \
#define TUPLEI_DEFINE_MOVE_FUNC(a) \
TUPLEI_CALL_MOVE(a, el -> TUPLEI_GET_FIELD a, org -> TUPLEI_GET_FIELD a);
/* Define a SWAP method by calling the SWAP methods for all params */
#define TUPLEI_DEFINE_SWAP(name, ...) \
#define TUPLEI_DEFINE_SWAP(name, ...) \
static inline void M_C(name, _swap)(M_C(name,_ct) el1, M_C(name,_ct) el2) { \
TUPLEI_CONTRACT(el1); \
TUPLEI_CONTRACT(el2); \
M_MAP(TUPLEI_DEFINE_SWAP_FUNC , __VA_ARGS__) \
TUPLEI_CONTRACT(el1); \
TUPLEI_CONTRACT(el2); \
M_MAP(TUPLEI_DEFINE_SWAP_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_SWAP_FUNC(a) \
#define TUPLEI_DEFINE_SWAP_FUNC(a) \
TUPLEI_CALL_SWAP(a, el1 -> TUPLEI_GET_FIELD a, el2 -> TUPLEI_GET_FIELD a);
/* Define a CLEAN method by calling the CLEAN methods for all params */
#define TUPLEI_DEFINE_CLEAN(name, ...) \
static inline void M_C(name, _clean)(M_C(name,_ct) el1) { \
TUPLEI_CONTRACT(el1); \
M_MAP(TUPLEI_DEFINE_CLEAN_FUNC , __VA_ARGS__) \
#define TUPLEI_DEFINE_CLEAN(name, ...) \
static inline void M_C(name, _clean)(M_C(name,_ct) el1) { \
TUPLEI_CONTRACT(el1); \
M_MAP(TUPLEI_DEFINE_CLEAN_FUNC , __VA_ARGS__) \
}
#define TUPLEI_DEFINE_CLEAN_FUNC(a) \
#define TUPLEI_DEFINE_CLEAN_FUNC(a) \
TUPLEI_CALL_CLEAN(a, el1 -> TUPLEI_GET_FIELD a);
/* Macros for testing for the presence of a method in the parameter (name, type, oplist) */
#define TUPLEI_TEST_METHOD_P(method, trio) \
#define TUPLEI_TEST_METHOD_P(method, trio) \
M_APPLY(TUPLEI_TEST_METHOD2_P, method, M_OPFLAT trio)
#define TUPLEI_TEST_METHOD2_P(method, f, t, op) \
#define TUPLEI_TEST_METHOD2_P(method, f, t, op) \
M_TEST_METHOD_P(method, op)
/* Macros for testing for the presence of a method in all the params */
#define TUPLEI_IF_ALL(method, ...) \
#define TUPLEI_IF_ALL(method, ...) \
M_IF(M_REDUCE2(TUPLEI_TEST_METHOD_P, M_AND, method, __VA_ARGS__))
// deferred evaluation
#define TUPLEI_OPLIST_P1(arg) TUPLEI_OPLIST_P2 arg
/* Validate the oplist before going further */
#define TUPLEI_OPLIST_P2(name, ...) \
#define TUPLEI_OPLIST_P2(name, ...) \
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(TUPLEI_OPLIST_P3, TUPLEI_OPLIST_FAILURE)(name, __VA_ARGS__)
/* Prepare a clean compilation failure */
#define TUPLEI_OPLIST_FAILURE(name, ...) \
#define TUPLEI_OPLIST_FAILURE(name, ...) \
((M_LIB_ERROR(ONE_ARGUMENT_OF_TUPLEI_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__)))
/* Define the TUPLE oplist */
#define TUPLEI_OPLIST_P3(name, ...) \
(M_IF_METHOD_ALL(INIT, __VA_ARGS__)(INIT(M_C(name,_init)),), \
INIT_SET(M_C(name, _init_set)), \
INIT_WITH(M_C(name, _init_set2)), \
SET(M_C(name,_set)), \
CLEAR(M_C(name, _clear)), \
TYPE(M_C(name,_ct)), \
M_IF_METHOD_ALL(CMP, __VA_ARGS__)(CMP(M_C(name, _cmp)),), \
M_IF_METHOD_ALL(HASH, __VA_ARGS__)(HASH(M_C(name, _hash)),), \
M_IF_METHOD_ALL(EQUAL, __VA_ARGS__)(EQUAL(M_C(name, _equal_p)),), \
M_IF_METHOD_ALL(GET_STR, __VA_ARGS__)(GET_STR(M_C(name, _get_str)),), \
#define TUPLEI_OPLIST_P3(name, ...) \
(M_IF_METHOD_ALL(INIT, __VA_ARGS__)(INIT(M_C(name,_init)),), \
INIT_SET(M_C(name, _init_set)), \
INIT_WITH(M_C(name, _init_set2)), \
SET(M_C(name,_set)), \
CLEAR(M_C(name, _clear)), \
TYPE(M_C(name,_ct)), \
M_IF_METHOD_ALL(CMP, __VA_ARGS__)(CMP(M_C(name, _cmp)),), \
M_IF_METHOD_ALL(HASH, __VA_ARGS__)(HASH(M_C(name, _hash)),), \
M_IF_METHOD_ALL(EQUAL, __VA_ARGS__)(EQUAL(M_C(name, _equal_p)),), \
M_IF_METHOD_ALL(GET_STR, __VA_ARGS__)(GET_STR(M_C(name, _get_str)),), \
M_IF_METHOD_ALL(PARSE_STR, __VA_ARGS__)(PARSE_STR(M_C(name, _parse_str)),), \
M_IF_METHOD_ALL(IN_STR, __VA_ARGS__)(IN_STR(M_C(name, _in_str)),), \
M_IF_METHOD_ALL(OUT_STR, __VA_ARGS__)(OUT_STR(M_C(name, _out_str)),), \
M_IF_METHOD_ALL(IN_STR, __VA_ARGS__)(IN_STR(M_C(name, _in_str)),), \
M_IF_METHOD_ALL(OUT_STR, __VA_ARGS__)(OUT_STR(M_C(name, _out_str)),), \
M_IF_METHOD_ALL(IN_SERIAL, __VA_ARGS__)(IN_SERIAL(M_C(name, _in_serial)),), \
M_IF_METHOD_ALL(OUT_SERIAL, __VA_ARGS__)(OUT_SERIAL(M_C(name, _out_serial)),), \
M_IF_METHOD_ALL(INIT_MOVE, __VA_ARGS__)(INIT_MOVE(M_C(name, _init_move)),), \
M_IF_METHOD_ALL(MOVE, __VA_ARGS__)(MOVE(M_C(name, _move)),), \
M_IF_METHOD_ALL(SWAP, __VA_ARGS__)(SWAP(M_C(name, _swap)),), \
M_IF_METHOD_ALL(CLEAN, __VA_ARGS__)(CLEAN(M_C(name, _clean)),), \
M_IF_METHOD_ALL(MOVE, __VA_ARGS__)(MOVE(M_C(name, _move)),), \
M_IF_METHOD_ALL(SWAP, __VA_ARGS__)(SWAP(M_C(name, _swap)),), \
M_IF_METHOD_ALL(CLEAN, __VA_ARGS__)(CLEAN(M_C(name, _clean)),), \
M_IF_METHOD(NEW, M_RET_ARG1(__VA_ARGS__,))(NEW(M_DELAY2(M_GET_NEW) M_RET_ARG1(__VA_ARGS__,)),), \
M_IF_METHOD(REALLOC, M_RET_ARG1(__VA_ARGS__,))(REALLOC(M_DELAY2(M_GET_REALLOC) M_RET_ARG1(__VA_ARGS__,)),), \
M_IF_METHOD(DEL, M_RET_ARG1(__VA_ARGS__,))(DEL(M_DELAY2(M_GET_DEL) M_RET_ARG1(__VA_ARGS__,)),), \
+468 -468
View File
File diff suppressed because it is too large. Load diff
+46 -46
View File
@@ -43,8 +43,8 @@
/* Include needed system header for detection of how many core on the system */
#if defined(_WIN32)
# include <windows.h>
#elif (defined(__APPLE__) && defined(__MACH__)) \
|| defined(__DragonFly__) || defined(__FreeBSD__) \
#elif (defined(__APPLE__) && defined(__MACH__)) \
|| defined(__DragonFly__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/param.h>
# include <sys/sysctl.h>
@@ -453,77 +453,77 @@ worker_count(worker_t g)
TODO: Support oplist for input & outputs parameters
*/
#if M_USE_WORKER_CLANG_BLOCK
#define WORKER_SPAWN(_block, _input, _core, _output) \
WORKER_DEF_DATA(_input, _output) \
WORKER_DEF_SUBBLOCK(_input, _output, _core) \
#define WORKER_SPAWN(_block, _input, _core, _output) \
WORKER_DEF_DATA(_input, _output) \
WORKER_DEF_SUBBLOCK(_input, _output, _core) \
worker_spawn_block ((_block), WORKER_SPAWN_SUBFUNC_NAME, &WORKER_SPAWN_DATA_NAME)
#elif M_USE_WORKER_CPP_FUNCTION
// TODO: Explicit pass all arguments by reference.
#define WORKER_SPAWN(_block, _input, _core, _output) \
#define WORKER_SPAWN(_block, _input, _core, _output) \
worker_spawn_function ((_block), [&](void *param) {(void)param ; _core } , NULL)
#else
#define WORKER_SPAWN(_block, _input, _core, _output) \
WORKER_DEF_DATA(_input, _output) \
WORKER_DEF_SUBFUNC(_input, _output, _core) \
#define WORKER_SPAWN(_block, _input, _core, _output) \
WORKER_DEF_DATA(_input, _output) \
WORKER_DEF_SUBFUNC(_input, _output, _core) \
worker_spawn ((_block), WORKER_SPAWN_SUBFUNC_NAME, &WORKER_SPAWN_DATA_NAME)
#endif
#define WORKER_SPAWN_STRUCT_NAME M_C(worker_data_s_, __LINE__)
#define WORKER_SPAWN_DATA_NAME M_C(worker_data_, __LINE__)
#define WORKER_SPAWN_SUBFUNC_NAME M_C(worker_subfunc_, __LINE__)
#define WORKER_DEF_DATA(_input, _output) \
struct WORKER_SPAWN_STRUCT_NAME { \
WORKER_DEF_DATA_INPUT _input \
M_IF_EMPTY _output ( , WORKER_DEF_DATA_OUTPUT _output) \
} WORKER_SPAWN_DATA_NAME = { \
WORKER_INIT_DATA_INPUT _input \
M_IF_EMPTY _output (, WORKER_INIT_DATA_OUTPUT _output) \
#define WORKER_DEF_DATA(_input, _output) \
struct WORKER_SPAWN_STRUCT_NAME { \
WORKER_DEF_DATA_INPUT _input \
M_IF_EMPTY _output ( , WORKER_DEF_DATA_OUTPUT _output) \
} WORKER_SPAWN_DATA_NAME = { \
WORKER_INIT_DATA_INPUT _input \
M_IF_EMPTY _output (, WORKER_INIT_DATA_OUTPUT _output) \
};
#define WORKER_DEF_SINGLE_INPUT(var) __typeof__(var) var;
#define WORKER_DEF_DATA_INPUT(...) \
#define WORKER_DEF_DATA_INPUT(...) \
M_MAP(WORKER_DEF_SINGLE_INPUT, __VA_ARGS__)
#define WORKER_DEF_SINGLE_OUTPUT(var) \
#define WORKER_DEF_SINGLE_OUTPUT(var) \
__typeof__(var) *M_C(var, _ptr);
#define WORKER_DEF_DATA_OUTPUT(...) \
#define WORKER_DEF_DATA_OUTPUT(...) \
M_MAP(WORKER_DEF_SINGLE_OUTPUT, __VA_ARGS__)
#define WORKER_INIT_SINGLE_INPUT(var) \
#define WORKER_INIT_SINGLE_INPUT(var) \
.var = var,
#define WORKER_INIT_DATA_INPUT(...) \
#define WORKER_INIT_DATA_INPUT(...) \
M_MAP(WORKER_INIT_SINGLE_INPUT, __VA_ARGS__)
#define WORKER_INIT_SINGLE_OUTPUT(var) \
#define WORKER_INIT_SINGLE_OUTPUT(var) \
.M_C(var, _ptr) = &var,
#define WORKER_INIT_DATA_OUTPUT(...) \
#define WORKER_INIT_DATA_OUTPUT(...) \
M_MAP(WORKER_INIT_SINGLE_OUTPUT, __VA_ARGS__)
#define WORKER_DEF_SUBFUNC(_input, _output, _core) \
__extension__ auto void WORKER_SPAWN_SUBFUNC_NAME(void *) ; \
__extension__ void WORKER_SPAWN_SUBFUNC_NAME(void *_data) \
{ \
struct WORKER_SPAWN_STRUCT_NAME *_s_data = _data ; \
WORKER_INIT_LOCAL_INPUT _input \
M_IF_EMPTY _output ( , WORKER_INIT_LOCAL_OUTPUT _output) \
do { _core } while (0); \
M_IF_EMPTY _output ( , WORKER_PROPAGATE_LOCAL_OUTPUT _output) \
#define WORKER_DEF_SUBFUNC(_input, _output, _core) \
__extension__ auto void WORKER_SPAWN_SUBFUNC_NAME(void *) ; \
__extension__ void WORKER_SPAWN_SUBFUNC_NAME(void *_data) \
{ \
struct WORKER_SPAWN_STRUCT_NAME *_s_data = _data ; \
WORKER_INIT_LOCAL_INPUT _input \
M_IF_EMPTY _output ( , WORKER_INIT_LOCAL_OUTPUT _output) \
do { _core } while (0); \
M_IF_EMPTY _output ( , WORKER_PROPAGATE_LOCAL_OUTPUT _output) \
};
#define WORKER_DEF_SUBBLOCK(_input, _output, _core) \
void (^WORKER_SPAWN_SUBFUNC_NAME) (void *) = ^ void (void * _data) \
{ \
struct WORKER_SPAWN_STRUCT_NAME *_s_data = _data ; \
WORKER_INIT_LOCAL_INPUT _input \
M_IF_EMPTY _output ( , WORKER_INIT_LOCAL_OUTPUT _output) \
do { _core } while (0); \
M_IF_EMPTY _output ( , WORKER_PROPAGATE_LOCAL_OUTPUT _output) \
#define WORKER_DEF_SUBBLOCK(_input, _output, _core) \
void (^WORKER_SPAWN_SUBFUNC_NAME) (void *) = ^ void (void * _data) \
{ \
struct WORKER_SPAWN_STRUCT_NAME *_s_data = _data ; \
WORKER_INIT_LOCAL_INPUT _input \
M_IF_EMPTY _output ( , WORKER_INIT_LOCAL_OUTPUT _output) \
do { _core } while (0); \
M_IF_EMPTY _output ( , WORKER_PROPAGATE_LOCAL_OUTPUT _output) \
};
#define WORKER_INIT_SINGLE_LOCAL_INPUT(var) \
#define WORKER_INIT_SINGLE_LOCAL_INPUT(var) \
__typeof__(var) var = _s_data->var;
#define WORKER_INIT_LOCAL_INPUT(...) \
#define WORKER_INIT_LOCAL_INPUT(...) \
M_MAP(WORKER_INIT_SINGLE_LOCAL_INPUT, __VA_ARGS__)
#define WORKER_INIT_SINGLE_LOCAL_OUTPUT(var) \
#define WORKER_INIT_SINGLE_LOCAL_OUTPUT(var) \
__typeof__(var) var;
#define WORKER_INIT_LOCAL_OUTPUT(...) \
#define WORKER_INIT_LOCAL_OUTPUT(...) \
M_MAP(WORKER_INIT_SINGLE_LOCAL_OUTPUT, __VA_ARGS__)
#define WORKER_PROPAGATE_SINGLE_OUTPUT(var) \
#define WORKER_PROPAGATE_SINGLE_OUTPUT(var) \
*(_s_data->M_C(var, _ptr)) = var;
#define WORKER_PROPAGATE_LOCAL_OUTPUT(...) \
#define WORKER_PROPAGATE_LOCAL_OUTPUT(...) \
M_MAP(WORKER_PROPAGATE_SINGLE_OUTPUT, __VA_ARGS__)
M_END_PROTECTED_CODE