Rename generated internal functions
to avoid "poluting" userspace naming.
This commit is contained in:
1 parent
25497bd96f
commit
517da1b999
25 files changed
+2386
-2388
No files matched your search
@@ -33,7 +33,7 @@
|
||||
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)) \
|
||||
M_ALG0_DEF_P1(name, M_GLOBAL_OPLIST(cont_oplist)) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
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__), \
|
||||
ALGOI_FOR_EACH_ARG(container, M_GLOBAL_OPLIST(cont_oplist), __VA_ARGS__ ))
|
||||
(M_ALG0_FOR_EACH(container, M_GLOBAL_OPLIST(cont_oplist), __VA_ARGS__), \
|
||||
M_ALG0_FOR_EACH_ARG(container, M_GLOBAL_OPLIST(cont_oplist), __VA_ARGS__ ))
|
||||
|
||||
|
||||
/* Map a function (or a macro) to all elements of a container
|
||||
@@ -53,8 +53,8 @@
|
||||
function[, extra arguments of function]) */
|
||||
#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__ ))
|
||||
(M_ALG0_TRANSFORM(contD, M_GLOBAL_OPLIST(contDop), contS, M_GLOBAL_OPLIST(contSop), __VA_ARGS__), \
|
||||
M_ALG0_TRANSFORM_ARG(contD, M_GLOBAL_OPLIST(contDop), contS, M_GLOBAL_OPLIST(contSop), __VA_ARGS__ ))
|
||||
|
||||
|
||||
/* Extract a subset of a container to copy into another container.
|
||||
@@ -63,10 +63,10 @@
|
||||
[, function [, extra arguments of function]]) */
|
||||
#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_ALG0_EXTRACT(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __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__ )))
|
||||
(M_ALG0_EXTRACT_FUNC(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __VA_ARGS__), \
|
||||
M_ALG0_EXTRACT_ARG(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __VA_ARGS__ )))
|
||||
|
||||
|
||||
/* Perform a Reduce operation over a container.
|
||||
@@ -75,8 +75,8 @@
|
||||
[, mapFunc[, extraParameters of map function]]) */
|
||||
#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__)) \
|
||||
(M_ALG0_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__), \
|
||||
M_ALG0_REDUCE_DISPATCH(dest, M_GET_OPLIST M_GLOBAL_OPLIST(contOp), M_GET_SUBTYPE M_GLOBAL_OPLIST(contOp), cont, contOp, __VA_ARGS__)) \
|
||||
|
||||
|
||||
/* Initialize & set a container with a variable array list.
|
||||
@@ -105,66 +105,66 @@
|
||||
ALGO_INSERT_AT(containerDst, containerDstOPLIST|containerDstType, containerDstIterator, containerSrc, containerSrcOPLIST|containerSrcType)
|
||||
*/
|
||||
#define ALGO_INSERT_AT(contDst, contDstOp, position, contSrc, contSrcOp) \
|
||||
ALGOI_INSERT_AT(contDst, M_GLOBAL_OPLIST(contDstOp), position, contSrc, M_GLOBAL_OPLIST(contSrcOp) )
|
||||
M_ALG0_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, \
|
||||
#define M_ALG0_DEF_P1(name, cont_oplist) \
|
||||
M_ALG0_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 */
|
||||
#define ALGOI_DEF_P2(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_IF_OPLIST(cont_oplist)(ALGOI_DEF_P3, ALGOI_DEF_FAILURE)(name, container_t, cont_oplist, type_t, type_oplist, it_t)
|
||||
#define M_ALG0_DEF_P2(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_IF_OPLIST(cont_oplist)(M_ALG0_DEF_P3, M_ALG0_DEF_FAILURE)(name, container_t, cont_oplist, type_t, type_oplist, it_t)
|
||||
|
||||
/* Then validate the second oplist */
|
||||
#define ALGOI_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_IF_OPLIST(type_oplist)(ALGOI_DEF_P4, ALGOI_DEF_FAILURE)(name, container_t, cont_oplist, type_t, type_oplist, it_t)
|
||||
#define M_ALG0_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_IF_OPLIST(type_oplist)(M_ALG0_DEF_P4, M_ALG0_DEF_FAILURE)(name, container_t, cont_oplist, type_t, type_oplist, it_t)
|
||||
|
||||
/* Stop processing with a compilation failure if an oplist was invalid */
|
||||
#define ALGOI_DEF_FAILURE(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_DEF_FAILURE(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(ALGO_DEF): one of the given argument is not a valid oplist: " M_AS_STR(cont_oplist) " / " M_AS_STR(type_oplist) )
|
||||
|
||||
|
||||
/* Expand all algorithms */
|
||||
#define ALGOI_DEF_P4(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_DEF_P4(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 10, container_t, cont_oplist) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 11, type_t, type_oplist) \
|
||||
\
|
||||
ALGOI_CALLBACK_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_IF_FUNCOBJ(ALGOI_FUNCOBJ_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t)) \
|
||||
M_ALG0_CALLBACK_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_IF_FUNCOBJ(M_ALG0_FUNCOBJ_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t)) \
|
||||
\
|
||||
M_IF_METHOD(EQUAL, type_oplist)( \
|
||||
ALGOI_FIND_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_ALG0_FIND_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
, /* NO EQUAL */) \
|
||||
\
|
||||
ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, if, M_C(name, _test_cb_ct), M_C(name, _eq_cb_ct), M_APPLY, M_APPLY) \
|
||||
M_IF_FUNCOBJ(ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, fo, M_C(name, _test_obj_t), M_C(name, _eq_obj_t), M_C(name, _test_obj_call), M_C(name, _eq_obj_call))) \
|
||||
M_ALG0_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, if, M_C(name, _test_cb_ct), M_C(name, _eq_cb_ct), M_APPLY, M_APPLY) \
|
||||
M_IF_FUNCOBJ(M_ALG0_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, fo, M_C(name, _test_obj_t), M_C(name, _eq_obj_t), M_C(name, _test_obj_call), M_C(name, _eq_obj_call))) \
|
||||
\
|
||||
ALGOI_MAP_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_ALG0_MAP_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _, M_C(name, _test_cb_ct), M_APPLY) \
|
||||
M_IF_FUNCOBJ(ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _fo_, M_C(name, _test_obj_t), M_C(name, _test_obj_call)) ) \
|
||||
M_ALG0_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _, M_C(name, _test_cb_ct), M_APPLY) \
|
||||
M_IF_FUNCOBJ(M_ALG0_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _fo_, M_C(name, _test_obj_t), M_C(name, _test_obj_call)) ) \
|
||||
\
|
||||
/* If there is a IT_REF method, we consider the container as modifiable through iterator */ \
|
||||
M_IF_METHOD(IT_REF, cont_oplist)( \
|
||||
ALGOI_FILL_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
ALGOI_VECTOR_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_ALG0_FILL_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_ALG0_VECTOR_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
M_IF_METHOD(CMP, type_oplist)( \
|
||||
ALGOI_MINMAX_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
ALGOI_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, +, _sort) \
|
||||
ALGOI_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, -, _sort_dsc) \
|
||||
M_ALG0_MINMAX_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_ALG0_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, +, _sort) \
|
||||
M_ALG0_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, -, _sort_dsc) \
|
||||
M_IF_METHOD(IT_REMOVE, cont_oplist)( \
|
||||
ALGOI_REMOVE_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
M_ALG0_REMOVE_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
, /* No IT_REMOVE method */) \
|
||||
, /* No CMP method */) \
|
||||
\
|
||||
M_IF_FUNCOBJ(ALGOI_SORT_DEF_P6(name, container_t, cont_oplist, type_t, type_oplist, it_t, _sort_fo, ALGOI_SORT_CALL_OBJ_P4, ALGOI_SORT_PARAM_OBJ_P4, ALGOI_SORT_ARG_OBJ_P4) ) \
|
||||
M_IF_FUNCOBJ(M_ALG0_SORT_DEF_P6(name, container_t, cont_oplist, type_t, type_oplist, it_t, _sort_fo, M_ALG0_SORT_CALL_OBJ_P4, M_ALG0_SORT_PARAM_OBJ_P4, M_ALG0_SORT_ARG_OBJ_P4) ) \
|
||||
, /* No IT_REF method */) \
|
||||
\
|
||||
M_IF_METHOD(EXT_ALGO, type_oplist)( \
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
/* Define the types of the callbacks associated to the algorithms.
|
||||
* Types remain internal */
|
||||
#define ALGOI_CALLBACK_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_CALLBACK_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
typedef bool (*M_C(name, _test_cb_ct))(type_t const); \
|
||||
typedef bool (*M_C(name, _eq_cb_ct))(type_t const, type_t const); \
|
||||
@@ -185,7 +185,7 @@
|
||||
|
||||
/* Define the function objects associated to the algorithms.
|
||||
* Created Function objects are part of the public interface */
|
||||
#define ALGOI_FUNCOBJ_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_FUNCOBJ_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
FUNC_OBJ_ITF_DEF(M_C(name, _test_obj), bool, type_t const) \
|
||||
FUNC_OBJ_ITF_DEF(M_C(name, _eq_obj), bool, type_t const, type_t const ) \
|
||||
@@ -195,7 +195,7 @@
|
||||
|
||||
|
||||
/* Define the sort functions with the CMP operator using the order selected */
|
||||
#define ALGOI_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, order, sort_name) \
|
||||
#define M_ALG0_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, order, sort_name) \
|
||||
\
|
||||
/* Define the encapsulation function that perform the selected order */ \
|
||||
static inline int M_C3(name,sort_name,_cmp)(type_t const*a,type_t const*b) \
|
||||
@@ -203,19 +203,19 @@
|
||||
return order M_CALL_CMP(type_oplist, *a, *b); \
|
||||
} \
|
||||
\
|
||||
ALGOI_SORT_DEF_P6(name, container_t, cont_oplist, type_t, type_oplist, it_t, sort_name, ALGOI_SORT_CALL_CMP_P4, M_EAT, /*empty*/ )
|
||||
M_ALG0_SORT_DEF_P6(name, container_t, cont_oplist, type_t, type_oplist, it_t, sort_name, M_ALG0_SORT_CALL_CMP_P4, M_EAT, /*empty*/ )
|
||||
|
||||
// Call the comparaison function of the type oplist (Using CMP operator)
|
||||
#define ALGOI_SORT_CALL_CMP_P4(name, sort_name, ref1, ref2) \
|
||||
#define M_ALG0_SORT_CALL_CMP_P4(name, sort_name, ref1, ref2) \
|
||||
M_C3(name, sort_name,_cmp)(ref1, ref2)
|
||||
|
||||
|
||||
// Call the created function object
|
||||
#define ALGOI_SORT_CALL_OBJ_P4(name, sort_name, ref1, ref2) \
|
||||
#define M_ALG0_SORT_CALL_OBJ_P4(name, sort_name, ref1, ref2) \
|
||||
M_C(name, _cmp_obj_call)(funcobj, *ref1, *ref2)
|
||||
// Adding a parameter named 'funcobj' to the algorithm functions
|
||||
#define ALGOI_SORT_PARAM_OBJ_P4(name) M_DEFERRED_COMMA M_C(name, _cmp_obj_t) funcobj
|
||||
#define ALGOI_SORT_ARG_OBJ_P4 M_DEFERRED_COMMA funcobj
|
||||
#define M_ALG0_SORT_PARAM_OBJ_P4(name) M_DEFERRED_COMMA M_C(name, _cmp_obj_t) funcobj
|
||||
#define M_ALG0_SORT_ARG_OBJ_P4 M_DEFERRED_COMMA funcobj
|
||||
|
||||
|
||||
/* Define the sort funtions using either the CMP operator or a function object
|
||||
@@ -231,7 +231,7 @@
|
||||
It is needed to add another argument to the function.
|
||||
- cmp_arg: Name of such argument.
|
||||
*/
|
||||
#define ALGOI_SORT_DEF_P6(name, container_t, cont_oplist, type_t, type_oplist, it_t, sort_name, cmp_func, cmp_param, cmp_arg) \
|
||||
#define M_ALG0_SORT_DEF_P6(name, container_t, cont_oplist, type_t, type_oplist, it_t, sort_name, cmp_func, cmp_param, cmp_arg) \
|
||||
\
|
||||
/* Test if the container is sorted */ \
|
||||
static inline bool \
|
||||
@@ -523,7 +523,7 @@
|
||||
TODO: Define _find_sorted that find in a sorted random access container
|
||||
(binary search)
|
||||
*/
|
||||
#define ALGOI_FIND_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_FIND_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
/* It supposes that the container is not sorted */ \
|
||||
/* Find the next occurence from it (included) of data */ \
|
||||
static inline void \
|
||||
@@ -631,7 +631,7 @@
|
||||
TODO: Define _find_sorted that find in a sorted random access container
|
||||
(binary search)
|
||||
*/
|
||||
#define ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, test_t, eq_t, call_test, call_eq) \
|
||||
#define M_ALG0_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, test_t, eq_t, call_test, call_eq) \
|
||||
\
|
||||
/* Find the next occurence that matches the condition */ \
|
||||
static inline void \
|
||||
@@ -694,7 +694,7 @@
|
||||
|
||||
|
||||
/* Define the FILL algorithms */
|
||||
#define ALGOI_FILL_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_FILL_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
/* Fill all the container with value (overwritten) */ \
|
||||
static inline void \
|
||||
@@ -750,7 +750,7 @@
|
||||
|
||||
|
||||
/* Define MAP algorithms */
|
||||
#define ALGOI_MAP_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_MAP_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
/* Apply func for all elements of the container */ \
|
||||
static inline void \
|
||||
@@ -826,7 +826,7 @@
|
||||
|
||||
|
||||
/* Define ALL_OF algorithms */
|
||||
#define ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, func_t, call) \
|
||||
#define M_ALG0_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, func_t, call) \
|
||||
\
|
||||
static inline bool \
|
||||
M_C4(name, _any_of, suffix, p) (container_t const l, \
|
||||
@@ -863,7 +863,7 @@
|
||||
|
||||
|
||||
/* Define MIN / MAX algorithms */
|
||||
#define ALGOI_MINMAX_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_MINMAX_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
static inline type_t * \
|
||||
M_C(name, _min) (const container_t l) \
|
||||
@@ -912,7 +912,7 @@
|
||||
} \
|
||||
|
||||
|
||||
#define ALGOI_REMOVE_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_REMOVE_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _uniq)(container_t l) \
|
||||
@@ -967,7 +967,7 @@
|
||||
} \
|
||||
|
||||
|
||||
#define ALGOI_VECTOR_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
#define M_ALG0_VECTOR_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
M_IF_METHOD(ADD, type_oplist)( \
|
||||
static inline void M_C(name, _add) (container_t dst, const container_t src) \
|
||||
@@ -1051,20 +1051,20 @@
|
||||
// _flatten (takes a set of containers and returns a new container containing all flatten objects)
|
||||
|
||||
|
||||
#define ALGOI_FOR_EACH(container, cont_oplist, func) do { \
|
||||
#define M_ALG0_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 { \
|
||||
#define M_ALG0_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 { \
|
||||
#define M_ALG0_TRANSFORM(contD, contDop, contS, contSop, func) do { \
|
||||
M_CALL_CLEAN(contDop, contD); \
|
||||
for M_EACH(_item, contS, contSop) { \
|
||||
M_GET_SUBTYPE contDop _tmp; \
|
||||
@@ -1075,7 +1075,7 @@
|
||||
M_IF_METHOD(REVERSE, contDop) (M_CALL_REVERSE(contDop, contD);, ) \
|
||||
} while (0)
|
||||
|
||||
#define ALGOI_TRANSFORM_ARG(contD, contDop, contS, contSop, func, ...) do { \
|
||||
#define M_ALG0_TRANSFORM_ARG(contD, contDop, contS, contSop, func, ...) do { \
|
||||
M_CALL_CLEAN(contDop, contD); \
|
||||
for M_EACH(_item, contS, contSop) { \
|
||||
M_GET_SUBTYPE contDop _tmp; \
|
||||
@@ -1087,7 +1087,7 @@
|
||||
} while (0)
|
||||
|
||||
|
||||
#define ALGOI_EXTRACT(contDst, contDstOplist, \
|
||||
#define M_ALG0_EXTRACT(contDst, contDstOplist, \
|
||||
contSrc, contSrcOplist) do { \
|
||||
M_CALL_CLEAN(contDstOplist, contDst); \
|
||||
for M_EACH(_item, contSrc, contSrcOplist) { \
|
||||
@@ -1100,7 +1100,7 @@
|
||||
M_IF_METHOD(REVERSE, contDstOplist) (M_CALL_REVERSE(contDstOplist, contDst);, ) \
|
||||
} while (0)
|
||||
|
||||
#define ALGOI_EXTRACT_FUNC(contDst, contDstOplist, \
|
||||
#define M_ALG0_EXTRACT_FUNC(contDst, contDstOplist, \
|
||||
contSrc, contSrcOplist, \
|
||||
condFunc) do { \
|
||||
M_CALL_CLEAN(contDstOplist, contDst); \
|
||||
@@ -1116,7 +1116,7 @@
|
||||
M_IF_METHOD(REVERSE, contDstOplist) (M_CALL_REVERSE(contDstOplist, contDst);, ) \
|
||||
} while (0)
|
||||
|
||||
#define ALGOI_EXTRACT_ARG(contDst, contDstOplist, \
|
||||
#define M_ALG0_EXTRACT_ARG(contDst, contDstOplist, \
|
||||
contSrc, contSrcOplist, \
|
||||
condFunc, ...) do { \
|
||||
M_CALL_CLEAN(contDstOplist, contDst); \
|
||||
@@ -1133,41 +1133,41 @@
|
||||
} while (0)
|
||||
|
||||
|
||||
#define ALGOI_REDUCE_DISPATCH(dest, destOp, dest_t, cont, contOp, ...) \
|
||||
#define M_ALG0_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_ALG0_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__) ) )
|
||||
(M_ALG0_REDUCE_FOR_EACH(dest, dest_t, destOp, cont, contOp, __VA_ARGS__), \
|
||||
M_ALG0_REDUCE_FOR_EACH_ARG(dest, dest_t, destOp, cont, contOp, __VA_ARGS__) ) )
|
||||
|
||||
/* The special functions handled by ALGO_REDUCE */
|
||||
#define ALGOI_REDUCE_AND(a,b) ((a) &= (b))
|
||||
#define ALGOI_REDUCE_OR(a,b) ((a) |= (b))
|
||||
#define ALGOI_REDUCE_SUM(a,b) ((a) += (b))
|
||||
#define ALGOI_REDUCE_PRODUCT(a,b) ((a) *= (b))
|
||||
#define M_ALG0_REDUCE_AND(a,b) ((a) &= (b))
|
||||
#define M_ALG0_REDUCE_OR(a,b) ((a) |= (b))
|
||||
#define M_ALG0_REDUCE_SUM(a,b) ((a) += (b))
|
||||
#define M_ALG0_REDUCE_PRODUCT(a,b) ((a) *= (b))
|
||||
|
||||
/* 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) \
|
||||
#define M_ALG0_REDUCE_FUNC(reduceFunc) \
|
||||
M_IF(M_KEYWORD_P(and, reduceFunc)) \
|
||||
(ALGOI_REDUCE_AND, \
|
||||
(M_ALG0_REDUCE_AND, \
|
||||
M_IF(M_KEYWORD_P(or, reduceFunc)) \
|
||||
(ALGOI_REDUCE_OR, \
|
||||
(M_ALG0_REDUCE_OR, \
|
||||
M_IF(M_KEYWORD_P(sum, reduceFunc)) \
|
||||
(ALGOI_REDUCE_SUM, \
|
||||
(M_ALG0_REDUCE_SUM, \
|
||||
M_IF(M_KEYWORD_P(product, reduceFunc)) \
|
||||
(ALGOI_REDUCE_PRODUCT, \
|
||||
(M_ALG0_REDUCE_PRODUCT, \
|
||||
reduceFunc) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define ALGOI_REDUCE_BASIC(dest, dest_t, destOp, cont, cont_oplist, reduceFunc) do { \
|
||||
#define M_ALG0_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); \
|
||||
M_ALG0_REDUCE_FUNC(reduceFunc) (dest, *_item); \
|
||||
} else { \
|
||||
M_CALL_SET(destOp, dest, *_item); \
|
||||
_init_done = true; \
|
||||
@@ -1175,14 +1175,14 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ALGOI_REDUCE_FOR_EACH(dest, dest_t, destOp, cont, cont_oplist, reduceFunc, mapFunc) do { \
|
||||
#define M_ALG0_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); \
|
||||
M_ALG0_REDUCE_FUNC(reduceFunc) (dest, _tmp); \
|
||||
} else { \
|
||||
M_CALL_SET(destOp, dest, _tmp); \
|
||||
_init_done = true; \
|
||||
@@ -1191,14 +1191,14 @@
|
||||
M_CALL_CLEAR(destOp, _tmp); \
|
||||
} while (0)
|
||||
|
||||
#define ALGOI_REDUCE_FOR_EACH_ARG(dest, dest_t, destOp, cont, cont_oplist, reduceFunc, mapFunc, ...) do { \
|
||||
#define M_ALG0_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); \
|
||||
M_ALG0_REDUCE_FUNC(reduceFunc) (dest, _tmp); \
|
||||
} else { \
|
||||
M_CALL_SET(destOp, dest, _tmp); \
|
||||
_init_done = true; \
|
||||
@@ -1208,26 +1208,26 @@
|
||||
} while (0)
|
||||
|
||||
|
||||
#define ALGOI_INIT_VA_FUNC(d, a) \
|
||||
#define M_ALG0_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 \
|
||||
M_MAP2(ALGOI_INIT_VA_FUNC, (dest, M_GET_PUSH contOp, ) , __VA_ARGS__) \
|
||||
M_MAP2(M_ALG0_INIT_VA_FUNC, (dest, M_GET_PUSH contOp, ) , __VA_ARGS__) \
|
||||
true)
|
||||
|
||||
|
||||
#define ALGO_LET_INIT_VAI(dest, ...) \
|
||||
ALGOI_LET_INIT_VAI(M_C3(m_cont_, __LINE__, dest), dest, __VA_ARGS__)
|
||||
M_ALG0_LET_INIT_VAI(M_C3(m_cont_, __LINE__, dest), dest, __VA_ARGS__)
|
||||
|
||||
#define ALGOI_LET_INIT_VAI(cont, dest, contOp, ...) \
|
||||
#define M_ALG0_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 { \
|
||||
#define M_ALG0_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); \
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
USAGE: ARRAY_DEF_AS(name, name_t, it_t, type [, oplist_of_the_type]) */
|
||||
#define ARRAY_DEF_AS(name, name_t, it_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
ARRAYI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_ARRA4_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
|
||||
@@ -48,7 +48,7 @@
|
||||
If no oplist is given it is assumed to be M_DEFAULT_OPLIST
|
||||
USAGE: ARRAY_OPLIST(name[, oplist of the type]) */
|
||||
#define ARRAY_OPLIST(...) \
|
||||
ARRAYI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_ARRA4_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -60,20 +60,20 @@
|
||||
|
||||
/* Deferred evaluation for the oplist definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define ARRAYI_OPLIST_P1(arg) ARRAYI_OPLIST_P2 arg
|
||||
#define M_ARRA4_OPLIST_P1(arg) M_ARRA4_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define ARRAYI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(ARRAYI_OPLIST_P3, ARRAYI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_ARRA4_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_ARRA4_OPLIST_P3, M_ARRA4_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define ARRAYI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_ARRA4_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_ARRAY_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* OPLIST definition of a dynamic array */
|
||||
/* FIXME: Do we want to export some methods as they are slow and
|
||||
are not fit to be used for building other methods (like _it_remove)? */
|
||||
#define ARRAYI_OPLIST_P3(name, oplist) \
|
||||
#define M_ARRA4_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _init)) \
|
||||
,M_IF_METHOD2(INIT_SET,SET, oplist)(INIT_SET(M_C(name, _init_set)),) \
|
||||
,M_IF_METHOD(INIT_SET, oplist)(INIT_WITH(API_1(M_INIT_VAI)),) \
|
||||
@@ -129,7 +129,7 @@
|
||||
)
|
||||
|
||||
/* Define the internal contract of an array */
|
||||
#define ARRAYI_CONTRACT(a) do { \
|
||||
#define M_ARRA4_CONTRACT(a) do { \
|
||||
M_ASSERT (a != NULL); \
|
||||
M_ASSERT (a->size <= a->alloc); \
|
||||
M_ASSERT (a->size == 0 || a->ptr != NULL); \
|
||||
@@ -137,14 +137,14 @@
|
||||
|
||||
/* Deferred evaluation for the array definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define ARRAYI_DEF_P1(arg) ARRAYI_DEF_P2 arg
|
||||
#define M_ARRA4_DEF_P1(arg) M_ARRA4_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define ARRAYI_DEF_P2(name, type, oplist, array_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(ARRAYI_DEF_P3, ARRAYI_DEF_FAILURE)(name, type, oplist, array_t, it_t)
|
||||
#define M_ARRA4_DEF_P2(name, type, oplist, array_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(M_ARRA4_DEF_P3, M_ARRA4_DEF_FAILURE)(name, type, oplist, array_t, it_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define ARRAYI_DEF_FAILURE(name, type, oplist, array_t, it_t) \
|
||||
#define M_ARRA4_DEF_FAILURE(name, type, oplist, array_t, it_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(ARRAY_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
/* Internal definition:
|
||||
@@ -154,7 +154,7 @@
|
||||
- array_t: alias for the type of the array
|
||||
- it_t: alias for the iterator of the array
|
||||
*/
|
||||
#define ARRAYI_DEF_P3(name, type, oplist, array_t, it_t) \
|
||||
#define M_ARRA4_DEF_P3(name, type, oplist, array_t, it_t) \
|
||||
\
|
||||
/* Define a dynamic array */ \
|
||||
typedef struct M_C(name, _s) { \
|
||||
@@ -186,23 +186,23 @@
|
||||
v->size = 0; \
|
||||
v->alloc = 0; \
|
||||
v->ptr = NULL; \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clean)(array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
for(size_t i = 0; i < v->size; i++) \
|
||||
M_CALL_CLEAR(oplist, v->ptr[i]); \
|
||||
v->size = 0; \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_C(name, _clean)(v); \
|
||||
M_CALL_FREE(oplist, v->ptr); \
|
||||
v->alloc = 0; \
|
||||
@@ -213,8 +213,8 @@
|
||||
static inline void \
|
||||
M_C(name, _set)(array_t d, const array_t s) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(d); \
|
||||
ARRAYI_CONTRACT(s); \
|
||||
M_ARRA4_CONTRACT(d); \
|
||||
M_ARRA4_CONTRACT(s); \
|
||||
if (M_UNLIKELY (d == s)) return; \
|
||||
if (s->size > d->alloc) { \
|
||||
const size_t alloc = s->size; \
|
||||
@@ -235,7 +235,7 @@
|
||||
for( ; i < d->size; i++) \
|
||||
M_CALL_CLEAR(oplist, d->ptr[i]); \
|
||||
d->size = s->size; \
|
||||
ARRAYI_CONTRACT(d); \
|
||||
M_ARRA4_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -251,13 +251,13 @@
|
||||
M_C(name, _init_move)(array_t d, array_t s) \
|
||||
{ \
|
||||
M_ASSERT (d != s); \
|
||||
ARRAYI_CONTRACT(s); \
|
||||
M_ARRA4_CONTRACT(s); \
|
||||
d->size = s->size; \
|
||||
d->alloc = s->alloc; \
|
||||
d->ptr = s->ptr; \
|
||||
s->alloc = 0; \
|
||||
s->ptr = NULL; \
|
||||
ARRAYI_CONTRACT(d); \
|
||||
M_ARRA4_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -272,7 +272,7 @@
|
||||
static inline void \
|
||||
M_C(name, _set_at)(array_t v, size_t i, type const x) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT(v->size > 0 && v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(i, v->size); \
|
||||
M_CALL_SET(oplist, v->ptr[i], x); \
|
||||
@@ -282,7 +282,7 @@
|
||||
static inline type const * \
|
||||
M_C(name, _back)(array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT(v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(0, v->size); \
|
||||
return M_CONST_CAST(type, &v->ptr[v->size-1]); \
|
||||
@@ -291,7 +291,7 @@
|
||||
static inline type * \
|
||||
M_C(name, _push_raw)(array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
if (M_UNLIKELY (v->size >= v->alloc)) { \
|
||||
M_ASSERT(v->size == v->alloc); \
|
||||
size_t alloc = M_CALL_INC_ALLOC(oplist, v->alloc); \
|
||||
@@ -311,7 +311,7 @@
|
||||
M_ASSERT(v->ptr != NULL); \
|
||||
type *ret = &v->ptr[v->size]; \
|
||||
v->size++; \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSUME(ret != NULL); \
|
||||
return ret; \
|
||||
} \
|
||||
@@ -355,7 +355,7 @@
|
||||
static inline void \
|
||||
M_C(name, _push_at)(array_t v, size_t key, type const x) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT_INDEX(key, v->size+1); \
|
||||
if (M_UNLIKELY (v->size >= v->alloc) ) { \
|
||||
M_ASSERT(v->size == v->alloc); \
|
||||
@@ -377,7 +377,7 @@
|
||||
memmove(&v->ptr[key+1], &v->ptr[key], (v->size-key)*sizeof(type)); \
|
||||
v->size++; \
|
||||
M_CALL_INIT_SET(oplist, v->ptr[key], x); \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
, /* No INIT_SET */ ) \
|
||||
\
|
||||
@@ -385,7 +385,7 @@
|
||||
static inline void \
|
||||
M_C(name, _resize)(array_t v, size_t size) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
if (v->size > size) { \
|
||||
/* Decrease size of array */ \
|
||||
for(size_t i = size ; i < v->size; i++) \
|
||||
@@ -407,14 +407,14 @@
|
||||
M_CALL_INIT(oplist, v->ptr[i]); \
|
||||
v->size = size; \
|
||||
} \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
, /* No INIT */ ) \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _reserve)(array_t v, size_t alloc) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
/* NOTE: Reserve below needed size to perform a shrink to fit */ \
|
||||
if (v->size > alloc) { \
|
||||
alloc = v->size; \
|
||||
@@ -432,14 +432,14 @@
|
||||
v->ptr = ptr; \
|
||||
v->alloc = alloc; \
|
||||
} \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
M_IF_METHOD(INIT, oplist)( \
|
||||
static inline type * \
|
||||
M_C(name, _get_at)(array_t v, size_t idx) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
const size_t size = idx + 1; \
|
||||
/* resize if needed */ \
|
||||
if (v->size <= size) { \
|
||||
@@ -464,7 +464,7 @@
|
||||
v->size = size; \
|
||||
} \
|
||||
M_ASSERT (idx < v->size); \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
return &v->ptr[idx]; \
|
||||
} \
|
||||
, /* No INIT */) \
|
||||
@@ -473,7 +473,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_back)(type *dest, array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(0, v->size); \
|
||||
v->size--; \
|
||||
@@ -482,7 +482,7 @@
|
||||
} else { \
|
||||
M_CALL_CLEAR(oplist, v->ptr[v->size]); \
|
||||
} \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
, /* SET | INIT_MOVE */ ) \
|
||||
\
|
||||
@@ -490,13 +490,13 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_move)(type *dest, array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(0, v->size); \
|
||||
M_ASSERT (dest != NULL); \
|
||||
v->size--; \
|
||||
M_DO_INIT_MOVE (oplist, *dest, v->ptr[v->size]); \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
, /* INIT_SET | INIT_MOVE */ ) \
|
||||
\
|
||||
@@ -504,7 +504,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_until)(array_t v, it_t pos) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (v == pos->array); \
|
||||
M_ASSERT_INDEX(pos->index, v->size+1); \
|
||||
M_C(name, _resize)(v, pos->index); \
|
||||
@@ -514,21 +514,21 @@
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(const array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
return v->size == 0; \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
return v->size; \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _capacity)(const array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
return v->alloc; \
|
||||
} \
|
||||
\
|
||||
@@ -536,7 +536,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_at)(type *dest, array_t v, size_t i) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (v->size > 0 && v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(i, v->size); \
|
||||
if (dest) \
|
||||
@@ -545,13 +545,13 @@
|
||||
M_CALL_CLEAR(oplist, v->ptr[i]); \
|
||||
memmove(&v->ptr[i], &v->ptr[i+1], sizeof(type)*(v->size - i) ); \
|
||||
v->size--; \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _erase)(array_t a, size_t i) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(a); \
|
||||
M_ARRA4_CONTRACT(a); \
|
||||
if (i >= a->size) return false; \
|
||||
M_C(name, _pop_at)(NULL, a, i); \
|
||||
return true; \
|
||||
@@ -562,7 +562,7 @@
|
||||
static inline void \
|
||||
M_C(name, _insert_v)(array_t v, size_t i, size_t num) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT_INDEX(i, v->size+1); \
|
||||
size_t size = v->size + num; \
|
||||
/* Test for overflow of variable size */ \
|
||||
@@ -591,14 +591,14 @@
|
||||
for(size_t k = i ; k < i+num; k++) \
|
||||
M_CALL_INIT(oplist, v->ptr[k]); \
|
||||
v->size = size; \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
, /* No INIT */) \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _remove_v)(array_t v, size_t i, size_t j) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT(i < j && v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(i, v->size); \
|
||||
M_ASSERT_INDEX(j, v->size+1); \
|
||||
@@ -606,14 +606,14 @@
|
||||
M_CALL_CLEAR(oplist, v->ptr[k]); \
|
||||
memmove(&v->ptr[i], &v->ptr[j], sizeof(type)*(v->size - j) ); \
|
||||
v->size -= (j-i); \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _swap)(array_t v1, array_t v2) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v1); \
|
||||
ARRAYI_CONTRACT(v2); \
|
||||
M_ARRA4_CONTRACT(v1); \
|
||||
M_ARRA4_CONTRACT(v2); \
|
||||
size_t tmp = v1->size; \
|
||||
v1->size = v2->size; \
|
||||
v2->size = tmp; \
|
||||
@@ -623,15 +623,15 @@
|
||||
type *p = v1->ptr; \
|
||||
v1->ptr = v2->ptr; \
|
||||
v2->ptr = p; \
|
||||
ARRAYI_CONTRACT(v1); \
|
||||
ARRAYI_CONTRACT(v2); \
|
||||
M_ARRA4_CONTRACT(v1); \
|
||||
M_ARRA4_CONTRACT(v2); \
|
||||
} \
|
||||
\
|
||||
M_IF_AT_LEAST_METHOD(INIT_SET,INIT_MOVE,oplist) ( \
|
||||
static inline void \
|
||||
M_C(name, _swap_at)(array_t v, size_t i, size_t j) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT(v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(i, v->size); \
|
||||
M_ASSERT_INDEX(j, v->size); \
|
||||
@@ -639,14 +639,14 @@
|
||||
M_DO_INIT_MOVE(oplist, tmp, v->ptr[i]); \
|
||||
M_DO_INIT_MOVE(oplist, v->ptr[i], v->ptr[j]); \
|
||||
M_DO_INIT_MOVE(oplist, v->ptr[j], tmp); \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
} \
|
||||
, /* INIT_SET | INIT_MOVE */ ) \
|
||||
\
|
||||
static inline type * \
|
||||
M_C(name, _get)(const array_t v, size_t i) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(i, v->size); \
|
||||
return &v->ptr[i]; \
|
||||
@@ -655,7 +655,7 @@
|
||||
static inline type const * \
|
||||
M_C(name, _cget)(const array_t v, size_t i) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (v->ptr != NULL); \
|
||||
M_ASSERT_INDEX(i, v->size); \
|
||||
return M_CONST_CAST(type, &v->ptr[i]); \
|
||||
@@ -664,7 +664,7 @@
|
||||
static inline type const * \
|
||||
M_C(name, _front)(const array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT_INDEX(0, v->size); \
|
||||
return M_C(name, _cget)(v, 0); \
|
||||
} \
|
||||
@@ -672,7 +672,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it)(it_t it, const array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->index = 0; \
|
||||
it->array = v; \
|
||||
@@ -681,7 +681,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it_last)(it_t it, const array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (it != NULL); \
|
||||
/* If size is 0, index is -1 as unsigned, so it is greater than end */ \
|
||||
it->index = v->size - 1; \
|
||||
@@ -691,7 +691,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it_end)(it_t it, const array_t v) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(v); \
|
||||
M_ARRA4_CONTRACT(v); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->index = v->size; \
|
||||
it->array = v; \
|
||||
@@ -703,7 +703,7 @@
|
||||
M_ASSERT (it != NULL && org != NULL); \
|
||||
it->index = org->index; \
|
||||
it->array = org->array; \
|
||||
ARRAYI_CONTRACT(it->array); \
|
||||
M_ARRA4_CONTRACT(it->array); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
@@ -795,7 +795,7 @@
|
||||
\
|
||||
M_IF_METHOD2(SWAP, SET, oplist)( \
|
||||
static inline void \
|
||||
M_C(name, _special_stable_sort_noalloc) (type tab[], size_t size, type tmp[]) \
|
||||
M_C3(m_arra4_,name,_stable_sort_noalloc)(type tab[], size_t size, type tmp[]) \
|
||||
{ \
|
||||
size_t th = 4; \
|
||||
M_IF_DEBUG(type *org_tab = tab;) \
|
||||
@@ -877,7 +877,7 @@
|
||||
M_MEMORY_FULL(sizeof (type) * l->size); \
|
||||
return ; \
|
||||
} \
|
||||
M_C(name, _special_stable_sort_noalloc)(l->ptr, l->size, temp); \
|
||||
M_C3(m_arra4_,name,_stable_sort_noalloc)(l->ptr, l->size, temp); \
|
||||
M_CALL_FREE(oplist, temp); \
|
||||
} \
|
||||
,) /* IF SWAP & SET methods */ \
|
||||
@@ -890,8 +890,7 @@
|
||||
M_C(name, _get_str)(string_t str, array_t const array, \
|
||||
bool append) \
|
||||
{ \
|
||||
STRINGI_CONTRACT(str); \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
(append ? string_cat_str : string_set_str) (str, "["); \
|
||||
it_t it; \
|
||||
for (M_C(name, _it)(it, array) ; \
|
||||
@@ -903,7 +902,6 @@
|
||||
string_push_back (str, M_GET_SEPARATOR oplist); \
|
||||
} \
|
||||
string_push_back (str, ']'); \
|
||||
STRINGI_CONTRACT(str); \
|
||||
} \
|
||||
, /* no GET_STR */ ) \
|
||||
\
|
||||
@@ -911,7 +909,7 @@
|
||||
static inline void \
|
||||
M_C(name, _out_str)(FILE *file, const array_t array) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
M_ASSERT (file != NULL); \
|
||||
fputc ('[', file); \
|
||||
for (size_t i = 0; i < array->size; i++) { \
|
||||
@@ -928,7 +926,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _parse_str)(array_t array, const char str[], const char**endp) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
M_ASSERT (str != NULL); \
|
||||
M_C(name,_clean)(array); \
|
||||
bool success = false; \
|
||||
@@ -946,7 +944,7 @@
|
||||
if (b == false || c == 0) { goto exit_clear; } \
|
||||
M_C(name, _push_back)(array, item); \
|
||||
} while (c == M_GET_SEPARATOR oplist); \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
success = (c == ']'); \
|
||||
exit_clear: \
|
||||
M_CALL_CLEAR(oplist, item); \
|
||||
@@ -960,7 +958,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _in_str)(array_t array, FILE *file) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
M_ASSERT (file != NULL); \
|
||||
M_C(name,_clean)(array); \
|
||||
int c = fgetc(file); \
|
||||
@@ -978,7 +976,7 @@
|
||||
M_C(name, _push_back)(array, item); \
|
||||
} while (c == M_GET_SEPARATOR oplist); \
|
||||
M_CALL_CLEAR(oplist, item); \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
return c == ']'; \
|
||||
} \
|
||||
, /* no IN_STR & INIT */ ) \
|
||||
@@ -987,7 +985,7 @@
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _out_serial)(m_serial_write_t f, const array_t array) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_return_code_t ret; \
|
||||
m_serial_local_t local; \
|
||||
@@ -1008,7 +1006,7 @@
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _in_serial)(array_t array, m_serial_read_t f) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_return_code_t ret; \
|
||||
m_serial_local_t local; \
|
||||
@@ -1031,7 +1029,7 @@
|
||||
ret = f->m_interface->read_array_next(local, f); \
|
||||
} while (ret == M_SERIAL_OK_CONTINUE); \
|
||||
M_CALL_CLEAR(oplist, item); \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
return ret; \
|
||||
} \
|
||||
, /* no IN_SERIAL & INIT */ ) \
|
||||
@@ -1041,8 +1039,8 @@
|
||||
M_C(name, _equal_p)(const array_t array1, \
|
||||
const array_t array2) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(array1); \
|
||||
ARRAYI_CONTRACT(array2); \
|
||||
M_ARRA4_CONTRACT(array1); \
|
||||
M_ARRA4_CONTRACT(array2); \
|
||||
if (array1->size != array2->size) return false; \
|
||||
size_t i; \
|
||||
for(i = 0; i < array1->size; i++) { \
|
||||
@@ -1059,7 +1057,7 @@
|
||||
static inline size_t \
|
||||
M_C(name, _hash)(const array_t array) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(array); \
|
||||
M_ARRA4_CONTRACT(array); \
|
||||
M_HASH_DECL(hash); \
|
||||
for(size_t i = 0 ; i < array->size; i++) { \
|
||||
size_t hi = M_CALL_HASH(oplist, array->ptr[i]); \
|
||||
@@ -1072,8 +1070,8 @@
|
||||
static inline void \
|
||||
M_C(name, _splice)(array_t a1, array_t a2) \
|
||||
{ \
|
||||
ARRAYI_CONTRACT(a1); \
|
||||
ARRAYI_CONTRACT(a2); \
|
||||
M_ARRA4_CONTRACT(a1); \
|
||||
M_ARRA4_CONTRACT(a2); \
|
||||
if (M_LIKELY (a2->size > 0)) { \
|
||||
size_t newSize = a1->size + a2->size; \
|
||||
if (newSize > a1->alloc) { \
|
||||
|
||||
+111
-111
@@ -35,23 +35,23 @@ M_BEGIN_PROTECTED_CODE
|
||||
// Define the basic limb of a bitset
|
||||
typedef uint64_t bitset_limb_ct;
|
||||
// And its size in bits
|
||||
#define BITSET_LIMB_BIT (sizeof(bitset_limb_ct) * CHAR_BIT)
|
||||
#define M_B1TSET_LIMB_BIT (sizeof(bitset_limb_ct) * CHAR_BIT)
|
||||
|
||||
// bitset grow policy. n is limb size
|
||||
#define BITSETI_INC_ALLOC_SIZE(n) ((n) < 4 ? 4 : (n) * 2)
|
||||
#define M_B1TSET_INC_ALLOC_SIZE(n) ((n) < 4 ? 4 : (n) * 2)
|
||||
|
||||
// Compute the number of allocated limbs needed to handle 'n' bits.
|
||||
#define BITSETI_TO_ALLOC(n) (((n) + BITSET_LIMB_BIT - 1) / BITSET_LIMB_BIT)
|
||||
#define M_B1TSET_TO_ALLOC(n) (((n) + M_B1TSET_LIMB_BIT - 1) / M_B1TSET_LIMB_BIT)
|
||||
|
||||
// Compute the number of bits available from the allocated size in limbs
|
||||
#define BITSETI_FROM_ALLOC(n) ((n) * BITSET_LIMB_BIT)
|
||||
#define M_B1TSET_FROM_ALLOC(n) ((n) * M_B1TSET_LIMB_BIT)
|
||||
|
||||
// Contract of a bitset
|
||||
#define BITSETI_CONTRACT(t) do { \
|
||||
#define M_B1TSET_CONTRACT(t) do { \
|
||||
M_ASSERT (t != NULL); \
|
||||
M_ASSERT (t->size <= BITSETI_FROM_ALLOC (t->alloc)); \
|
||||
M_ASSERT (t->alloc <= ((size_t)-1) / BITSET_LIMB_BIT); \
|
||||
M_ASSERT (t->size < ((size_t)-1) - BITSET_LIMB_BIT); \
|
||||
M_ASSERT (t->size <= M_B1TSET_FROM_ALLOC (t->alloc)); \
|
||||
M_ASSERT (t->alloc <= ((size_t)-1) / M_B1TSET_LIMB_BIT); \
|
||||
M_ASSERT (t->size < ((size_t)-1) - M_B1TSET_LIMB_BIT); \
|
||||
M_ASSERT (t->size == 0 || t->ptr != NULL); \
|
||||
M_ASSERT (t->alloc == 0 || t->ptr != NULL); \
|
||||
} while (0)
|
||||
@@ -84,18 +84,18 @@ static inline void
|
||||
bitset_init(bitset_t t)
|
||||
{
|
||||
M_ASSERT (t != NULL);
|
||||
M_STATIC_ASSERT (M_POWEROF2_P(BITSET_LIMB_BIT), MLIB_INTERNAL, "M*LIB: BITSET LIMB shall be a power of 2.");
|
||||
M_STATIC_ASSERT (M_POWEROF2_P(M_B1TSET_LIMB_BIT), MLIB_INTERNAL, "M*LIB: BITSET LIMB shall be a power of 2.");
|
||||
t->size = 0;
|
||||
t->alloc = 0;
|
||||
t->ptr = NULL;
|
||||
BITSETI_CONTRACT(t);
|
||||
M_B1TSET_CONTRACT(t);
|
||||
}
|
||||
|
||||
/* Clean a bitset */
|
||||
static inline void
|
||||
bitset_clean(bitset_t t)
|
||||
{
|
||||
BITSETI_CONTRACT(t);
|
||||
M_B1TSET_CONTRACT(t);
|
||||
t->size = 0;
|
||||
}
|
||||
|
||||
@@ -116,11 +116,11 @@ bitset_clear(bitset_t t)
|
||||
static inline void
|
||||
bitset_set(bitset_t d, const bitset_t s)
|
||||
{
|
||||
BITSETI_CONTRACT(d);
|
||||
BITSETI_CONTRACT(s);
|
||||
M_B1TSET_CONTRACT(d);
|
||||
M_B1TSET_CONTRACT(s);
|
||||
if (M_UNLIKELY (d == s)) return;
|
||||
const size_t needAlloc = BITSETI_TO_ALLOC (s->size);
|
||||
if (s->size > BITSETI_FROM_ALLOC (d->alloc)) {
|
||||
const size_t needAlloc = M_B1TSET_TO_ALLOC (s->size);
|
||||
if (s->size > M_B1TSET_FROM_ALLOC (d->alloc)) {
|
||||
bitset_limb_ct *ptr = M_MEMORY_REALLOC (bitset_limb_ct, d->ptr, needAlloc);
|
||||
if (M_UNLIKELY (ptr == NULL)) {
|
||||
M_MEMORY_FULL(needAlloc);
|
||||
@@ -131,7 +131,7 @@ bitset_set(bitset_t d, const bitset_t s)
|
||||
}
|
||||
memcpy (d->ptr, s->ptr, needAlloc * sizeof(bitset_limb_ct) );
|
||||
d->size = s->size;
|
||||
BITSETI_CONTRACT(d);
|
||||
M_B1TSET_CONTRACT(d);
|
||||
}
|
||||
|
||||
/* Initialize & set a bitset to another one (CONSTRUCTOR) */
|
||||
@@ -147,13 +147,13 @@ bitset_init_set(bitset_t d, const bitset_t s)
|
||||
static inline void
|
||||
bitset_init_move(bitset_t d, bitset_t s)
|
||||
{
|
||||
BITSETI_CONTRACT(s);
|
||||
M_B1TSET_CONTRACT(s);
|
||||
d->size = s->size;
|
||||
d->alloc = s->alloc;
|
||||
d->ptr = s->ptr;
|
||||
s->alloc = 0;
|
||||
s->ptr = NULL;
|
||||
BITSETI_CONTRACT(d);
|
||||
M_B1TSET_CONTRACT(d);
|
||||
}
|
||||
|
||||
/* Move a bitset from another one (DESTRUCTOR) */
|
||||
@@ -168,38 +168,38 @@ bitset_move(bitset_t d, bitset_t s)
|
||||
static inline void
|
||||
bitset_set_at(bitset_t v, size_t i, bool x)
|
||||
{
|
||||
BITSETI_CONTRACT(v);
|
||||
M_B1TSET_CONTRACT(v);
|
||||
M_ASSERT (v->ptr != NULL);
|
||||
M_ASSERT_INDEX(i, v->size);
|
||||
const size_t offset = i / BITSET_LIMB_BIT;
|
||||
const size_t index = i % BITSET_LIMB_BIT;
|
||||
const size_t offset = i / M_B1TSET_LIMB_BIT;
|
||||
const size_t index = i % M_B1TSET_LIMB_BIT;
|
||||
// This is a branchless version as x can only be 0 or 1 with only one variable shift.
|
||||
const bitset_limb_ct mask = ((bitset_limb_ct)1)<<index;
|
||||
v->ptr[offset] = (v->ptr[offset] & ~mask) | (mask & (0-(bitset_limb_ct)x));
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
}
|
||||
|
||||
/* Flip the bit 'i' in the bitset */
|
||||
static inline void
|
||||
bitset_flip_at(bitset_t v, size_t i)
|
||||
{
|
||||
BITSETI_CONTRACT(v);
|
||||
M_B1TSET_CONTRACT(v);
|
||||
M_ASSERT (v->ptr != NULL);
|
||||
M_ASSERT_INDEX(i, v->size);
|
||||
size_t offset = i / BITSET_LIMB_BIT;
|
||||
size_t index = i % BITSET_LIMB_BIT;
|
||||
size_t offset = i / M_B1TSET_LIMB_BIT;
|
||||
size_t index = i % M_B1TSET_LIMB_BIT;
|
||||
v->ptr[offset] ^= ((bitset_limb_ct)1)<<index;
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
}
|
||||
|
||||
/* Push back the boolean 'x' in the bitset (increasing the bitset) */
|
||||
static inline void
|
||||
bitset_push_back (bitset_t v, bool x)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
if (v->size >= BITSETI_FROM_ALLOC (v->alloc)) {
|
||||
M_B1TSET_CONTRACT (v);
|
||||
if (v->size >= M_B1TSET_FROM_ALLOC (v->alloc)) {
|
||||
// Compute the needed allocation.
|
||||
const size_t needAlloc = BITSETI_INC_ALLOC_SIZE(v->alloc);
|
||||
const size_t needAlloc = M_B1TSET_INC_ALLOC_SIZE(v->alloc);
|
||||
// Check for integer overflow
|
||||
if (M_UNLIKELY (needAlloc <= v->alloc)) {
|
||||
M_MEMORY_FULL(needAlloc * sizeof(bitset_limb_ct));
|
||||
@@ -228,14 +228,14 @@ bitset_push_back (bitset_t v, bool x)
|
||||
static inline void
|
||||
bitset_resize (bitset_t v, size_t size)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
// Check for overflow
|
||||
if (M_UNLIKELY (size >= ((size_t)-1) - BITSET_LIMB_BIT)) {
|
||||
if (M_UNLIKELY (size >= ((size_t)-1) - M_B1TSET_LIMB_BIT)) {
|
||||
M_MEMORY_FULL((size_t) -1);
|
||||
return;
|
||||
}
|
||||
// Compute the needed allocation.
|
||||
size_t newAlloc = BITSETI_TO_ALLOC (size);
|
||||
size_t newAlloc = M_B1TSET_TO_ALLOC (size);
|
||||
if (newAlloc > v->alloc) {
|
||||
bitset_limb_ct *ptr = M_MEMORY_REALLOC (bitset_limb_ct, v->ptr, newAlloc);
|
||||
if (M_UNLIKELY (ptr == NULL) ) {
|
||||
@@ -251,16 +251,16 @@ bitset_resize (bitset_t v, size_t size)
|
||||
v->size = size;
|
||||
for( ; i < size; i++)
|
||||
bitset_set_at(v, i, 0);
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
}
|
||||
|
||||
/* Reserve allocation in the bitset to accomodate at least 'size' bits without reallocation */
|
||||
static inline void
|
||||
bitset_reserve (bitset_t v, size_t size)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
size_t oldAlloc = BITSETI_TO_ALLOC (v->size);
|
||||
size_t newAlloc = BITSETI_TO_ALLOC (size);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
size_t oldAlloc = M_B1TSET_TO_ALLOC (v->size);
|
||||
size_t newAlloc = M_B1TSET_TO_ALLOC (size);
|
||||
if (oldAlloc > newAlloc) {
|
||||
newAlloc = oldAlloc;
|
||||
}
|
||||
@@ -277,7 +277,7 @@ bitset_reserve (bitset_t v, size_t size)
|
||||
v->ptr = ptr;
|
||||
v->alloc = newAlloc;
|
||||
}
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
}
|
||||
|
||||
/* Return the value of the boolean at index 'i'.
|
||||
@@ -287,11 +287,11 @@ bitset_reserve (bitset_t v, size_t size)
|
||||
static inline bool
|
||||
bitset_get(const bitset_t v, size_t i)
|
||||
{
|
||||
BITSETI_CONTRACT(v);
|
||||
M_B1TSET_CONTRACT(v);
|
||||
M_ASSERT (v->ptr != NULL);
|
||||
M_ASSERT_INDEX(i, v->size);
|
||||
size_t offset = i / BITSET_LIMB_BIT;
|
||||
size_t index = i % BITSET_LIMB_BIT;
|
||||
size_t offset = i / M_B1TSET_LIMB_BIT;
|
||||
size_t index = i % M_B1TSET_LIMB_BIT;
|
||||
return ( v->ptr[offset] & (((bitset_limb_ct)1) << index) ) != 0;
|
||||
}
|
||||
|
||||
@@ -302,21 +302,21 @@ bitset_get(const bitset_t v, size_t i)
|
||||
static inline void
|
||||
bitset_pop_back(bool *dest, bitset_t v)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
M_ASSERT_INDEX (0, v->size);
|
||||
if (dest) {
|
||||
*dest = bitset_get (v, v->size - 1);
|
||||
}
|
||||
v->size--;
|
||||
// Last popped bit is not cleared
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
}
|
||||
|
||||
/* Return the front bit value in the bitset */
|
||||
static inline bool
|
||||
bitset_front(bitset_t v)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
M_ASSERT_INDEX (0, v->size);
|
||||
return bitset_get(v, 0);
|
||||
}
|
||||
@@ -325,7 +325,7 @@ bitset_front(bitset_t v)
|
||||
static inline bool
|
||||
bitset_back(bitset_t v)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
M_ASSERT_INDEX (0, v->size);
|
||||
return bitset_get(v, v->size-1);
|
||||
}
|
||||
@@ -334,7 +334,7 @@ bitset_back(bitset_t v)
|
||||
static inline bool
|
||||
bitset_empty_p(bitset_t v)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
return v->size == 0;
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ bitset_empty_p(bitset_t v)
|
||||
static inline size_t
|
||||
bitset_size(bitset_t v)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
return v->size;
|
||||
}
|
||||
|
||||
@@ -350,15 +350,15 @@ bitset_size(bitset_t v)
|
||||
static inline size_t
|
||||
bitset_capacity(bitset_t v)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
return BITSETI_FROM_ALLOC (v->alloc);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
return M_B1TSET_FROM_ALLOC (v->alloc);
|
||||
}
|
||||
|
||||
/* Swap the bit at index i and j of the bitset */
|
||||
static inline void
|
||||
bitset_swap_at (bitset_t v, size_t i, size_t j)
|
||||
{
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
M_ASSERT_INDEX(i, v->size);
|
||||
M_ASSERT_INDEX(j, v->size);
|
||||
|
||||
@@ -366,15 +366,15 @@ bitset_swap_at (bitset_t v, size_t i, size_t j)
|
||||
bool j_val = bitset_get(v, j);
|
||||
bitset_set_at (v, i, j_val);
|
||||
bitset_set_at (v, j, i_val);
|
||||
BITSETI_CONTRACT (v);
|
||||
M_B1TSET_CONTRACT (v);
|
||||
}
|
||||
|
||||
/* Swap the bitsets */
|
||||
static inline void
|
||||
bitset_swap (bitset_t v1, bitset_t v2)
|
||||
{
|
||||
BITSETI_CONTRACT (v1);
|
||||
BITSETI_CONTRACT (v2);
|
||||
M_B1TSET_CONTRACT (v1);
|
||||
M_B1TSET_CONTRACT (v2);
|
||||
M_SWAP (size_t, v1->size, v2->size);
|
||||
M_SWAP (size_t, v1->alloc, v2->alloc);
|
||||
M_SWAP (bitset_limb_ct *, v1->ptr, v2->ptr);
|
||||
@@ -385,12 +385,12 @@ bitset_swap (bitset_t v1, bitset_t v2)
|
||||
* Return the new carry.
|
||||
*/
|
||||
static inline bitset_limb_ct
|
||||
bitseti_lshift(bitset_limb_ct ptr[], size_t n, bitset_limb_ct carry)
|
||||
M_B1TSET_lshift(bitset_limb_ct ptr[], size_t n, bitset_limb_ct carry)
|
||||
{
|
||||
for(size_t i = 0; i < n; i++) {
|
||||
bitset_limb_ct v = ptr[i];
|
||||
ptr[i] = (v << 1) | carry;
|
||||
carry = (v >> (BITSET_LIMB_BIT-1) );
|
||||
carry = (v >> (M_B1TSET_LIMB_BIT-1) );
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
@@ -400,11 +400,11 @@ bitseti_lshift(bitset_limb_ct ptr[], size_t n, bitset_limb_ct carry)
|
||||
* Return the new carry.
|
||||
*/
|
||||
static inline bitset_limb_ct
|
||||
bitseti_rshift(bitset_limb_ct ptr[], size_t n, bitset_limb_ct carry)
|
||||
M_B1TSET_rshift(bitset_limb_ct ptr[], size_t n, bitset_limb_ct carry)
|
||||
{
|
||||
for(size_t i = n - 1; i < n; i--) {
|
||||
bitset_limb_ct v = ptr[i];
|
||||
v = (v >> 1) | (carry << (BITSET_LIMB_BIT-1) );
|
||||
v = (v >> 1) | (carry << (M_B1TSET_LIMB_BIT-1) );
|
||||
carry = v & 1;
|
||||
}
|
||||
return carry;
|
||||
@@ -414,26 +414,26 @@ bitseti_rshift(bitset_limb_ct ptr[], size_t n, bitset_limb_ct carry)
|
||||
static inline void
|
||||
bitset_push_at(bitset_t set, size_t key, bool value)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
// First push another value to extend the array to the right size
|
||||
bitset_push_back(set, false);
|
||||
M_ASSERT (set->ptr != NULL);
|
||||
M_ASSERT_INDEX(key, set->size);
|
||||
|
||||
// Then shift it
|
||||
size_t offset = key / BITSET_LIMB_BIT;
|
||||
size_t index = key % BITSET_LIMB_BIT;
|
||||
size_t offset = key / M_B1TSET_LIMB_BIT;
|
||||
size_t index = key % M_B1TSET_LIMB_BIT;
|
||||
bitset_limb_ct v = set->ptr[offset];
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1)<<index)-1;
|
||||
bitset_limb_ct carry = (v >> (BITSET_LIMB_BIT-1) );
|
||||
bitset_limb_ct carry = (v >> (M_B1TSET_LIMB_BIT-1) );
|
||||
v = (v & mask) | ((unsigned int) value << index) | ((v & ~mask) << 1);
|
||||
set->ptr[offset] = v;
|
||||
size_t size = (set->size + BITSET_LIMB_BIT - 1) / BITSET_LIMB_BIT;
|
||||
size_t size = (set->size + M_B1TSET_LIMB_BIT - 1) / M_B1TSET_LIMB_BIT;
|
||||
M_ASSERT (size >= offset + 1);
|
||||
v = bitseti_lshift(&set->ptr[offset+1], size - offset - 1, carry);
|
||||
v = M_B1TSET_lshift(&set->ptr[offset+1], size - offset - 1, carry);
|
||||
// v is unused.
|
||||
(void) v;
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
}
|
||||
|
||||
/* Pop a new bit at position 'key' in the bitset
|
||||
@@ -441,7 +441,7 @@ bitset_push_at(bitset_t set, size_t key, bool value)
|
||||
static inline void
|
||||
bitset_pop_at(bool *dest, bitset_t set, size_t key)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
M_ASSERT (set->ptr != NULL);
|
||||
M_ASSERT_INDEX(key, set->size);
|
||||
|
||||
@@ -449,36 +449,36 @@ bitset_pop_at(bool *dest, bitset_t set, size_t key)
|
||||
*dest = bitset_get (set, key);
|
||||
}
|
||||
// Shift it
|
||||
size_t offset = key / BITSET_LIMB_BIT;
|
||||
size_t index = key % BITSET_LIMB_BIT;
|
||||
size_t size = (set->size + BITSET_LIMB_BIT - 1) / BITSET_LIMB_BIT;
|
||||
size_t offset = key / M_B1TSET_LIMB_BIT;
|
||||
size_t index = key % M_B1TSET_LIMB_BIT;
|
||||
size_t size = (set->size + M_B1TSET_LIMB_BIT - 1) / M_B1TSET_LIMB_BIT;
|
||||
bitset_limb_ct v, mask, carry;
|
||||
carry = bitseti_rshift(&set->ptr[offset+1], size - offset - 1, false);
|
||||
carry = M_B1TSET_rshift(&set->ptr[offset+1], size - offset - 1, false);
|
||||
v = set->ptr[offset];
|
||||
mask = (((bitset_limb_ct)1)<<index)-1;
|
||||
v = (v & mask) | ((v>>1) & ~mask) | (carry << (BITSET_LIMB_BIT-1)) ;
|
||||
v = (v & mask) | ((v>>1) & ~mask) | (carry << (M_B1TSET_LIMB_BIT-1)) ;
|
||||
set->ptr[offset] = v;
|
||||
// Decrease size
|
||||
set->size --;
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
}
|
||||
|
||||
/* Test if two bitsets are equal */
|
||||
static inline bool
|
||||
bitset_equal_p (const bitset_t set1, const bitset_t set2)
|
||||
{
|
||||
BITSETI_CONTRACT (set1);
|
||||
BITSETI_CONTRACT (set2);
|
||||
M_B1TSET_CONTRACT (set1);
|
||||
M_B1TSET_CONTRACT (set2);
|
||||
if (set1->size != set2->size)
|
||||
return false;
|
||||
/* We won't compare each bit individualy,
|
||||
but instead compare them per limb */
|
||||
const size_t limbSize = (set1->size) / BITSET_LIMB_BIT;
|
||||
const size_t limbSize = (set1->size) / M_B1TSET_LIMB_BIT;
|
||||
for(size_t i = 0 ; i < limbSize;i++)
|
||||
if (set1->ptr[i] != set2->ptr[i])
|
||||
return false;
|
||||
/* Compare the last limb if needed */
|
||||
const size_t index = set1->size % BITSET_LIMB_BIT;
|
||||
const size_t index = set1->size % M_B1TSET_LIMB_BIT;
|
||||
if (index > 0) {
|
||||
const bitset_limb_ct mask = (((bitset_limb_ct)1) << index) - 1;
|
||||
if ((set1->ptr[limbSize] & mask) != (set2->ptr[limbSize] & mask))
|
||||
@@ -491,7 +491,7 @@ bitset_equal_p (const bitset_t set1, const bitset_t set2)
|
||||
static inline void
|
||||
bitset_it(bitset_it_t it, bitset_t set)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
it->index = 0;
|
||||
it->set = set;
|
||||
}
|
||||
@@ -509,7 +509,7 @@ bitset_it_set(bitset_it_t it, const bitset_it_t itorg)
|
||||
static inline void
|
||||
bitset_it_last(bitset_it_t it, bitset_t set)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
it->index = set->size-1;
|
||||
it->set = set;
|
||||
}
|
||||
@@ -518,7 +518,7 @@ bitset_it_last(bitset_it_t it, bitset_t set)
|
||||
static inline void
|
||||
bitset_it_end(bitset_it_t it, bitset_t set)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
it->index = set->size;
|
||||
it->set = set;
|
||||
}
|
||||
@@ -581,7 +581,7 @@ bitset_cref(bitset_it_t it)
|
||||
static inline void
|
||||
bitset_out_str(FILE *file, const bitset_t set)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
M_ASSERT(file != NULL);
|
||||
fputc ('[', file);
|
||||
for(size_t i = 0; i < set->size; i++) {
|
||||
@@ -596,7 +596,7 @@ bitset_out_str(FILE *file, const bitset_t set)
|
||||
static inline bool
|
||||
bitset_in_str(bitset_t set, FILE *file)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
M_ASSERT(file != NULL);
|
||||
bitset_clean(set);
|
||||
int c = fgetc(file);
|
||||
@@ -607,7 +607,7 @@ bitset_in_str(bitset_t set, FILE *file)
|
||||
bitset_push_back (set, b);
|
||||
c = fgetc(file);
|
||||
}
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
return c == ']';
|
||||
}
|
||||
|
||||
@@ -615,7 +615,7 @@ bitset_in_str(bitset_t set, FILE *file)
|
||||
static inline bool
|
||||
bitset_parse_str(bitset_t set, const char str[], const char **endptr)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
M_ASSERT(str != NULL);
|
||||
bool success = false;
|
||||
bitset_clean(set);
|
||||
@@ -628,7 +628,7 @@ bitset_parse_str(bitset_t set, const char str[], const char **endptr)
|
||||
bitset_push_back (set, b);
|
||||
c = *str++;
|
||||
} while (c != ']' && c != 0);
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
success = (c == ']');
|
||||
exit:
|
||||
if (endptr) *endptr = str;
|
||||
@@ -647,11 +647,11 @@ bitset_set_str(bitset_t dest, const char str[])
|
||||
static inline void
|
||||
bitset_and(bitset_t dest, const bitset_t src)
|
||||
{
|
||||
BITSETI_CONTRACT(dest);
|
||||
BITSETI_CONTRACT(src);
|
||||
M_B1TSET_CONTRACT(dest);
|
||||
M_B1TSET_CONTRACT(src);
|
||||
size_t s = M_MIN(dest->size, src->size);
|
||||
size_t n = s / BITSET_LIMB_BIT;
|
||||
size_t m = s % BITSET_LIMB_BIT;
|
||||
size_t n = s / M_B1TSET_LIMB_BIT;
|
||||
size_t m = s % M_B1TSET_LIMB_BIT;
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
dest->ptr[i] &= src->ptr[i];
|
||||
if (m) {
|
||||
@@ -659,7 +659,7 @@ bitset_and(bitset_t dest, const bitset_t src)
|
||||
dest->ptr[n] = (dest->ptr[n] & src->ptr[n]) & mask;
|
||||
}
|
||||
dest->size = s;
|
||||
BITSETI_CONTRACT(dest);
|
||||
M_B1TSET_CONTRACT(dest);
|
||||
}
|
||||
|
||||
/* Perform an OR operation between the bitsets,
|
||||
@@ -667,11 +667,11 @@ bitset_and(bitset_t dest, const bitset_t src)
|
||||
static inline void
|
||||
bitset_or(bitset_t dest, const bitset_t src)
|
||||
{
|
||||
BITSETI_CONTRACT(dest);
|
||||
BITSETI_CONTRACT(src);
|
||||
M_B1TSET_CONTRACT(dest);
|
||||
M_B1TSET_CONTRACT(src);
|
||||
size_t s = M_MIN(dest->size, src->size);
|
||||
size_t n = s / BITSET_LIMB_BIT;
|
||||
size_t m = s % BITSET_LIMB_BIT;
|
||||
size_t n = s / M_B1TSET_LIMB_BIT;
|
||||
size_t m = s % M_B1TSET_LIMB_BIT;
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
dest->ptr[i] |= src->ptr[i];
|
||||
if (m) {
|
||||
@@ -679,7 +679,7 @@ bitset_or(bitset_t dest, const bitset_t src)
|
||||
dest->ptr[n] = (dest->ptr[n] | src->ptr[n]) & mask;
|
||||
}
|
||||
dest->size = s;
|
||||
BITSETI_CONTRACT(dest);
|
||||
M_B1TSET_CONTRACT(dest);
|
||||
}
|
||||
|
||||
/* Perform an XOR operation between the bitsets,
|
||||
@@ -687,11 +687,11 @@ bitset_or(bitset_t dest, const bitset_t src)
|
||||
static inline void
|
||||
bitset_xor(bitset_t dest, const bitset_t src)
|
||||
{
|
||||
BITSETI_CONTRACT(dest);
|
||||
BITSETI_CONTRACT(src);
|
||||
M_B1TSET_CONTRACT(dest);
|
||||
M_B1TSET_CONTRACT(src);
|
||||
size_t s = M_MIN(dest->size, src->size);
|
||||
size_t n = s / BITSET_LIMB_BIT;
|
||||
size_t m = s % BITSET_LIMB_BIT;
|
||||
size_t n = s / M_B1TSET_LIMB_BIT;
|
||||
size_t m = s % M_B1TSET_LIMB_BIT;
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
dest->ptr[i] ^= src->ptr[i];
|
||||
if (m) {
|
||||
@@ -699,17 +699,17 @@ bitset_xor(bitset_t dest, const bitset_t src)
|
||||
dest->ptr[n] = (dest->ptr[n] ^ src->ptr[n]) & mask;
|
||||
}
|
||||
dest->size = s;
|
||||
BITSETI_CONTRACT(dest);
|
||||
M_B1TSET_CONTRACT(dest);
|
||||
}
|
||||
|
||||
/* Perform a NOT operation of the bitset */
|
||||
static inline void
|
||||
bitset_not(bitset_t dest)
|
||||
{
|
||||
BITSETI_CONTRACT(dest);
|
||||
M_B1TSET_CONTRACT(dest);
|
||||
size_t s = dest->size;
|
||||
size_t n = s / BITSET_LIMB_BIT;
|
||||
size_t m = s % BITSET_LIMB_BIT;
|
||||
size_t n = s / M_B1TSET_LIMB_BIT;
|
||||
size_t m = s % M_B1TSET_LIMB_BIT;
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
dest->ptr[i] = ~ (dest->ptr[i]);
|
||||
if (m) {
|
||||
@@ -717,17 +717,17 @@ bitset_not(bitset_t dest)
|
||||
dest->ptr[n] = (~ dest->ptr[n]) & mask;
|
||||
}
|
||||
dest->size = s;
|
||||
BITSETI_CONTRACT(dest);
|
||||
M_B1TSET_CONTRACT(dest);
|
||||
}
|
||||
|
||||
/* Copute a hash of the bitset */
|
||||
static inline size_t
|
||||
bitset_hash(const bitset_t set)
|
||||
{
|
||||
BITSETI_CONTRACT(set);
|
||||
M_B1TSET_CONTRACT(set);
|
||||
size_t s = set->size;
|
||||
size_t n = s / BITSET_LIMB_BIT;
|
||||
size_t m = s % BITSET_LIMB_BIT;
|
||||
size_t n = s / M_B1TSET_LIMB_BIT;
|
||||
size_t m = s % M_B1TSET_LIMB_BIT;
|
||||
M_HASH_DECL(hash);
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
M_HASH_UP(hash, set->ptr[i]);
|
||||
@@ -742,25 +742,25 @@ bitset_hash(const bitset_t set)
|
||||
static inline size_t
|
||||
bitset_clz(const bitset_t set)
|
||||
{
|
||||
BITSETI_CONTRACT(set);
|
||||
M_B1TSET_CONTRACT(set);
|
||||
size_t s = set->size;
|
||||
M_ASSERT_INDEX (0, s); // TBC: Special case to handle?
|
||||
size_t n = (s -1) / BITSET_LIMB_BIT;
|
||||
size_t m = s % BITSET_LIMB_BIT;
|
||||
size_t n = (s -1) / M_B1TSET_LIMB_BIT;
|
||||
size_t m = s % M_B1TSET_LIMB_BIT;
|
||||
bitset_limb_ct limb = set->ptr[n];
|
||||
if (m) {
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1) << m) - 1;
|
||||
limb &= mask;
|
||||
} else {
|
||||
m = BITSET_LIMB_BIT;
|
||||
m = M_B1TSET_LIMB_BIT;
|
||||
}
|
||||
s = 0;
|
||||
while (limb == 0 && n > 0) {
|
||||
s += m;
|
||||
limb = set->ptr[--n];
|
||||
m = BITSET_LIMB_BIT;
|
||||
m = M_B1TSET_LIMB_BIT;
|
||||
}
|
||||
s += m_core_clz64(limb) - (BITSET_LIMB_BIT - m);
|
||||
s += m_core_clz64(limb) - (M_B1TSET_LIMB_BIT - m);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -815,7 +815,7 @@ bitset_clz(const bitset_t set)
|
||||
static inline void
|
||||
bitset_get_str(string_t str, const bitset_t set, bool append)
|
||||
{
|
||||
BITSETI_CONTRACT (set);
|
||||
M_B1TSET_CONTRACT (set);
|
||||
M_ASSERT(str != NULL);
|
||||
(append ? string_cat_str : string_set_str) (str, "[");
|
||||
for(size_t i = 0; i < set->size; i++) {
|
||||
|
||||
+83
-83
@@ -47,7 +47,7 @@
|
||||
*/
|
||||
#define BPTREE_DEF2_AS(name, name_t, it_t, itref_t, N, key_type, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BPTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_BPTR33_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, N, key_type, M_GLOBAL_OPLIST_OR_DEF(key_type)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 1, 0, name_t, M_C(name, _node_ct), M_C(name, _pit_ct), it_t, itref_t ), \
|
||||
(name, N, key_type, __VA_ARGS__, 1, 0, name_t, M_C(name, _node_ct), M_C(name, _pit_ct), it_t, itref_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
@@ -65,7 +65,7 @@
|
||||
USAGE: BPTREE_DEF_AS(name, name_t, it_t, N, type, [, oplist_of_the_type]) */
|
||||
#define BPTREE_DEF_AS(name, name_t, it_t, N, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BPTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_BPTR33_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, N, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 0, 0, name_t, M_C(name, _node_ct), M_C(name, _pit_ct), it_t, M_C(name, _itref_ct) ), \
|
||||
(name, N, __VA_ARGS__, __VA_ARGS__, 0, 0, name_t, M_C(name, _node_ct), M_C(name, _pit_ct), it_t, M_C(name, _itref_ct) ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
@@ -93,7 +93,7 @@
|
||||
*/
|
||||
#define BPTREE_MULTI_DEF2_AS(name, name_t, it_t, itref_t, N, key_type, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BPTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_BPTR33_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, N, key_type, M_GLOBAL_OPLIST_OR_DEF(key_type)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 1, 1, name_t, M_C(name, _node_ct), M_C(name, _pit_ct), it_t, itref_t ), \
|
||||
(name, N, key_type, __VA_ARGS__, 1, 1, name_t, M_C(name, _node_ct), M_C(name, _pit_ct), it_t, itref_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
@@ -113,7 +113,7 @@
|
||||
USAGE: BPTREE_MULTI_DEF_AS(name, name_t, it_t, N, type, [, oplist_of_the_type]) */
|
||||
#define BPTREE_MULTI_DEF_AS(name, name_t, it_t, N, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BPTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_BPTR33_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, N, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 0, 1, name_t, M_C(name, _node_ct), M_C(name, _pit_ct), it_t, M_C(name, _itref_ct) ), \
|
||||
(name, N, __VA_ARGS__, __VA_ARGS__, 0, 1, name_t, M_C(name, _node_ct), M_C(name, _pit_ct), it_t, M_C(name, _itref_ct) ))) \
|
||||
M_BEGIN_PROTECTED_CODE
|
||||
@@ -122,7 +122,7 @@
|
||||
/* Define the oplist of a B+TREE used as a set of type (from BPTREE_DEF).
|
||||
USAGE: BPTREE_OPLIST(name [, oplist_of_the_type]) */
|
||||
#define BPTREE_OPLIST(...) \
|
||||
BPTREEI_KEY_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_BPTR33_KEY_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST ), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
by algorithm.
|
||||
*/
|
||||
#define BPTREE_OPLIST2(...) \
|
||||
BPTREEI_OPLIST2_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_BPTR33_OPLIST2_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST ), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -143,18 +143,18 @@
|
||||
|
||||
/* Deferred evaluation for the oplist definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define BPTREEI_KEY_OPLIST_P1(arg) BPTREEI_KEY_OPLIST_P2 arg
|
||||
#define M_BPTR33_KEY_OPLIST_P1(arg) M_BPTR33_KEY_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplists */
|
||||
#define BPTREEI_KEY_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(BPTREEI_KEY_OPLIST_P3, BPTREEI_KEY_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_BPTR33_KEY_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_BPTR33_KEY_OPLIST_P3, M_BPTR33_KEY_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define BPTREEI_KEY_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_BPTR33_KEY_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_BPTREE_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* OPLIST definition of a b+tree */
|
||||
#define BPTREEI_KEY_OPLIST_P3(name, oplist) \
|
||||
#define M_BPTR33_KEY_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _init)), \
|
||||
INIT_SET(M_C(name, _init_set)), \
|
||||
INIT_WITH(API_1(M_INIT_VAI)), \
|
||||
@@ -192,20 +192,20 @@
|
||||
)
|
||||
|
||||
/* Deferred evaluation */
|
||||
#define BPTREEI_OPLIST2_P1(arg) BPTREEI_OPLIST2_P2 arg
|
||||
#define M_BPTR33_OPLIST2_P1(arg) M_BPTR33_OPLIST2_P2 arg
|
||||
|
||||
/* Validation of the given oplists (first the key oplist, then the value oplist) */
|
||||
#define BPTREEI_OPLIST2_P2(name, key_oplist, value_oplist) \
|
||||
M_IF_OPLIST(key_oplist)(BPTREEI_OPLIST2_P3, BPTREEI_OPLIST2_FAILURE)(name, key_oplist, value_oplist)
|
||||
#define BPTREEI_OPLIST2_P3(name, key_oplist, value_oplist) \
|
||||
M_IF_OPLIST(value_oplist)(BPTREEI_OPLIST2_P4, BPTREEI_OPLIST2_FAILURE)(name, key_oplist, value_oplist)
|
||||
#define M_BPTR33_OPLIST2_P2(name, key_oplist, value_oplist) \
|
||||
M_IF_OPLIST(key_oplist)(M_BPTR33_OPLIST2_P3, M_BPTR33_OPLIST2_FAILURE)(name, key_oplist, value_oplist)
|
||||
#define M_BPTR33_OPLIST2_P3(name, key_oplist, value_oplist) \
|
||||
M_IF_OPLIST(value_oplist)(M_BPTR33_OPLIST2_P4, M_BPTR33_OPLIST2_FAILURE)(name, key_oplist, value_oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define BPTREEI_OPLIST2_FAILURE(name, key_oplist, value_oplist) \
|
||||
#define M_BPTR33_OPLIST2_FAILURE(name, key_oplist, value_oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_BPTREE_OPLIST_IS_NOT_AN_OPLIST, name, key_oplist, value_oplist)))
|
||||
|
||||
/* Final definition of the oplist */
|
||||
#define BPTREEI_OPLIST2_P4(name, key_oplist, value_oplist) \
|
||||
#define M_BPTR33_OPLIST2_P4(name, key_oplist, value_oplist) \
|
||||
(INIT(M_C(name, _init)), \
|
||||
INIT_SET(M_C(name, _init_set)), \
|
||||
INIT_WITH(API_1(M_INIT_KEY_VAI)), \
|
||||
@@ -252,9 +252,9 @@
|
||||
|
||||
/* Internal contract of a B+TREE of size 'N' for a node 'node' or root 'root' */
|
||||
#ifdef NDEBUG
|
||||
# define BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, node, root) do { } while (0)
|
||||
# define M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, node, root) do { } while (0)
|
||||
#else
|
||||
# define BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, node, root) do { \
|
||||
# define M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, node, root) do { \
|
||||
M_ASSERT ((node) != NULL); \
|
||||
M_ASSERT ((root) != NULL); \
|
||||
int num2 = (node)->num; \
|
||||
@@ -283,9 +283,9 @@
|
||||
#endif
|
||||
|
||||
/* Contract for a B+TREE of size N named 'b' */
|
||||
#define BPTREEI_CONTRACT(N, isMulti, key_oplist, b) do { \
|
||||
#define M_BPTR33_CONTRACT(N, isMulti, key_oplist, b) do { \
|
||||
M_ASSERT (N >= 3); /* TBC: 2 instead ? */ \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, (b)->root, (b)->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, (b)->root, (b)->root); \
|
||||
M_ASSERT ((b)->root->next == NULL); \
|
||||
if ((b)->root->num <= 0) M_ASSERT (-(b)->root->num == (int) (b)->size); \
|
||||
} while (0)
|
||||
@@ -298,22 +298,22 @@
|
||||
Ceil(Log2(2 ^ (CHAR_BIT*sizeof (size_t)))) + 1
|
||||
"+ 1" due to final line composed of nodes.
|
||||
*/
|
||||
#define BPTREEI_MAX_STACK ((int)(1 + CHAR_BIT*sizeof (size_t)))
|
||||
#define M_BPTR33_MAX_STACK ((int)(1 + CHAR_BIT*sizeof (size_t)))
|
||||
|
||||
/* Deferred evaluation for the b+tree definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define BPTREEI_DEF_P1(arg) BPTREEI_DEF_P2 arg
|
||||
#define M_BPTR33_DEF_P1(arg) M_BPTR33_DEF_P2 arg
|
||||
|
||||
/* Validate the key oplist before going further */
|
||||
#define BPTREEI_DEF_P2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
M_IF_OPLIST(key_oplist)(BPTREEI_DEF_P3, BPTREEI_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
#define M_BPTR33_DEF_P2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
M_IF_OPLIST(key_oplist)(M_BPTR33_DEF_P3, M_BPTR33_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
|
||||
/* Validate the value oplist before going further */
|
||||
#define BPTREEI_DEF_P3(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
M_IF_OPLIST(value_oplist)(BPTREEI_DEF_P4, BPTREEI_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
#define M_BPTR33_DEF_P3(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
M_IF_OPLIST(value_oplist)(M_BPTR33_DEF_P4, M_BPTR33_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define BPTREEI_DEF_FAILURE(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
#define M_BPTR33_DEF_FAILURE(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(BPTREE*_DEF): one of the given argument is not a valid oplist: " M_AS_STR(key_oplist) " / " M_AS_STR(value_oplist))
|
||||
|
||||
/* Internal b+tree definition
|
||||
@@ -331,7 +331,7 @@
|
||||
- pit_t: alias for internal parent iterator
|
||||
- subtype_t: alias for the type referenced by the iterator
|
||||
*/
|
||||
#define BPTREEI_DEF_P4(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
#define M_BPTR33_DEF_P4(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
\
|
||||
M_IF(isMap)( \
|
||||
/* Type returned by the iterator. Due to having key and value \
|
||||
@@ -377,7 +377,7 @@
|
||||
/* Define the Parent Tree Iterator */ \
|
||||
typedef struct M_C(name, _parent_it_s) { \
|
||||
int num; \
|
||||
node_t parent[BPTREEI_MAX_STACK]; \
|
||||
node_t parent[M_BPTR33_MAX_STACK]; \
|
||||
} pit_t[1]; \
|
||||
\
|
||||
/* Define the Iterator */ \
|
||||
@@ -409,7 +409,7 @@
|
||||
{ \
|
||||
b->root = M_C(name, _new_node)(); \
|
||||
b->size = 0; \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
} \
|
||||
\
|
||||
static inline bool M_C(name, _is_leaf)(const node_t n) \
|
||||
@@ -430,7 +430,7 @@
|
||||
\
|
||||
static inline void M_C(name, _clean)(tree_t b) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
node_t next, n = b->root; \
|
||||
pit_t pit; \
|
||||
/* np is the heigh of the tree */ \
|
||||
@@ -438,11 +438,11 @@
|
||||
/* Scan down the nodes to the left down node */ \
|
||||
while (!M_C(name, _is_leaf)(n)) { \
|
||||
pit->parent[np++] = n; \
|
||||
M_ASSERT (np <= BPTREEI_MAX_STACK); \
|
||||
M_ASSERT (np <= M_BPTR33_MAX_STACK); \
|
||||
n = n->kind.node[0]; \
|
||||
} \
|
||||
pit->parent[np++] = n; \
|
||||
M_ASSERT (np <= BPTREEI_MAX_STACK); \
|
||||
M_ASSERT (np <= M_BPTR33_MAX_STACK); \
|
||||
/* Clean & free non root */ \
|
||||
for(int i = 0; i < np; i++) { \
|
||||
n = pit->parent[i]; \
|
||||
@@ -468,12 +468,12 @@
|
||||
/* Clean root */ \
|
||||
b->root->num = 0; \
|
||||
b->size = 0; \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _clear)(tree_t b) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_C(name, _clean)(b); \
|
||||
/* Once the tree is clean, only the root remains */ \
|
||||
M_CALL_DEL(key_oplist, b->root); \
|
||||
@@ -523,18 +523,18 @@
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, n, (o==root) ? n : root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, n, (o==root) ? n : root); \
|
||||
return n; \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _init_set)(tree_t b, const tree_t o) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, o); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, o); \
|
||||
M_ASSERT (b != NULL); \
|
||||
/* Just copy recursively the root node */ \
|
||||
b->root = M_C(name, _copy_node)(o->root, o->root); \
|
||||
b->size = o->size; \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _set)(tree_t b, const tree_t o) \
|
||||
@@ -547,14 +547,14 @@
|
||||
\
|
||||
static inline bool M_C(name, _empty_p)(const tree_t b) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
/* root shall be an empty leaf */ \
|
||||
return b->size == 0; \
|
||||
} \
|
||||
\
|
||||
static inline size_t M_C(name, _size)(const tree_t b) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
return b->size; \
|
||||
} \
|
||||
\
|
||||
@@ -562,10 +562,10 @@
|
||||
{ \
|
||||
node_t n = b->root; \
|
||||
int np = 0; \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \
|
||||
/* Go down the tree while searching for key */ \
|
||||
while (!M_C(name, _is_leaf)(n)) { \
|
||||
M_ASSERT (np <= BPTREEI_MAX_STACK); \
|
||||
M_ASSERT (np <= M_BPTR33_MAX_STACK); \
|
||||
int i, hi = n->num; \
|
||||
M_ASSERT (hi > 0); \
|
||||
/* Linear search is usually faster than binary search for \
|
||||
@@ -581,7 +581,7 @@
|
||||
/* Select the new node to go down to */ \
|
||||
n = n->kind.node[i]; \
|
||||
M_ASSERT (n != NULL); \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \
|
||||
} \
|
||||
pit->num = np; \
|
||||
return n; \
|
||||
@@ -589,12 +589,12 @@
|
||||
\
|
||||
static inline value_t *M_C(name, _get)(const tree_t b, key_t const key) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
pit_t pit; \
|
||||
/* Get the leaf node where the key can be */ \
|
||||
node_t n = M_C(name, _search_for_leaf)(pit, b, key); \
|
||||
int cmp = 0; \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \
|
||||
/* Search in the leaf for key */ \
|
||||
for(int i = 0; cmp >= 0 && i < -n->num; i++) { \
|
||||
cmp = M_CALL_CMP(key_oplist, key, n->key[i]); \
|
||||
@@ -672,7 +672,7 @@
|
||||
M_IF(isMap)(M_DEFERRED_COMMA value_t const value,)) \
|
||||
{ \
|
||||
pit_t pit; \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
node_t leaf = M_C(name, _search_for_leaf)(pit, b, key); \
|
||||
/* Insert key into the leaf.*/ \
|
||||
/* NOTE: Even if there is N elements, we can still add one more.*/ \
|
||||
@@ -680,7 +680,7 @@
|
||||
if (i < 0) { \
|
||||
/* Nothing to do anymore. key already exists in the tree. \
|
||||
value has been updated if needed */ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
return; \
|
||||
} \
|
||||
b->size ++; \
|
||||
@@ -689,7 +689,7 @@
|
||||
M_ASSERT (num > 0); \
|
||||
if (M_LIKELY (num <= N)) { \
|
||||
/* nothing more to do */ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
return; \
|
||||
} \
|
||||
M_ASSERT (num == N+1); \
|
||||
@@ -706,8 +706,8 @@
|
||||
nleaf->num = -nnum; \
|
||||
nleaf->next = leaf->next; \
|
||||
leaf->next = nleaf; \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, leaf, b->root); \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, nleaf, b->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, leaf, b->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, nleaf, b->root); \
|
||||
/* Update parent to inject *key_ptr that splits between (leaf, nleaf) */ \
|
||||
key_t *key_ptr = &leaf->key[num-1]; \
|
||||
while (true) { \
|
||||
@@ -720,7 +720,7 @@
|
||||
parent->kind.node[0] = leaf; \
|
||||
parent->kind.node[1] = nleaf; \
|
||||
b->root = parent; \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
return; \
|
||||
} \
|
||||
/* Non root node. Get the parent node */ \
|
||||
@@ -731,7 +731,7 @@
|
||||
parent->kind.node[i+1] = nleaf; \
|
||||
/* Test if parent node is full? */ \
|
||||
if (M_LIKELY (parent->num <= N)) { \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
return; /* No need to split parent.*/ \
|
||||
} \
|
||||
M_ASSERT (parent->num == N+1); \
|
||||
@@ -748,8 +748,8 @@
|
||||
nparent->num = nnp; \
|
||||
nparent->next = parent->next; \
|
||||
parent->next = nparent; \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, parent, b->root); \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, nparent, b->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, parent, b->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, nparent, b->root); \
|
||||
/* Prepare for the next step */ \
|
||||
key_ptr = &parent->key[np]; \
|
||||
leaf = parent; \
|
||||
@@ -896,7 +896,7 @@
|
||||
\
|
||||
static inline bool M_C(name, _erase)(tree_t b, key_t const key) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
pit_t pit; \
|
||||
node_t leaf = M_C(name, _search_for_leaf)(pit, b, key); \
|
||||
int k = M_C(name, _search_and_remove_in_leaf)(leaf, key); \
|
||||
@@ -965,7 +965,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it)(it_t it, const tree_t b) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_ASSERT (it != NULL); \
|
||||
node_t n = b->root; \
|
||||
/* Scan down the nodes */ \
|
||||
@@ -979,7 +979,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it_end)(it_t it, const tree_t b) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_ASSERT (it != NULL); \
|
||||
node_t n = b->root; \
|
||||
/* Scan down the nodes */ \
|
||||
@@ -1047,13 +1047,13 @@
|
||||
static inline void \
|
||||
M_C(name, _it_from)(it_t it, const tree_t b, key_t const key) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_ASSERT (it != NULL); \
|
||||
pit_t pit; \
|
||||
node_t n = M_C(name, _search_for_leaf)(pit, b, key); \
|
||||
it->node = n; \
|
||||
int i; \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \
|
||||
M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \
|
||||
for(i = 0; i < -n->num; i++) { \
|
||||
if (M_CALL_CMP(key_oplist, key, n->key[i]) <= 0) \
|
||||
break; \
|
||||
@@ -1094,7 +1094,7 @@
|
||||
static inline value_t * \
|
||||
M_C(name, _min)(const tree_t b) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_ASSERT (b->size > 0); \
|
||||
node_t n = b->root; \
|
||||
/* Scan down the nodes */ \
|
||||
@@ -1107,7 +1107,7 @@
|
||||
static inline value_t * \
|
||||
M_C(name, _max)(const tree_t b) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
node_t n = b->root; \
|
||||
/* Scan down the nodes */ \
|
||||
while (!M_C(name, _is_leaf)(n)) { \
|
||||
@@ -1131,47 +1131,47 @@
|
||||
static inline void \
|
||||
M_C(name, _init_move)(tree_t b, tree_t ref) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, ref); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, ref); \
|
||||
M_ASSERT (b != NULL && b != ref); \
|
||||
b->size = ref->size; \
|
||||
b->root = ref->root; \
|
||||
ref->root = NULL; \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _move)(tree_t b, tree_t ref) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, ref); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, ref); \
|
||||
M_ASSERT (b != ref); \
|
||||
M_C(name,_clear)(b); \
|
||||
M_C(name,_init_move)(b, ref); \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _swap)(tree_t tree1, tree_t tree2) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, tree1); \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, tree2); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, tree1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, tree2); \
|
||||
M_SWAP(size_t, tree1->size, tree2->size); \
|
||||
M_SWAP(node_t, tree1->root, tree2->root); \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, tree1); \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, tree2); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, tree1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, tree2); \
|
||||
} \
|
||||
\
|
||||
BPTREEI_FUNC_ADDITIONAL_DEF2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
M_BPTR33_FUNC_ADDITIONAL_DEF2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
|
||||
|
||||
/* Define additional functions.
|
||||
Do not used any fields but the already defined methods */
|
||||
#define BPTREEI_FUNC_ADDITIONAL_DEF2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
#define M_BPTR33_FUNC_ADDITIONAL_DEF2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
\
|
||||
M_IF_METHOD_BOTH(EQUAL, key_oplist, value_oplist)( \
|
||||
static inline bool M_C(name,_equal_p)(const tree_t t1, const tree_t t2) { \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t2); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t2); \
|
||||
if (t1->size != t2->size) return false; \
|
||||
if (t1->size == 0) return true; \
|
||||
/* Slow comparaison */ \
|
||||
@@ -1206,7 +1206,7 @@
|
||||
\
|
||||
M_IF_METHOD_BOTH(HASH, key_oplist, value_oplist)( \
|
||||
static inline size_t M_C(name,_hash)(const tree_t t1) { \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_HASH_DECL(hash); \
|
||||
/* NOTE: We can't compute the hash directly for the same reason \
|
||||
than for EQUAL operator. */ \
|
||||
@@ -1229,7 +1229,7 @@
|
||||
M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)( \
|
||||
static inline void M_C(name, _get_str)(string_t str, \
|
||||
const tree_t t1, bool append) { \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_ASSERT(str != NULL); \
|
||||
(append ? string_cat_str : string_set_str) (str, "["); \
|
||||
/* NOTE: The print is really naive, and not really efficient */ \
|
||||
@@ -1258,7 +1258,7 @@
|
||||
static inline void \
|
||||
M_C(name, _out_str)(FILE *file, tree_t const t1) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_ASSERT (file != NULL); \
|
||||
fputc ('[', file); \
|
||||
bool commaToPrint = false; \
|
||||
@@ -1286,7 +1286,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _parse_str)(tree_t t1, const char str[], const char **endp) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_ASSERT (str != NULL); \
|
||||
M_C(name,_clean)(t1); \
|
||||
bool success = false; \
|
||||
@@ -1328,7 +1328,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _in_str)(tree_t t1, FILE *file) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_ASSERT (file != NULL); \
|
||||
M_C(name,_clean)(t1); \
|
||||
int c = fgetc(file); \
|
||||
@@ -1366,7 +1366,7 @@
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _out_serial)(m_serial_write_t f, tree_t const t1) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_return_code_t ret; \
|
||||
m_serial_local_t local; \
|
||||
@@ -1410,7 +1410,7 @@
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _in_serial)(tree_t t1, m_serial_read_t f) \
|
||||
{ \
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_local_t local; \
|
||||
m_serial_return_code_t ret; \
|
||||
|
||||
+166
-166
@@ -62,7 +62,7 @@ typedef enum {
|
||||
USAGE: BUFFER_DEF_AS(name, name_t, type, size_of_buffer_or_0, policy[, oplist]) */
|
||||
#define BUFFER_DEF_AS(name, name_t, type, m_size, ... ) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BUFFERI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_BUFF3R_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, type, m_size,__VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), name_t ), \
|
||||
(name, type, m_size,__VA_ARGS__, name_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
@@ -71,7 +71,7 @@ typedef enum {
|
||||
/* Define the oplist of a lock based buffer given its name and its oplist.
|
||||
USAGE: BUFFER_OPLIST(name[, oplist of the type]) */
|
||||
#define BUFFER_OPLIST(...) \
|
||||
BUFFERI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_BUFF3R_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -91,7 +91,7 @@ typedef enum {
|
||||
*/
|
||||
#define QUEUE_MPMC_DEF_AS(name, name_t, type, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
QUEUEI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_QU3U3_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, type, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), name_t ), \
|
||||
(name, type, __VA_ARGS__, name_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
@@ -112,7 +112,7 @@ typedef enum {
|
||||
*/
|
||||
#define QUEUE_SPSC_DEF_AS(name, name_t, type, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
QUEUEI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_QU3U3_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, type, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), name_t ), \
|
||||
(name, type, __VA_ARGS__, name_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
@@ -122,31 +122,31 @@ typedef enum {
|
||||
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
#define BUFFERI_IF_CTE_SIZE(m_size) M_IF(M_BOOL(m_size))
|
||||
#define BUFFERI_SIZE(m_size) BUFFERI_IF_CTE_SIZE(m_size) (m_size, v->size)
|
||||
#define M_BUFF3R_IF_CTE_SIZE(m_size) M_IF(M_BOOL(m_size))
|
||||
#define M_BUFF3R_SIZE(m_size) M_BUFF3R_IF_CTE_SIZE(m_size) (m_size, v->size)
|
||||
|
||||
#define BUFFERI_POLICY_P(policy, val) \
|
||||
#define M_BUFF3R_POLICY_P(policy, val) \
|
||||
(((policy) & (val)) != 0)
|
||||
|
||||
#define BUFFERI_CONTRACT(buffer, size) do { \
|
||||
#define M_BUFF3R_CONTRACT(buffer, size) do { \
|
||||
M_ASSERT (buffer != NULL); \
|
||||
M_ASSERT (buffer->data != NULL); \
|
||||
}while (0)
|
||||
|
||||
#define BUFFERI_PROTECTED_CONTRACT(buffer, size) do { \
|
||||
M_ASSERT (atomic_load(&buffer->number[0]) <= BUFFERI_SIZE(size)); \
|
||||
#define M_BUFF3R_PROTECTED_CONTRACT(buffer, size) do { \
|
||||
M_ASSERT (atomic_load(&buffer->number[0]) <= M_BUFF3R_SIZE(size)); \
|
||||
} while (0)
|
||||
|
||||
/* Deferred evaluation for the definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define BUFFERI_DEF_P1(arg) BUFFERI_DEF_P2 arg
|
||||
#define M_BUFF3R_DEF_P1(arg) M_BUFF3R_DEF_P2 arg
|
||||
|
||||
/* Validate the value oplist before going further */
|
||||
#define BUFFERI_DEF_P2(name, type, m_size, policy, oplist, buffer_t) \
|
||||
M_IF_OPLIST(oplist)(BUFFERI_DEF_P3, BUFFERI_DEF_FAILURE)(name, type, m_size, policy, oplist, buffer_t)
|
||||
#define M_BUFF3R_DEF_P2(name, type, m_size, policy, oplist, buffer_t) \
|
||||
M_IF_OPLIST(oplist)(M_BUFF3R_DEF_P3, M_BUFF3R_DEF_FAILURE)(name, type, m_size, policy, oplist, buffer_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define BUFFERI_DEF_FAILURE(name, type, m_size, policy, oplist, buffer_t) \
|
||||
#define M_BUFF3R_DEF_FAILURE(name, type, m_size, policy, oplist, buffer_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(BUFFER_DEF): the given argument is not a valid oplist: " M_AS_STR(oplist))
|
||||
|
||||
/* Define the buffer type using mutex lock and its functions.
|
||||
@@ -157,7 +157,7 @@ typedef enum {
|
||||
- oplist: the oplist of the type of an element of the buffer
|
||||
- buffer_t: name of the buffer
|
||||
*/
|
||||
#define BUFFERI_DEF_P3(name, type, m_size, policy, oplist, buffer_t) \
|
||||
#define M_BUFF3R_DEF_P3(name, type, m_size, policy, oplist, buffer_t) \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
m_mutex_t mutexPush; /* MUTEX used for pushing elements */ \
|
||||
@@ -167,12 +167,12 @@ typedef enum {
|
||||
m_cond_t there_is_room_for_data; /* Cond. raised when there is room */ \
|
||||
m_mutex_t mutexPop; /* MUTEX used for popping elements */ \
|
||||
size_t idx_cons; /* Index of the consumption threads */ \
|
||||
BUFFERI_IF_CTE_SIZE(m_size)( ,size_t size;) /* Size of the buffer */ \
|
||||
M_BUFF3R_IF_CTE_SIZE(m_size)( ,size_t size;) /* Size of the buffer */ \
|
||||
/* number[0] := Number of elements in the buffer */ \
|
||||
/* number[1] := [OPTION] Number of elements being deferred in the buffer */ \
|
||||
atomic_ulong number[1 + BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)]; \
|
||||
atomic_ulong number[1 + M_BUFF3R_POLICY_P(policy, BUFFER_DEFERRED_POP)]; \
|
||||
/* If fixed size, array of elements, otherwise pointer to element */ \
|
||||
BUFFERI_IF_CTE_SIZE(m_size)(type data[m_size], type *data); \
|
||||
M_BUFF3R_IF_CTE_SIZE(m_size)(type data[m_size], type *data); \
|
||||
} buffer_t[1]; \
|
||||
\
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
@@ -188,78 +188,78 @@ typedef enum {
|
||||
static inline void \
|
||||
M_C(name, _init)(buffer_t v, size_t size) \
|
||||
{ \
|
||||
BUFFERI_IF_CTE_SIZE(m_size)(M_ASSERT(size == m_size), v->size = size); \
|
||||
M_BUFF3R_IF_CTE_SIZE(m_size)(M_ASSERT(size == m_size), v->size = size); \
|
||||
v->idx_prod = v->idx_cons = v->overwrite = 0; \
|
||||
atomic_init (&v->number[0], 0UL); \
|
||||
if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
if (M_BUFF3R_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
atomic_init (&v->number[1], 0UL); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_init(v->mutexPush); \
|
||||
m_mutex_init(v->mutexPop); \
|
||||
m_cond_init(v->there_is_data); \
|
||||
m_cond_init(v->there_is_room_for_data); \
|
||||
} else { \
|
||||
M_ASSERT(BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING)); \
|
||||
M_ASSERT(M_BUFF3R_POLICY_P((policy), BUFFER_UNBLOCKING)); \
|
||||
} \
|
||||
\
|
||||
BUFFERI_IF_CTE_SIZE(m_size)( /* Statically allocated */ , \
|
||||
v->data = M_CALL_REALLOC(oplist, type, NULL, BUFFERI_SIZE(m_size)); \
|
||||
M_BUFF3R_IF_CTE_SIZE(m_size)( /* Statically allocated */ , \
|
||||
v->data = M_CALL_REALLOC(oplist, type, NULL, M_BUFF3R_SIZE(m_size)); \
|
||||
if (v->data == NULL) { \
|
||||
M_MEMORY_FULL (BUFFERI_SIZE(m_size)*sizeof(type)); \
|
||||
M_MEMORY_FULL (M_BUFF3R_SIZE(m_size)*sizeof(type)); \
|
||||
return; \
|
||||
} \
|
||||
) \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(size_t i = 0; i < size; i++) { \
|
||||
M_CALL_INIT(oplist, v->data[i]); \
|
||||
} \
|
||||
} \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
} \
|
||||
\
|
||||
BUFFERI_IF_CTE_SIZE(m_size)( \
|
||||
M_BUFF3R_IF_CTE_SIZE(m_size)( \
|
||||
static inline void \
|
||||
M_C(name, _int_init)(buffer_t v) \
|
||||
M_C3(m_buff3r_,name,_init)(buffer_t v) \
|
||||
{ \
|
||||
M_C(name, _init)(v, m_size); \
|
||||
} \
|
||||
, ) \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _int_clear_obj)(buffer_t v) \
|
||||
M_C3(m_buff3r_,name,_clear_obj)(buffer_t v) \
|
||||
{ \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(size_t i = 0; i < M_BUFF3R_SIZE(m_size); i++) { \
|
||||
M_CALL_CLEAR(oplist, v->data[i]); \
|
||||
} \
|
||||
} else { \
|
||||
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
|
||||
size_t i = M_BUFF3R_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
|
||||
while (i != v->idx_prod) { \
|
||||
M_CALL_CLEAR(oplist, v->data[i]); \
|
||||
i++; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_STACK) && i >= BUFFERI_SIZE(m_size)) \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_STACK) && i >= M_BUFF3R_SIZE(m_size)) \
|
||||
i = 0; \
|
||||
} \
|
||||
} \
|
||||
v->idx_prod = v->idx_cons = 0; \
|
||||
atomic_store_explicit (&v->number[0], 0UL, memory_order_relaxed); \
|
||||
if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
if (M_BUFF3R_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
atomic_store_explicit(&v->number[1], 0UL, memory_order_relaxed); \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(buffer_t v) \
|
||||
{ \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_C(name, _int_clear_obj)(v); \
|
||||
BUFFERI_IF_CTE_SIZE(m_size)( , \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
M_C3(m_buff3r_,name,_clear_obj)(v); \
|
||||
M_BUFF3R_IF_CTE_SIZE(m_size)( , \
|
||||
M_CALL_FREE(oplist, v->data); \
|
||||
v->data = NULL; \
|
||||
) \
|
||||
v->overwrite = 0; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_clear(v->mutexPush); \
|
||||
m_mutex_clear(v->mutexPop); \
|
||||
m_cond_clear(v->there_is_data); \
|
||||
@@ -270,24 +270,24 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
static inline void \
|
||||
M_C(name, _clean)(buffer_t v) \
|
||||
{ \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_lock(v->mutexPush); \
|
||||
m_mutex_lock(v->mutexPop); \
|
||||
} \
|
||||
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
|
||||
if (BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) \
|
||||
M_C(name, _int_clear_obj)(v); \
|
||||
M_BUFF3R_PROTECTED_CONTRACT(v, m_size); \
|
||||
if (M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) \
|
||||
M_C3(m_buff3r_,name,_clear_obj)(v); \
|
||||
v->idx_prod = v->idx_cons = 0; \
|
||||
atomic_store_explicit (&v->number[0], 0UL, memory_order_relaxed); \
|
||||
if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
if (M_BUFF3R_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
atomic_store_explicit(&v->number[1], 0UL, memory_order_relaxed); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_cond_broadcast(v->there_is_room_for_data); \
|
||||
m_mutex_unlock(v->mutexPop); \
|
||||
m_mutex_unlock(v->mutexPush); \
|
||||
} \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -298,24 +298,24 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
vu.cptr = src; \
|
||||
M_C(name, _ptr) v = vu.ptr; \
|
||||
M_ASSERT (dest != v); \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_C(name, _init)(dest, BUFFERI_SIZE(m_size)); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
M_C(name, _init)(dest, M_BUFF3R_SIZE(m_size)); \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_lock(v->mutexPush); \
|
||||
m_mutex_lock(v->mutexPop); \
|
||||
} \
|
||||
\
|
||||
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \
|
||||
M_BUFF3R_PROTECTED_CONTRACT(v, m_size); \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(size_t i = 0; i < M_BUFF3R_SIZE(m_size); i++) { \
|
||||
M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \
|
||||
} \
|
||||
} else { \
|
||||
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
|
||||
size_t i = M_BUFF3R_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
|
||||
while (i != v->idx_prod) { \
|
||||
M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \
|
||||
i++; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_STACK) && i >= BUFFERI_SIZE(m_size)) \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_STACK) && i >= M_BUFF3R_SIZE(m_size)) \
|
||||
i = 0; \
|
||||
} \
|
||||
} \
|
||||
@@ -323,15 +323,15 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
dest->idx_prod = v->idx_prod; \
|
||||
dest->idx_cons = v->idx_cons; \
|
||||
atomic_store_explicit (&dest->number[0], atomic_load(&v->number[0]), memory_order_relaxed); \
|
||||
if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
if (M_BUFF3R_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
atomic_store_explicit(&dest->number[1], atomic_load(&v->number[1]), memory_order_relaxed); \
|
||||
\
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_unlock(v->mutexPop); \
|
||||
m_mutex_unlock(v->mutexPush); \
|
||||
} \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
BUFFERI_CONTRACT(dest, m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(dest, m_size); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -341,11 +341,11 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
M_C(name, _uptr_ct) vu; \
|
||||
vu.cptr = src; \
|
||||
M_C(name, _ptr) v = vu.ptr; \
|
||||
BUFFERI_CONTRACT(dest,m_size); \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(dest,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
\
|
||||
if (dest == v) return; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
/* Case of deadlock: A := B, B:=C, C:=A (all in //) \
|
||||
Solution: order the lock by increasing memory */ \
|
||||
if (dest < v) { \
|
||||
@@ -361,19 +361,19 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
|
||||
M_C(name, _int_clear_obj)(dest); \
|
||||
M_BUFF3R_PROTECTED_CONTRACT(v, m_size); \
|
||||
M_C3(m_buff3r_,name,_clear_obj)(dest); \
|
||||
\
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(size_t i = 0; i < M_BUFF3R_SIZE(m_size); i++) { \
|
||||
M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \
|
||||
} \
|
||||
} else { \
|
||||
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
|
||||
size_t i = M_BUFF3R_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
|
||||
while (i != v->idx_prod) { \
|
||||
M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \
|
||||
i++; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_STACK) && i >= BUFFERI_SIZE(m_size)) \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_STACK) && i >= M_BUFF3R_SIZE(m_size)) \
|
||||
i = 0; \
|
||||
} \
|
||||
} \
|
||||
@@ -381,10 +381,10 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
dest->idx_prod = v->idx_prod; \
|
||||
dest->idx_cons = v->idx_cons; \
|
||||
atomic_store_explicit (&dest->number[0], atomic_load(&v->number[0]), memory_order_relaxed); \
|
||||
if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
if (M_BUFF3R_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
atomic_store_explicit(&dest->number[1], atomic_load(&v->number[1]), memory_order_relaxed); \
|
||||
\
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
/* It may be false, but it is not wrong! */ \
|
||||
m_cond_broadcast(v->there_is_room_for_data); \
|
||||
m_cond_broadcast(v->there_is_data); \
|
||||
@@ -400,19 +400,19 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
m_mutex_unlock(v->mutexPush); \
|
||||
} \
|
||||
} \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
BUFFERI_CONTRACT(dest, m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(dest, m_size); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(buffer_t v) \
|
||||
{ \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
/* If the buffer has been configured with deferred pop \
|
||||
we considered the queue as empty when the number of \
|
||||
deferred pop has reached 0, not the number of items in the \
|
||||
buffer is 0. */ \
|
||||
if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
if (M_BUFF3R_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
|
||||
return atomic_load_explicit (&v->number[1], memory_order_relaxed) == 0; \
|
||||
else \
|
||||
return atomic_load_explicit (&v->number[0], memory_order_relaxed) == 0; \
|
||||
@@ -421,27 +421,27 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
static inline bool \
|
||||
M_C(name, _full_p)(buffer_t v) \
|
||||
{ \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
return atomic_load_explicit (&v->number[0], memory_order_relaxed) \
|
||||
== BUFFERI_SIZE(m_size); \
|
||||
== M_BUFF3R_SIZE(m_size); \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _size)(buffer_t v) \
|
||||
{ \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
return atomic_load_explicit (&v->number[0], memory_order_relaxed); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _push_blocking)(buffer_t v, type const data, bool blocking) \
|
||||
{ \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
\
|
||||
/* BUFFER lock */ \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_lock(v->mutexPush); \
|
||||
while (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
|
||||
while (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
|
||||
&& M_C(name, _full_p)(v)) { \
|
||||
if (!blocking) { \
|
||||
m_mutex_unlock(v->mutexPush); \
|
||||
@@ -449,31 +449,31 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
} \
|
||||
m_cond_wait(v->there_is_room_for_data, v->mutexPush); \
|
||||
} \
|
||||
} else if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
|
||||
} else if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
|
||||
&& M_C(name, _full_p)(v)) \
|
||||
return false; \
|
||||
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
|
||||
M_BUFF3R_PROTECTED_CONTRACT(v, m_size); \
|
||||
\
|
||||
size_t previousSize, idx = v->idx_prod; \
|
||||
/* INDEX computation if we have to overwrite the last element */ \
|
||||
if (M_UNLIKELY (BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
|
||||
if (M_UNLIKELY (M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
|
||||
&& M_C(name, _full_p)(v))) { \
|
||||
v->overwrite++; \
|
||||
/* Let's overwrite the last element */ \
|
||||
/* Compute the index of the last push element */ \
|
||||
idx--; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_STACK)) { \
|
||||
idx = idx >= BUFFERI_SIZE(m_size) ? BUFFERI_SIZE(m_size)-1 : idx; \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_STACK)) { \
|
||||
idx = idx >= M_BUFF3R_SIZE(m_size) ? M_BUFF3R_SIZE(m_size)-1 : idx; \
|
||||
} \
|
||||
/* Update data in the buffer */ \
|
||||
M_CALL_SET(oplist, v->data[idx], data); \
|
||||
previousSize = BUFFERI_SIZE(m_size); \
|
||||
previousSize = M_BUFF3R_SIZE(m_size); \
|
||||
\
|
||||
} else { \
|
||||
\
|
||||
/* Add a new item in the buffer */ \
|
||||
/* PUSH data in the buffer */ \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, v->data[idx], data); \
|
||||
} else { \
|
||||
M_CALL_INIT_SET(oplist, v->data[idx], data); \
|
||||
@@ -481,8 +481,8 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
\
|
||||
/* Increment production INDEX of the buffer */ \
|
||||
idx++; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_STACK)) { \
|
||||
idx = (idx == BUFFERI_SIZE(m_size)) ? 0 : idx; \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_STACK)) { \
|
||||
idx = (idx == M_BUFF3R_SIZE(m_size)) ? 0 : idx; \
|
||||
} \
|
||||
v->idx_prod = idx; \
|
||||
\
|
||||
@@ -492,13 +492,13 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
like an atomic variable. */ \
|
||||
/* Increment number of elements of the buffer */ \
|
||||
previousSize = atomic_fetch_add (&v->number[0], 1UL); \
|
||||
if (BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
|
||||
if (M_BUFF3R_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
|
||||
previousSize = atomic_fetch_add (&v->number[1], 1UL); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* BUFFER unlock */ \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_unlock(v->mutexPush); \
|
||||
/* If the number of items in the buffer was 0, some consummer \
|
||||
may be waiting. Signal to them the availibility of the data \
|
||||
@@ -510,18 +510,18 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _pop_blocking)(type *data, buffer_t v, bool blocking) \
|
||||
{ \
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
M_ASSERT (data != NULL); \
|
||||
\
|
||||
/* BUFFER lock */ \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_lock(v->mutexPop); \
|
||||
while (M_C(name, _empty_p)(v)) { \
|
||||
if (!blocking) { \
|
||||
@@ -532,21 +532,21 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
} \
|
||||
} else if (M_C(name, _empty_p)(v)) \
|
||||
return false; \
|
||||
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
|
||||
M_BUFF3R_PROTECTED_CONTRACT(v, m_size); \
|
||||
\
|
||||
/* POP data from the buffer and update INDEX */ \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_STACK)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_STACK)) { \
|
||||
/* FIFO queue */ \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, *data, v->data[v->idx_cons]); \
|
||||
} else { \
|
||||
M_DO_INIT_MOVE (oplist, *data, v->data[v->idx_cons]); \
|
||||
} \
|
||||
v->idx_cons = (v->idx_cons == BUFFERI_SIZE(m_size)-1) ? 0 : (v->idx_cons + 1); \
|
||||
v->idx_cons = (v->idx_cons == M_BUFF3R_SIZE(m_size)-1) ? 0 : (v->idx_cons + 1); \
|
||||
} else { \
|
||||
/* STACK queue */ \
|
||||
v->idx_prod --; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, *data, v->data[v->idx_prod]); \
|
||||
} else { \
|
||||
M_DO_INIT_MOVE (oplist, *data, v->data[v->idx_prod]); \
|
||||
@@ -559,27 +559,27 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
like an atomic variable. */ \
|
||||
/* Decrement number of elements in the buffer */ \
|
||||
size_t previousSize; \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
|
||||
previousSize = atomic_fetch_sub (&v->number[0], 1UL); \
|
||||
} else { \
|
||||
atomic_fetch_sub (&v->number[1], 1UL); \
|
||||
} \
|
||||
\
|
||||
/* BUFFER unlock */ \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
|
||||
m_mutex_unlock(v->mutexPop); \
|
||||
/* If the number of items in the buffer was the max, some producer \
|
||||
may be waiting. Signal to them the availibility of the free room \
|
||||
We cannot only signal one thread. */ \
|
||||
if ((!BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) \
|
||||
&& previousSize == BUFFERI_SIZE(m_size)) { \
|
||||
if ((!M_BUFF3R_POLICY_P((policy), BUFFER_DEFERRED_POP)) \
|
||||
&& previousSize == M_BUFF3R_SIZE(m_size)) { \
|
||||
m_mutex_lock(v->mutexPush); \
|
||||
m_cond_broadcast(v->there_is_room_for_data); \
|
||||
m_mutex_unlock(v->mutexPush); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
BUFFERI_CONTRACT(v,m_size); \
|
||||
M_BUFF3R_CONTRACT(v,m_size); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
@@ -588,14 +588,14 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
M_C(name, _push)(buffer_t v, type const data) \
|
||||
{ \
|
||||
return M_C(name, _push_blocking)(v, data, \
|
||||
!BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING_PUSH)); \
|
||||
!M_BUFF3R_POLICY_P((policy), BUFFER_UNBLOCKING_PUSH)); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _pop)(type *data, buffer_t v) \
|
||||
{ \
|
||||
return M_C(name, _pop_blocking)(data, v, \
|
||||
!BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING_POP)); \
|
||||
!M_BUFF3R_POLICY_P((policy), BUFFER_UNBLOCKING_POP)); \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
@@ -608,16 +608,16 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
M_C(name, _capacity)(const buffer_t v) \
|
||||
{ \
|
||||
(void) v; /* may be unused */ \
|
||||
return BUFFERI_SIZE(m_size); \
|
||||
return M_BUFF3R_SIZE(m_size); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _pop_release)(buffer_t v) \
|
||||
{ \
|
||||
/* Decrement the effective number of elements in the buffer */ \
|
||||
if (BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
|
||||
if (M_BUFF3R_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
|
||||
size_t previousSize = atomic_fetch_sub (&v->number[0], 1UL); \
|
||||
if (previousSize == BUFFERI_SIZE(m_size)) { \
|
||||
if (previousSize == M_BUFF3R_SIZE(m_size)) { \
|
||||
m_mutex_lock(v->mutexPush); \
|
||||
m_cond_broadcast(v->there_is_room_for_data); \
|
||||
m_mutex_unlock(v->mutexPush); \
|
||||
@@ -639,20 +639,20 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
|
||||
/* Deferred evaluation for the definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define QUEUEI_MPMC_DEF_P1(arg) QUEUEI_MPMC_DEF_P2 arg
|
||||
#define M_QU3U3_MPMC_DEF_P1(arg) M_QU3U3_MPMC_DEF_P2 arg
|
||||
|
||||
/* Validate the value oplist before going further */
|
||||
#define QUEUEI_MPMC_DEF_P2(name, type, policy, oplist, buffer_t) \
|
||||
M_IF_OPLIST(oplist)(QUEUEI_MPMC_DEF_P3, QUEUEI_MPMC_DEF_FAILURE)(name, type, policy, oplist, buffer_t)
|
||||
#define M_QU3U3_MPMC_DEF_P2(name, type, policy, oplist, buffer_t) \
|
||||
M_IF_OPLIST(oplist)(M_QU3U3_MPMC_DEF_P3, M_QU3U3_MPMC_DEF_FAILURE)(name, type, policy, oplist, buffer_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define QUEUEI_MPMC_DEF_FAILURE(name, type, policy, oplist, buffer_t) \
|
||||
#define M_QU3U3_MPMC_DEF_FAILURE(name, type, policy, oplist, buffer_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(QUEUE_MPMC_DEF): the given argument is not a valid oplist: " M_AS_STR(oplist))
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define QUEUEI_MPMC_CONTRACT(v) /* nothing */
|
||||
# define M_QU3U3_MPMC_CONTRACT(v) /* nothing */
|
||||
#else
|
||||
# define QUEUEI_MPMC_CONTRACT(v) do { \
|
||||
# define M_QU3U3_MPMC_CONTRACT(v) do { \
|
||||
M_ASSERT (v != 0); \
|
||||
M_ASSERT (v->Tab != NULL); \
|
||||
unsigned int _r = atomic_load(&v->ConsoIdx); \
|
||||
@@ -671,7 +671,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
- oplist: the oplist of the type of an element of the buffer
|
||||
- buffer_t: name of the buffer
|
||||
*/
|
||||
#define QUEUEI_MPMC_DEF_P3(name, type, policy, oplist, buffer_t) \
|
||||
#define M_QU3U3_MPMC_DEF_P3(name, type, policy, oplist, buffer_t) \
|
||||
\
|
||||
/* The sequence number of an element will be equal to either \
|
||||
- 2* the index of the production which creates it, \
|
||||
@@ -704,7 +704,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
static inline bool \
|
||||
M_C(name, _push)(buffer_t table, type const x) \
|
||||
{ \
|
||||
QUEUEI_MPMC_CONTRACT(table); \
|
||||
M_QU3U3_MPMC_CONTRACT(table); \
|
||||
unsigned int idx = atomic_load_explicit(&table->ProdIdx, \
|
||||
memory_order_relaxed); \
|
||||
const unsigned int i = idx & (table->size -1); \
|
||||
@@ -720,21 +720,21 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
return false; \
|
||||
} \
|
||||
/* If it is interrupted here, it may block pop method (not push) */ \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, table->Tab[i].x, x); \
|
||||
} else { \
|
||||
M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \
|
||||
} \
|
||||
/* Finish transaction */ \
|
||||
atomic_store_explicit(&table->Tab[i].seq, 2*idx, memory_order_release); \
|
||||
QUEUEI_MPMC_CONTRACT(table); \
|
||||
M_QU3U3_MPMC_CONTRACT(table); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _pop)(type *ptr, buffer_t table) \
|
||||
{ \
|
||||
QUEUEI_MPMC_CONTRACT(table); \
|
||||
M_QU3U3_MPMC_CONTRACT(table); \
|
||||
M_ASSERT (ptr != NULL); \
|
||||
unsigned int iC = atomic_load_explicit(&table->ConsoIdx, \
|
||||
memory_order_relaxed); \
|
||||
@@ -750,13 +750,13 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
/* Thread has been preempted by another one */ \
|
||||
return false; \
|
||||
} \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, *ptr, table->Tab[i].x); \
|
||||
} else { \
|
||||
M_DO_INIT_MOVE (oplist, *ptr, table->Tab[i].x); \
|
||||
} \
|
||||
atomic_store_explicit(&table->Tab[i].seq, 2*iC + 1, memory_order_release); \
|
||||
QUEUEI_MPMC_CONTRACT(table); \
|
||||
M_QU3U3_MPMC_CONTRACT(table); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
@@ -777,18 +777,18 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
} \
|
||||
for(unsigned int j = 0; j < (unsigned int) size; j++) { \
|
||||
atomic_init(&buffer->Tab[j].seq, 2*j+1U); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_INIT(oplist, buffer->Tab[j].x); \
|
||||
} \
|
||||
} \
|
||||
QUEUEI_MPMC_CONTRACT(buffer); \
|
||||
M_QU3U3_MPMC_CONTRACT(buffer); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(buffer_t buffer) \
|
||||
{ \
|
||||
QUEUEI_MPMC_CONTRACT(buffer); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_QU3U3_MPMC_CONTRACT(buffer); \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(unsigned int j = 0; j < buffer->size; j++) { \
|
||||
M_CALL_CLEAR(oplist, buffer->Tab[j].x); \
|
||||
} \
|
||||
@@ -811,7 +811,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
static inline size_t \
|
||||
M_C(name, _size)(buffer_t table) \
|
||||
{ \
|
||||
QUEUEI_MPMC_CONTRACT(table); \
|
||||
M_QU3U3_MPMC_CONTRACT(table); \
|
||||
const unsigned int iC = atomic_load_explicit(&table->ConsoIdx, memory_order_relaxed); \
|
||||
const unsigned int iP = atomic_load_explicit(&table->ProdIdx, memory_order_acquire); \
|
||||
/* We return an approximation as we can't read both iC & iP atomically \
|
||||
@@ -830,7 +830,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
static inline size_t \
|
||||
M_C(name, _capacity)(buffer_t v) \
|
||||
{ \
|
||||
QUEUEI_MPMC_CONTRACT(v); \
|
||||
M_QU3U3_MPMC_CONTRACT(v); \
|
||||
return v->size; \
|
||||
} \
|
||||
\
|
||||
@@ -860,20 +860,20 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
|
||||
/* Deferred evaluation for the definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define QUEUEI_SPSC_DEF_P1(arg) QUEUEI_SPSC_DEF_P2 arg
|
||||
#define M_QU3U3_SPSC_DEF_P1(arg) M_QU3U3_SPSC_DEF_P2 arg
|
||||
|
||||
/* Validate the value oplist before going further */
|
||||
#define QUEUEI_SPSC_DEF_P2(name, type, policy, oplist, buffer_t) \
|
||||
M_IF_OPLIST(oplist)(QUEUEI_SPSC_DEF_P3, QUEUEI_SPSC_DEF_FAILURE)(name, type, policy, oplist, buffer_t)
|
||||
#define M_QU3U3_SPSC_DEF_P2(name, type, policy, oplist, buffer_t) \
|
||||
M_IF_OPLIST(oplist)(M_QU3U3_SPSC_DEF_P3, M_QU3U3_SPSC_DEF_FAILURE)(name, type, policy, oplist, buffer_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define QUEUEI_SPSC_DEF_FAILURE(name, type, policy, oplist, buffer_t) \
|
||||
#define M_QU3U3_SPSC_DEF_FAILURE(name, type, policy, oplist, buffer_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(QUEUE_SPSC_DEF): the given argument is not a valid oplist: " M_AS_STR(oplist))
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define QUEUEI_SPSC_CONTRACT(table) do { } while (0)
|
||||
#define M_QU3U3_SPSC_CONTRACT(table) do { } while (0)
|
||||
#else
|
||||
#define QUEUEI_SPSC_CONTRACT(table) do { \
|
||||
#define M_QU3U3_SPSC_CONTRACT(table) do { \
|
||||
M_ASSERT (table != NULL); \
|
||||
unsigned int _r = atomic_load(&table->consoIdx); \
|
||||
unsigned int _w = atomic_load(&table->prodIdx); \
|
||||
@@ -891,7 +891,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
- oplist: the oplist of the type of an element of the buffer
|
||||
- buffer_t: name of the buffer
|
||||
*/
|
||||
#define QUEUEI_SPSC_DEF_P3(name, type, policy, oplist, buffer_t) \
|
||||
#define M_QU3U3_SPSC_DEF_P3(name, type, policy, oplist, buffer_t) \
|
||||
\
|
||||
typedef struct M_C(name, _el_s) { \
|
||||
type x; \
|
||||
@@ -911,7 +911,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
static inline bool \
|
||||
M_C(name, _push)(buffer_t table, type const x) \
|
||||
{ \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
unsigned int r = atomic_load_explicit(&table->consoIdx, \
|
||||
memory_order_relaxed); \
|
||||
unsigned int w = atomic_load_explicit(&table->prodIdx, \
|
||||
@@ -919,20 +919,20 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
if (w-r >= table->size) \
|
||||
return false; \
|
||||
unsigned int i = w & (table->size -1); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, table->Tab[i].x, x); \
|
||||
} else { \
|
||||
M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \
|
||||
} \
|
||||
atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _push_move)(buffer_t table, type x) \
|
||||
{ \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
unsigned int r = atomic_load_explicit(&table->consoIdx, \
|
||||
memory_order_relaxed); \
|
||||
unsigned int w = atomic_load_explicit(&table->prodIdx, \
|
||||
@@ -940,20 +940,20 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
if (w-r >= table->size) \
|
||||
return false; \
|
||||
unsigned int i = w & (table->size -1); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_DO_MOVE(oplist, table->Tab[i].x, x); \
|
||||
} else { \
|
||||
M_DO_INIT_MOVE(oplist, table->Tab[i].x, x); \
|
||||
} \
|
||||
atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _pop)(type *ptr, buffer_t table) \
|
||||
{ \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
M_ASSERT (ptr != NULL); \
|
||||
unsigned int w = atomic_load_explicit(&table->prodIdx, \
|
||||
memory_order_relaxed); \
|
||||
@@ -962,20 +962,20 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
if (w-r == 0) \
|
||||
return false; \
|
||||
unsigned int i = r & (table->size -1); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, *ptr , table->Tab[i].x); \
|
||||
} else { \
|
||||
M_DO_INIT_MOVE (oplist, *ptr, table->Tab[i].x); \
|
||||
} \
|
||||
atomic_store_explicit(&table->consoIdx, r+1, memory_order_release); \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static inline unsigned \
|
||||
M_C(name, _push_bulk)(buffer_t table, unsigned n, type const x[]) \
|
||||
{ \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
M_ASSERT (x != NULL); \
|
||||
M_ASSERT (n <= table->size); \
|
||||
unsigned int r = atomic_load_explicit(&table->consoIdx, \
|
||||
@@ -987,21 +987,21 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
return 0; \
|
||||
for(unsigned int k = 0; k < max; k++) { \
|
||||
unsigned int i = (w+k) & (table->size -1); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, table->Tab[i].x, x[k]); \
|
||||
} else { \
|
||||
M_CALL_INIT_SET(oplist, table->Tab[i].x, x[k]); \
|
||||
} \
|
||||
} \
|
||||
atomic_store_explicit(&table->prodIdx, w+max, memory_order_release); \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
return max; \
|
||||
} \
|
||||
\
|
||||
static inline unsigned \
|
||||
M_C(name, _pop_bulk)(unsigned int n, type ptr[], buffer_t table) \
|
||||
{ \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
M_ASSERT (ptr != NULL); \
|
||||
M_ASSERT (n <= table->size); \
|
||||
unsigned int w = atomic_load_explicit(&table->prodIdx, \
|
||||
@@ -1013,21 +1013,21 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
unsigned int max = M_MIN(w-r, n); \
|
||||
for(unsigned int k = 0; k < max; k++) { \
|
||||
unsigned int i = (r+k) & (table->size -1); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, ptr[k], table->Tab[i].x); \
|
||||
} else { \
|
||||
M_DO_INIT_MOVE (oplist, ptr[k], table->Tab[i].x); \
|
||||
} \
|
||||
} \
|
||||
atomic_store_explicit(&table->consoIdx, r+max, memory_order_release); \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
return max; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _push_force)(buffer_t table, type const x) \
|
||||
{ \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
unsigned int r = atomic_load_explicit(&table->consoIdx, \
|
||||
memory_order_relaxed); \
|
||||
unsigned int w = atomic_load_explicit(&table->prodIdx, \
|
||||
@@ -1038,19 +1038,19 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
r += b; \
|
||||
} \
|
||||
unsigned int i = w & (table->size -1); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_CALL_SET(oplist, table->Tab[i].x, x); \
|
||||
} else { \
|
||||
M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \
|
||||
} \
|
||||
atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _size)(buffer_t table) \
|
||||
{ \
|
||||
QUEUEI_SPSC_CONTRACT(table); \
|
||||
M_QU3U3_SPSC_CONTRACT(table); \
|
||||
unsigned int r = atomic_load_explicit(&table->consoIdx, \
|
||||
memory_order_relaxed); \
|
||||
unsigned int w = atomic_load_explicit(&table->prodIdx, \
|
||||
@@ -1101,19 +1101,19 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \
|
||||
return; \
|
||||
} \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(unsigned int j = 0; j < (unsigned int) size; j++) { \
|
||||
M_CALL_INIT(oplist, buffer->Tab[j].x); \
|
||||
} \
|
||||
} \
|
||||
QUEUEI_SPSC_CONTRACT(buffer); \
|
||||
M_QU3U3_SPSC_CONTRACT(buffer); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(buffer_t buffer) \
|
||||
{ \
|
||||
QUEUEI_SPSC_CONTRACT(buffer); \
|
||||
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
M_QU3U3_SPSC_CONTRACT(buffer); \
|
||||
if (!M_BUFF3R_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
|
||||
for(unsigned int j = 0; j < buffer->size; j++) { \
|
||||
M_CALL_CLEAR(oplist, buffer->Tab[j].x); \
|
||||
} \
|
||||
@@ -1136,19 +1136,19 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
|
||||
/* Deferred evaluation for the definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define BUFFERI_OPLIST_P1(arg) BUFFERI_OPLIST_P2 arg
|
||||
#define M_BUFF3R_OPLIST_P1(arg) M_BUFF3R_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define BUFFERI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(BUFFERI_OPLIST_P3, BUFFERI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_BUFF3R_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_BUFF3R_OPLIST_P3, M_BUFF3R_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define BUFFERI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_BUFF3R_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_BUFFER_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* OPLIST definition of a buffer */
|
||||
#define BUFFERI_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _int_init)) \
|
||||
#define M_BUFF3R_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C3(m_buff3r_,name, _init)) \
|
||||
,INIT_SET(M_C(name, _init_set)) \
|
||||
,SET(M_C(name, _set)) \
|
||||
,CLEAR(M_C(name, _clear)) \
|
||||
|
||||
+27
-27
@@ -32,19 +32,19 @@
|
||||
M_BEGIN_PROTECTED_CODE
|
||||
|
||||
/* Minimum number of nodes per group of nodes */
|
||||
#define C_MEMPOOL_MIN_NODE_PER_GROUP 16
|
||||
#define M_CMEMP00L_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) \
|
||||
M_CMEMP00L_DEF_SINGLY_LIST(name, type_t) \
|
||||
M_CMEMP00L_DEF_LF_QUEUE(name, type_t) \
|
||||
M_CMEMP00L_DEF_LFMP_THREAD_MEMPOOL(name, type_t) \
|
||||
M_CMEMP00L_DEF_SYSTEM_ALLOC(name, type_t) \
|
||||
M_CMEMP00L_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) \
|
||||
#define M_CMEMP00L_DEF_SINGLY_LIST(name, type_t) \
|
||||
\
|
||||
typedef struct M_C(name, _slist_node_s) { \
|
||||
struct M_C(name, _slist_node_s) *next; \
|
||||
@@ -123,7 +123,7 @@ 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) \
|
||||
#define M_CMEMP00L_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; \
|
||||
@@ -304,7 +304,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
|
||||
/* 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) \
|
||||
#define M_CMEMP00L_DEF_SYSTEM_ALLOC(name, type_t) \
|
||||
\
|
||||
static inline M_C(name, _lf_node_t) * \
|
||||
M_C(name, _alloc_node)(unsigned int initial) \
|
||||
@@ -386,7 +386,7 @@ 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) \
|
||||
#define M_CMEMP00L_DEF_LFMP_THREAD_MEMPOOL(name, type_t) \
|
||||
\
|
||||
typedef struct M_C(name, _lfmp_thread_s) { \
|
||||
M_C(name, _slist_ct) free; \
|
||||
@@ -410,7 +410,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
} \
|
||||
|
||||
/* NOTE: once a node is deleted, its data are kept readable until the future GC */
|
||||
#define C_MEMPOOL_DEF_LF_MEMPOOL(name, type_t) \
|
||||
#define M_CMEMP00L_DEF_LF_MEMPOOL(name, type_t) \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
unsigned initial; \
|
||||
@@ -418,18 +418,18 @@ M_BEGIN_PROTECTED_CODE
|
||||
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; \
|
||||
m_gM_CMEMP00L_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_C(name, _int_gc_on_sleep)(m_gc_t gc_mem, m_gM_CMEMP00L_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); \
|
||||
M_TYPE_FROM_FIELD(struct M_C(name, _s), data, m_gM_CMEMP00L_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)) { \
|
||||
@@ -473,7 +473,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
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); \
|
||||
mem->initial = M_MAX(M_CMEMP00L_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)); \
|
||||
@@ -555,13 +555,13 @@ typedef atomic_ulong m_gc_atomic_ticket_ct;
|
||||
|
||||
/* Define the Linked List of mempools that are registered in the GC */
|
||||
struct m_gc_s;
|
||||
typedef struct m_gc_mempool_list_s {
|
||||
struct m_gc_mempool_list_s *next;
|
||||
typedef struct m_gM_CMEMP00L_list_s {
|
||||
struct m_gM_CMEMP00L_list_s *next;
|
||||
void (*gc_on_sleep)(struct m_gc_s *gc_mem,
|
||||
struct m_gc_mempool_list_s *data, m_gc_tid_t id,
|
||||
struct m_gM_CMEMP00L_list_s *data, m_gc_tid_t id,
|
||||
m_gc_ticket_ct ticket, m_gc_ticket_ct min_ticket);
|
||||
void *data;
|
||||
} m_gc_mempool_list_ct;
|
||||
} m_gM_CMEMP00L_list_ct;
|
||||
|
||||
/* Define the Garbage collector thread data */
|
||||
typedef struct m_gc_lfmp_thread_s {
|
||||
@@ -576,7 +576,7 @@ typedef struct m_gc_s {
|
||||
m_gc_tid_t max_thread;
|
||||
genint_t thread_alloc;
|
||||
m_gc_lfmp_thread_ct *thread_data;
|
||||
m_gc_mempool_list_ct *mempool_list;
|
||||
m_gM_CMEMP00L_list_ct *mempool_list;
|
||||
} m_gc_t[1];
|
||||
|
||||
static inline void
|
||||
@@ -662,7 +662,7 @@ m_gc_sleep(m_gc_t gc_mem, m_gc_tid_t id)
|
||||
atomic_store(&gc_mem->thread_data[id].ticket, t+1);
|
||||
const m_gc_ticket_ct min_ticket = m_gc_int_min_ticket(gc_mem);
|
||||
/* Iterate over all registered mempools */
|
||||
m_gc_mempool_list_ct *it = gc_mem->mempool_list;
|
||||
m_gM_CMEMP00L_list_ct *it = gc_mem->mempool_list;
|
||||
|
||||
while (it) {
|
||||
/* Perform a garbage collect of the mempool */
|
||||
@@ -681,9 +681,9 @@ m_gc_sleep(m_gc_t gc_mem, m_gc_tid_t id)
|
||||
/* */
|
||||
/***********************************************************************/
|
||||
|
||||
C_MEMPOOL_DEF_SINGLY_LIST(m_vlapool, char)
|
||||
C_MEMPOOL_DEF_LF_QUEUE(m_vlapool, char)
|
||||
C_MEMPOOL_DEF_SYSTEM_ALLOC(m_vlapool, char)
|
||||
M_CMEMP00L_DEF_SINGLY_LIST(m_vlapool, char)
|
||||
M_CMEMP00L_DEF_LF_QUEUE(m_vlapool, char)
|
||||
M_CMEMP00L_DEF_SYSTEM_ALLOC(m_vlapool, char)
|
||||
|
||||
typedef struct m_vlapool_lfmp_thread_s {
|
||||
m_vlapool_slist_ct to_be_reclaimed;
|
||||
@@ -707,18 +707,18 @@ typedef struct m_vlapool_s {
|
||||
m_vlapool_lflist_ct to_be_reclaimed;
|
||||
m_vlapool_lflist_ct empty;
|
||||
m_vlapool_lfmp_thread_ct *thread_data;
|
||||
m_gc_mempool_list_ct mvla_node;
|
||||
m_gM_CMEMP00L_list_ct mvla_node;
|
||||
struct m_gc_s *gc_mem;
|
||||
} m_vlapool_t[1];
|
||||
|
||||
/* Garbage collect of the nodes of the vla mempool on sleep */
|
||||
static inline void
|
||||
m_vlapool_int_gc_on_sleep(m_gc_t gc_mem, m_gc_mempool_list_ct *data,
|
||||
m_vlapool_int_gc_on_sleep(m_gc_t gc_mem, m_gM_CMEMP00L_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_vlapool_s *vlapool =
|
||||
M_TYPE_FROM_FIELD(struct m_vlapool_s, data, m_gc_mempool_list_ct, mvla_node);
|
||||
M_TYPE_FROM_FIELD(struct m_vlapool_s, data, m_gM_CMEMP00L_list_ct, mvla_node);
|
||||
|
||||
/* Move the local nodes of the vlapool to be reclaimed to the thread into the global pool */
|
||||
if (!m_vlapool_slist_empty_p(vlapool->thread_data[id].to_be_reclaimed)) {
|
||||
|
||||
+76
-76
@@ -41,7 +41,7 @@
|
||||
USAGE: CONCURRENT_DEF_AS(name, name_t, type [, oplist_of_the_type]) */
|
||||
#define CONCURRENT_DEF_AS(name, name_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
CONCURRENTI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_C0NCURRENT_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
|
||||
@@ -62,7 +62,7 @@
|
||||
USAGE: CONCURRENT_RP_DEF_AS(name, name_t, type [, oplist_of_the_type]) */
|
||||
#define CONCURRENT_RP_DEF_AS(name, name_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
CONCURRENTI_RP_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_C0NCURRENT_RP_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
|
||||
@@ -71,7 +71,7 @@
|
||||
/* Define the oplist of a protected concurrent container given its name and its oplist.
|
||||
USAGE: CONCURRENT_OPLIST(name[, oplist of the type]) */
|
||||
#define CONCURRENT_OPLIST(...) \
|
||||
CONCURRENTI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_C0NCURRENT_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -80,14 +80,14 @@
|
||||
|
||||
/* Deferred evaluation for the oplist definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define CONCURRENTI_OPLIST_P1(arg) CONCURRENTI_OPLIST_P2 arg
|
||||
#define M_C0NCURRENT_OPLIST_P1(arg) M_C0NCURRENT_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define CONCURRENTI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(CONCURRENTI_OPLIST_P3, CONCURRENTI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_C0NCURRENT_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_C0NCURRENT_OPLIST_P3, M_C0NCURRENT_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define CONCURRENTI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_C0NCURRENT_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_CONCURRENT_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* OPLIST definition
|
||||
@@ -95,7 +95,7 @@
|
||||
container (_get returns a pointer to an internal data, data that may be
|
||||
destroyed by another thread).
|
||||
*/
|
||||
#define CONCURRENTI_OPLIST_P3(name, oplist) \
|
||||
#define M_C0NCURRENT_OPLIST_P3(name, oplist) \
|
||||
(M_IF_METHOD(INIT, oplist)(INIT(M_C(name, _init)),) \
|
||||
,M_IF_METHOD(INIT_SET, oplist)(INIT_SET(M_C(name, _init_set)),) \
|
||||
,M_IF_METHOD(SET, oplist)(SET(M_C(name, _set)),) \
|
||||
@@ -135,21 +135,21 @@
|
||||
/* Internal contract
|
||||
NOTE: Can't check too much without locking the container itself
|
||||
*/
|
||||
#define CONCURRENTI_CONTRACT(c) do { \
|
||||
#define M_C0NCURRENT_CONTRACT(c) do { \
|
||||
M_ASSERT ((c) != NULL); \
|
||||
M_ASSERT ( (c)->self == (c)); \
|
||||
} while (0)
|
||||
|
||||
/* Deferred evaluation for the concurrent definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define CONCURRENTI_DEF_P1(arg) CONCURRENTI_DEF_P2 arg
|
||||
#define M_C0NCURRENT_DEF_P1(arg) M_C0NCURRENT_DEF_P2 arg
|
||||
|
||||
/* Validate the value oplist before going further */
|
||||
#define CONCURRENTI_DEF_P2(name, type, oplist, concurrent_t) \
|
||||
M_IF_OPLIST(oplist)(CONCURRENTI_DEF_P3, CONCURRENTI_DEF_FAILURE)(name, type, oplist, concurrent_t)
|
||||
#define M_C0NCURRENT_DEF_P2(name, type, oplist, concurrent_t) \
|
||||
M_IF_OPLIST(oplist)(M_C0NCURRENT_DEF_P3, M_C0NCURRENT_DEF_FAILURE)(name, type, oplist, concurrent_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define CONCURRENTI_DEF_FAILURE(name, type, oplist, concurrent_t) \
|
||||
#define M_C0NCURRENT_DEF_FAILURE(name, type, oplist, concurrent_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(CONCURRENT_DEF): the given argument is not a valid oplist: " M_AS_STR(oplist))
|
||||
|
||||
/* Internal concurrent definition
|
||||
@@ -158,7 +158,7 @@
|
||||
- oplist: oplist of the type of the sub container
|
||||
- concurrent_t: alias for M_C(name, _t) [ type of the container ]
|
||||
*/
|
||||
#define CONCURRENTI_DEF_P3(name, type, oplist, concurrent_t) \
|
||||
#define M_C0NCURRENT_DEF_P3(name, type, oplist, concurrent_t) \
|
||||
\
|
||||
/* Define a concurrent container using a lock */ \
|
||||
typedef struct M_C(name, _s) { \
|
||||
@@ -189,7 +189,7 @@
|
||||
m_mutex_init(out->lock); \
|
||||
m_cond_init(out->there_is_data); \
|
||||
out->self = out; \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
} \
|
||||
\
|
||||
/* Clear the fields of the concurrent object not associated to the \
|
||||
@@ -197,7 +197,7 @@
|
||||
static inline void \
|
||||
M_C(name, _internal_clear)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_clear(out->lock); \
|
||||
m_cond_clear(out->there_is_data); \
|
||||
out->self = NULL; \
|
||||
@@ -210,7 +210,7 @@
|
||||
static inline void \
|
||||
M_C(name, _read_lock)(const concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_lock (out->self->lock); \
|
||||
} \
|
||||
\
|
||||
@@ -220,7 +220,7 @@
|
||||
static inline void \
|
||||
M_C(name, _read_unlock)(const concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_unlock (out->self->lock); \
|
||||
} \
|
||||
\
|
||||
@@ -229,7 +229,7 @@
|
||||
static inline void \
|
||||
M_C(name, _read_wait)(const concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_cond_wait(out->self->there_is_data, out->self->lock); \
|
||||
} \
|
||||
\
|
||||
@@ -240,7 +240,7 @@
|
||||
static inline void \
|
||||
M_C(name, _write_lock)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_lock (out->lock); \
|
||||
} \
|
||||
\
|
||||
@@ -250,7 +250,7 @@
|
||||
static inline void \
|
||||
M_C(name, _write_unlock)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_unlock (out->lock); \
|
||||
} \
|
||||
\
|
||||
@@ -259,7 +259,7 @@
|
||||
static inline void \
|
||||
M_C(name, _write_wait)(const concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_cond_wait(out->self->there_is_data, out->self->lock); \
|
||||
} \
|
||||
\
|
||||
@@ -268,13 +268,13 @@
|
||||
static inline void \
|
||||
M_C(name, _write_signal)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
/* We need to signal this to ALL waiting threads as multiple threads \
|
||||
may wait on a some data of this container. */ \
|
||||
m_cond_broadcast(out->there_is_data); \
|
||||
} \
|
||||
\
|
||||
CONCURRENTI_DEF_FUNC_P3(name, type, oplist, concurrent_t)
|
||||
M_C0NCURRENT_DEF_FUNC_P3(name, type, oplist, concurrent_t)
|
||||
|
||||
|
||||
/* Internal definition of the functions commons to concurrent and rp-concurrent
|
||||
@@ -285,7 +285,7 @@
|
||||
A function is defined only if the underlying container exports the needed
|
||||
services. It is usually one service declared per service exported.
|
||||
*/
|
||||
#define CONCURRENTI_DEF_FUNC_P3(name, type, oplist, concurrent_t) \
|
||||
#define M_C0NCURRENT_DEF_FUNC_P3(name, type, oplist, concurrent_t) \
|
||||
\
|
||||
M_IF_METHOD(INIT, oplist)( \
|
||||
static inline void \
|
||||
@@ -293,7 +293,7 @@
|
||||
{ \
|
||||
M_C(name, _internal_init)(out); \
|
||||
M_CALL_INIT(oplist, out->data); \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
} \
|
||||
,) \
|
||||
\
|
||||
@@ -301,13 +301,13 @@
|
||||
static inline void \
|
||||
M_C(name, _init_set)(concurrent_t out, concurrent_t const src) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(src); \
|
||||
M_C0NCURRENT_CONTRACT(src); \
|
||||
M_ASSERT (out != src); \
|
||||
M_C(name, _internal_init)(out); \
|
||||
M_C(name, _read_lock)(src); \
|
||||
M_CALL_INIT_SET(oplist, out->data, src->data); \
|
||||
M_C(name, _read_unlock)(src); \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
} \
|
||||
,) \
|
||||
\
|
||||
@@ -315,7 +315,7 @@
|
||||
static inline void \
|
||||
M_C(name, _set)(concurrent_t out, concurrent_t const src) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
if (M_UNLIKELY (out == src)) return; \
|
||||
/* Need to order the locks in a total way to avoid lock deadlock. \
|
||||
Indeed, two call to _set can be done in two threads with : \
|
||||
@@ -342,7 +342,7 @@
|
||||
M_C(name, _write_unlock)(out); \
|
||||
M_C(name, _read_unlock)(src); \
|
||||
} \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
} \
|
||||
,) \
|
||||
\
|
||||
@@ -350,7 +350,7 @@
|
||||
static inline void \
|
||||
M_C(name, _clear)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
/* No need to lock. A clear is supposed to be called when all operations \
|
||||
of the container in other threads are terminated */ \
|
||||
M_CALL_CLEAR(oplist, out->data); \
|
||||
@@ -362,13 +362,13 @@
|
||||
static inline void \
|
||||
M_C(name, _init_move)(concurrent_t out, concurrent_t src) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(src); \
|
||||
M_C0NCURRENT_CONTRACT(src); \
|
||||
M_ASSERT (out != src); \
|
||||
/* No need to lock 'src' ? */ \
|
||||
M_C(name, _internal_init)(out); \
|
||||
M_CALL_INIT_MOVE(oplist, out->data, src->data); \
|
||||
M_C(name, _internal_clear)(src); \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
} \
|
||||
,) \
|
||||
\
|
||||
@@ -376,14 +376,14 @@
|
||||
static inline void \
|
||||
M_C(name, _move)(concurrent_t out, concurrent_t src) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
CONCURRENTI_CONTRACT(src); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(src); \
|
||||
/* No need to lock 'src' ? */ \
|
||||
M_C(name, _write_lock)(out); \
|
||||
M_CALL_MOVE(oplist, out->data, src->data); \
|
||||
M_C(name, _write_unlock)(out); \
|
||||
M_C(name, _internal_clear)(src); \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
} \
|
||||
,) \
|
||||
\
|
||||
@@ -391,8 +391,8 @@
|
||||
static inline void \
|
||||
M_C(name, _swap)(concurrent_t out, concurrent_t src) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
CONCURRENTI_CONTRACT(src); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(src); \
|
||||
if (M_UNLIKELY (out == src)) return; \
|
||||
/* See comment above */ \
|
||||
if (out < src) { \
|
||||
@@ -417,7 +417,7 @@
|
||||
static inline void \
|
||||
M_C(name, _clean)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
M_CALL_CLEAN(oplist, out->data); \
|
||||
M_C(name, _write_unlock)(out); \
|
||||
@@ -428,7 +428,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(concurrent_t const out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _read_lock)(out); \
|
||||
bool b = M_CALL_EMPTY_P(oplist, out->data); \
|
||||
M_C(name, _read_unlock)(out); \
|
||||
@@ -440,7 +440,7 @@
|
||||
static inline size_t \
|
||||
M_C(name, _size)(concurrent_t const out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _read_lock)(out); \
|
||||
size_t r = M_CALL_GET_SIZE(oplist, out->data); \
|
||||
M_C(name, _read_unlock)(out); \
|
||||
@@ -452,7 +452,7 @@
|
||||
static inline void \
|
||||
M_C(name, _set_at)(concurrent_t out, M_GET_KEY_TYPE oplist const key, M_GET_VALUE_TYPE oplist const data) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
M_CALL_SET_KEY(oplist, out->data, key, data); \
|
||||
M_C(name, _write_signal)(out); \
|
||||
@@ -464,7 +464,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _get_copy)(M_GET_VALUE_TYPE oplist *out_data, const concurrent_t out, M_GET_KEY_TYPE oplist const key) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_ASSERT (out_data != NULL); \
|
||||
M_C(name, _read_lock)(out); \
|
||||
M_GET_VALUE_TYPE oplist *p = M_CALL_GET_KEY(oplist, out->data, key); \
|
||||
@@ -480,7 +480,7 @@
|
||||
static inline void \
|
||||
M_C(name, _get_at_copy)(M_GET_VALUE_TYPE oplist *out_data, concurrent_t out, M_GET_KEY_TYPE oplist const key) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_ASSERT (out_data != NULL); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
M_GET_VALUE_TYPE oplist *p = M_CALL_GET_SET_KEY(oplist, out->data, key); \
|
||||
@@ -494,7 +494,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _erase)(concurrent_t out, M_GET_KEY_TYPE oplist const key) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
bool b = M_CALL_ERASE_KEY(oplist, out->data, key); \
|
||||
/* We suppose that the container has 'infinite' capacity, so \
|
||||
@@ -508,7 +508,7 @@
|
||||
static inline void \
|
||||
M_C(name, _push)(concurrent_t out, M_GET_SUBTYPE oplist const data) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
M_CALL_PUSH(oplist, out->data, data); \
|
||||
M_C(name, _write_signal)(out); \
|
||||
@@ -520,7 +520,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop)(M_GET_SUBTYPE oplist *p, concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
M_CALL_POP(oplist, p, out->data); \
|
||||
/* See comment above */ \
|
||||
@@ -532,7 +532,7 @@
|
||||
static inline void \
|
||||
M_C(name, _push_move)(concurrent_t out, M_GET_SUBTYPE oplist *data) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
M_CALL_PUSH_MOVE(oplist, out->data, data); \
|
||||
M_C(name, _write_signal)(out); \
|
||||
@@ -544,7 +544,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_move)(M_GET_SUBTYPE oplist *p, concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
M_CALL_POP_MOVE(oplist, p, out->data); \
|
||||
/* See comment above */ \
|
||||
@@ -556,7 +556,7 @@
|
||||
static inline void \
|
||||
M_C(name, _get_str)(string_t str, concurrent_t const out, bool a) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _read_lock)(out); \
|
||||
M_CALL_GET_STR(oplist, str, out->data, a); \
|
||||
M_C(name, _read_unlock)(out); \
|
||||
@@ -567,7 +567,7 @@
|
||||
static inline void \
|
||||
M_C(name, _out_str)(FILE *f, concurrent_t const out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _read_lock)(out); \
|
||||
M_CALL_OUT_STR(oplist, f, out->data); \
|
||||
M_C(name, _read_unlock)(out); \
|
||||
@@ -578,7 +578,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _parse_str)(concurrent_t out, const char str[], const char **e) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
bool b = M_CALL_PARSE_STR(oplist, out->data, str, e); \
|
||||
M_C(name, _write_signal)(out); \
|
||||
@@ -591,7 +591,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _in_str)(concurrent_t out, FILE *f) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
bool b = M_CALL_IN_STR(oplist, out->data, f); \
|
||||
M_C(name, _write_signal)(out); \
|
||||
@@ -604,7 +604,7 @@
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _out_serial)(m_serial_write_t f, concurrent_t const out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _read_lock)(out); \
|
||||
m_serial_return_code_t r = M_CALL_OUT_SERIAL(oplist, f, out->data); \
|
||||
M_C(name, _read_unlock)(out); \
|
||||
@@ -616,7 +616,7 @@
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _in_serial)(concurrent_t out, m_serial_read_t f) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _write_lock)(out); \
|
||||
m_serial_return_code_t r = M_CALL_IN_SERIAL(oplist, out->data, f); \
|
||||
M_C(name, _write_signal)(out); \
|
||||
@@ -629,8 +629,8 @@
|
||||
static inline bool \
|
||||
M_C(name, _equal_p)(concurrent_t const out1, concurrent_t const out2) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out1); \
|
||||
CONCURRENTI_CONTRACT(out2); \
|
||||
M_C0NCURRENT_CONTRACT(out1); \
|
||||
M_C0NCURRENT_CONTRACT(out2); \
|
||||
if (M_UNLIKELY (out1 == out2)) return true; \
|
||||
/* See comment above on mutal mutexs */ \
|
||||
if (out1 < out2) { \
|
||||
@@ -656,7 +656,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _get_blocking)(M_GET_VALUE_TYPE oplist *out_data, const concurrent_t out, M_GET_KEY_TYPE oplist const key, bool blocking) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_ASSERT (out_data != NULL); \
|
||||
bool ret = false; \
|
||||
M_C(name, _read_lock)(out); \
|
||||
@@ -680,7 +680,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _pop_blocking)(M_GET_SUBTYPE oplist *p, concurrent_t out, bool blocking) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_ASSERT (p != NULL); \
|
||||
bool ret = false; \
|
||||
M_C(name, _write_lock)(out); \
|
||||
@@ -703,7 +703,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _pop_move_blocking)(M_GET_SUBTYPE oplist *p, concurrent_t out, bool blocking) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_ASSERT (p != NULL); \
|
||||
bool ret = false; \
|
||||
M_C(name, _write_lock)(out); \
|
||||
@@ -726,7 +726,7 @@
|
||||
static inline size_t \
|
||||
M_C(name, _hash)(concurrent_t const out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
M_C(name, _read_lock)(out); \
|
||||
size_t h = M_CALL_HASH(oplist, out->data); \
|
||||
M_C(name, _read_unlock)(out); \
|
||||
@@ -739,14 +739,14 @@
|
||||
|
||||
/* Deferred evaluation for the RP concurrent definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define CONCURRENTI_RP_DEF_P1(arg) CONCURRENTI_RP_DEF_P2 arg
|
||||
#define M_C0NCURRENT_RP_DEF_P1(arg) M_C0NCURRENT_RP_DEF_P2 arg
|
||||
|
||||
/* Validate the value oplist before going further */
|
||||
#define CONCURRENTI_RP_DEF_P2(name, type, oplist, concurrent_t) \
|
||||
M_IF_OPLIST(oplist)(CONCURRENTI_RP_DEF_P3, CONCURRENTI_RP_DEF_FAILURE)(name, type, oplist, concurrent_t)
|
||||
#define M_C0NCURRENT_RP_DEF_P2(name, type, oplist, concurrent_t) \
|
||||
M_IF_OPLIST(oplist)(M_C0NCURRENT_RP_DEF_P3, M_C0NCURRENT_RP_DEF_FAILURE)(name, type, oplist, concurrent_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define CONCURRENTI_RP_DEF_FAILURE(name, type, oplist, concurrent_t) \
|
||||
#define M_C0NCURRENT_RP_DEF_FAILURE(name, type, oplist, concurrent_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(CONCURRENT_RP_DEF): the given argument is not a valid oplist: " M_AS_STR(oplist))
|
||||
|
||||
/* Internal RP concurrent definition
|
||||
@@ -755,7 +755,7 @@
|
||||
- oplist: oplist of the type of the sub container
|
||||
- concurrent_t: alias for M_C(name, _t) [ type of the container ]
|
||||
*/
|
||||
#define CONCURRENTI_RP_DEF_P3(name, type, oplist, concurrent_t) \
|
||||
#define M_C0NCURRENT_RP_DEF_P3(name, type, oplist, concurrent_t) \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
struct M_C(name, _s) *self; \
|
||||
@@ -782,13 +782,13 @@
|
||||
out->self = out; \
|
||||
out->read_count = 0; \
|
||||
out->writer_waiting = false; \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _internal_clear)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_clear(out->lock); \
|
||||
m_cond_clear(out->rw_done); \
|
||||
m_cond_clear(out->there_is_data); \
|
||||
@@ -798,7 +798,7 @@
|
||||
static inline void \
|
||||
M_C(name, _read_lock)(const concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
struct M_C(name, _s) *self = out->self; \
|
||||
m_mutex_lock (self->lock); \
|
||||
while (self->writer_waiting == true) { \
|
||||
@@ -811,7 +811,7 @@
|
||||
static inline void \
|
||||
M_C(name, _read_unlock)(const concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
struct M_C(name, _s) *self = out->self; \
|
||||
m_mutex_lock (self->lock); \
|
||||
self->read_count --; \
|
||||
@@ -824,7 +824,7 @@
|
||||
static inline void \
|
||||
M_C(name, _write_lock)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_lock (out->lock); \
|
||||
while (out->writer_waiting == true) { \
|
||||
m_cond_wait(out->rw_done, out->lock); \
|
||||
@@ -839,7 +839,7 @@
|
||||
static inline void \
|
||||
M_C(name, _write_unlock)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_lock (out->lock); \
|
||||
out->writer_waiting = false; \
|
||||
m_cond_broadcast (out->rw_done); \
|
||||
@@ -849,7 +849,7 @@
|
||||
static inline void \
|
||||
M_C(name, _read_wait)(const concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
struct M_C(name, _s) *self = out->self; \
|
||||
M_ASSERT (self == out); \
|
||||
m_mutex_lock (out->self->lock); \
|
||||
@@ -868,7 +868,7 @@
|
||||
static inline void \
|
||||
M_C(name, _write_wait)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_lock (out->lock); \
|
||||
out->writer_waiting = false; \
|
||||
m_cond_broadcast (out->rw_done); \
|
||||
@@ -886,13 +886,13 @@
|
||||
static inline void \
|
||||
M_C(name, _write_signal)(concurrent_t out) \
|
||||
{ \
|
||||
CONCURRENTI_CONTRACT(out); \
|
||||
M_C0NCURRENT_CONTRACT(out); \
|
||||
m_mutex_lock (out->lock); \
|
||||
m_cond_broadcast(out->there_is_data); \
|
||||
m_mutex_unlock (out->lock); \
|
||||
} \
|
||||
\
|
||||
CONCURRENTI_DEF_FUNC_P3(name, type, oplist, concurrent_t)
|
||||
M_C0NCURRENT_DEF_FUNC_P3(name, type, oplist, concurrent_t)
|
||||
|
||||
|
||||
#endif
|
||||
@@ -2855,9 +2855,10 @@ static inline size_t m_core_cstr_hash(const char str[])
|
||||
#define M_CHECK_COMPATIBLE_OPLIST(name, inst, type, oplist) \
|
||||
M_IF_METHOD(TYPE, oplist) \
|
||||
( \
|
||||
static inline void M_C3(name, _int_control_type, inst)(void) \
|
||||
static inline void M_C3(m_c0re_ctype_, name, inst)(void) \
|
||||
{ \
|
||||
type x; \
|
||||
/* Proper check using _Generic */ \
|
||||
M_STATIC_ASSERT(_Generic(&x, \
|
||||
M_GET_TYPE oplist *: 1 /* Ok, type matches */, \
|
||||
default: 0 /* NOK, type doesn't match */ ), \
|
||||
@@ -2871,8 +2872,9 @@ static inline size_t m_core_cstr_hash(const char str[])
|
||||
#define M_CHECK_COMPATIBLE_OPLIST(name, inst, type, oplist) \
|
||||
M_IF_METHOD(TYPE, oplist) \
|
||||
( \
|
||||
static inline void M_C3(name, _int_control_type, inst)(void) \
|
||||
static inline void M_C3(m_c0re_ctype_, name, inst)(void) \
|
||||
{ \
|
||||
/* Imperfect check using size of type */ \
|
||||
M_STATIC_ASSERT(sizeof (type) == sizeof (M_GET_TYPE oplist), \
|
||||
M_LIB_TYPE_MISTMACH, \
|
||||
"The given type " M_AS_STR(type) \
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
USAGE: DEQUE_DEF(name, name_t, it_t, type [, oplist_of_the_type]) */
|
||||
#define DEQUE_DEF_AS(name, name_t, it_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
DEQUEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_D3QU3_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t, it_t, M_C(name, _node_ct) ), \
|
||||
(name, __VA_ARGS__, name_t, it_t, M_C(name, _node_ct)))) \
|
||||
M_END_PROTECTED_CODE
|
||||
@@ -47,21 +47,21 @@
|
||||
/* Define the oplist of a deque of a type.
|
||||
USAGE: DEQUE_OPLIST(name[, oplist of the type]) */
|
||||
#define DEQUE_OPLIST(...) \
|
||||
DEQUEI_OPLIST_P1 (M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_D3QU3_OPLIST_P1 (M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
/* Default initial size of a bucket of items */
|
||||
#ifndef DEQUEUI_DEFAULT_SIZE
|
||||
#define DEQUEUI_DEFAULT_SIZE 8
|
||||
#ifndef M_D3QU3_DEFAULT_SIZE
|
||||
#define M_D3QU3_DEFAULT_SIZE 8
|
||||
#endif
|
||||
|
||||
/* Define the internal contract of a deque */
|
||||
#define DEQUEI_CONTRACT(d) do { \
|
||||
#define M_D3QU3_CONTRACT(d) do { \
|
||||
M_ASSERT ((d) != NULL); \
|
||||
M_ASSERT ((d)->default_size >= DEQUEUI_DEFAULT_SIZE); \
|
||||
M_ASSERT ((d)->default_size >= M_D3QU3_DEFAULT_SIZE); \
|
||||
M_ASSERT ((d)->front->node != NULL); \
|
||||
M_ASSERT ((d)->front->index <= (d)->front->node->size); \
|
||||
M_ASSERT ((d)->back->node != NULL); \
|
||||
@@ -74,14 +74,14 @@
|
||||
|
||||
/* Deferred evaluation for the deque definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define DEQUEI_DEF_P1(arg) DEQUEI_DEF_P2 arg
|
||||
#define M_D3QU3_DEF_P1(arg) M_D3QU3_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define DEQUEI_DEF_P2(name, type, oplist, deque_t, it_t, node_t) \
|
||||
M_IF_OPLIST(oplist)(DEQUEI_DEF_P3, DEQUEI_DEF_FAILURE)(name, type, oplist, deque_t, it_t, node_t)
|
||||
#define M_D3QU3_DEF_P2(name, type, oplist, deque_t, it_t, node_t) \
|
||||
M_IF_OPLIST(oplist)(M_D3QU3_DEF_P3, M_D3QU3_DEF_FAILURE)(name, type, oplist, deque_t, it_t, node_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define DEQUEI_DEF_FAILURE(name, type, oplist, deque_t, it_t, node_t) \
|
||||
#define M_D3QU3_DEF_FAILURE(name, type, oplist, deque_t, it_t, node_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(DEQUE_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
/* Internal deque definition
|
||||
@@ -92,7 +92,7 @@
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
- node_t: alias for node_t [ node ]
|
||||
*/
|
||||
#define DEQUEI_DEF_P3(name, type, oplist, deque_t, it_t, node_t) \
|
||||
#define M_D3QU3_DEF_P3(name, type, oplist, deque_t, it_t, node_t) \
|
||||
\
|
||||
/* It is a linked list of buckets of the types, \
|
||||
each new created bucket size grows compared to the previous one \
|
||||
@@ -155,8 +155,9 @@
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
/* Allocate a new node for a deque */ \
|
||||
static inline node_t* \
|
||||
M_C(name, _int_new_node)(deque_t d) \
|
||||
M_C3(m_d3qu3_,name,_new_node)(deque_t d) \
|
||||
{ \
|
||||
size_t def = d->default_size; \
|
||||
/* Test for overflow of the size computation */ \
|
||||
@@ -164,7 +165,7 @@
|
||||
M_MEMORY_FULL(sizeof(node_t)+def * sizeof(type)); \
|
||||
return NULL; \
|
||||
} \
|
||||
/* Alloc a new node */ \
|
||||
/* Alloc a new node with dynamic size */ \
|
||||
node_t*n = (node_t*) (void*) \
|
||||
M_CALL_REALLOC(oplist, char, NULL, \
|
||||
sizeof(node_t) + def * sizeof(type) ); \
|
||||
@@ -187,22 +188,22 @@
|
||||
M_C(name, _init)(deque_t d) \
|
||||
{ \
|
||||
M_C(name, _node_list_init)(d->list); \
|
||||
d->default_size = DEQUEUI_DEFAULT_SIZE; \
|
||||
d->default_size = M_D3QU3_DEFAULT_SIZE; \
|
||||
d->count = 0; \
|
||||
node_t *n = M_C(name, _int_new_node)(d); \
|
||||
node_t *n = M_C3(m_d3qu3_,name,_new_node)(d); \
|
||||
if (n == NULL) return; \
|
||||
M_C(name, _node_list_push_back)(d->list, n); \
|
||||
d->front->node = n; \
|
||||
d->front->index = DEQUEUI_DEFAULT_SIZE/2; \
|
||||
d->front->index = M_D3QU3_DEFAULT_SIZE/2; \
|
||||
d->back->node = n; \
|
||||
d->back->index = DEQUEUI_DEFAULT_SIZE/2; \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
d->back->index = M_D3QU3_DEFAULT_SIZE/2; \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clean)(deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
node_t *min_node = NULL; \
|
||||
for(node_t *n = d->front->node; \
|
||||
n != NULL ; \
|
||||
@@ -221,13 +222,13 @@
|
||||
d->back->node = min_node; \
|
||||
d->back->index = min_node->size / 2; \
|
||||
d->count = 0; \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_C(name, _clean)(d); \
|
||||
/* We have registered the delete operator to clear all objects */ \
|
||||
M_C(name, _node_list_clear)(d->list); \
|
||||
@@ -240,7 +241,7 @@
|
||||
static inline type * \
|
||||
M_C(name, _push_back_raw)(deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
node_t *n = d->back->node; \
|
||||
size_t index = d->back->index; \
|
||||
if (M_UNLIKELY (n->size <= index)) { \
|
||||
@@ -248,7 +249,7 @@
|
||||
n = M_C(name, _node_list_next_obj)(d->list, n); \
|
||||
if (n == NULL) { \
|
||||
/* No node exists, allocate a new one */ \
|
||||
n = M_C(name, _int_new_node)(d); \
|
||||
n = M_C3(m_d3qu3_,name,_new_node)(d); \
|
||||
if (M_UNLIKELY (n == NULL)) return NULL; \
|
||||
M_C(name, _node_list_push_back)(d->list, n); \
|
||||
} \
|
||||
@@ -259,7 +260,7 @@
|
||||
index++; \
|
||||
d->count ++; \
|
||||
d->back->index = index; \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
@@ -297,7 +298,7 @@
|
||||
static inline type* \
|
||||
M_C(name, _push_front_raw)(deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
node_t *n = d->front->node; \
|
||||
size_t index = d->front->index; \
|
||||
index --; \
|
||||
@@ -305,7 +306,7 @@
|
||||
if (M_UNLIKELY (n->size <= index)) { \
|
||||
n = M_C(name, _node_list_previous_obj)(d->list, n); \
|
||||
if (n == NULL) { \
|
||||
n = M_C(name, _int_new_node)(d); \
|
||||
n = M_C3(m_d3qu3_,name,_new_node)(d); \
|
||||
if (M_UNLIKELY (n == NULL)) return NULL; \
|
||||
M_C(name, _node_list_push_front)(d->list, n); \
|
||||
} \
|
||||
@@ -315,7 +316,7 @@
|
||||
type *ret = &n->data[index]; \
|
||||
d->count ++; \
|
||||
d->front->index = index; \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
@@ -353,7 +354,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_back)(type *ptr, deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT(d->count > 0); \
|
||||
node_t *n = d->back->node; \
|
||||
size_t index = d->back->index; \
|
||||
@@ -382,7 +383,7 @@
|
||||
M_CALL_CLEAR(oplist, n->data[index]); \
|
||||
d->count --; \
|
||||
d->back->index = index; \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
M_IF_METHOD(INIT, oplist)( \
|
||||
@@ -399,7 +400,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_front)(type *ptr, deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT(d->count > 0); \
|
||||
node_t *n = d->front->node; \
|
||||
size_t index = d->front->index; \
|
||||
@@ -444,7 +445,7 @@
|
||||
static inline type * \
|
||||
M_C(name, _back)(const deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT (d->count > 0); \
|
||||
size_t i = d->back->index; \
|
||||
node_t *n = d->back->node; \
|
||||
@@ -459,7 +460,7 @@
|
||||
static inline type * \
|
||||
M_C(name, _front)(const deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT (d->count > 0); \
|
||||
size_t i = d->front->index; \
|
||||
node_t *n = d->front->node; \
|
||||
@@ -474,14 +475,14 @@
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
return d->count; \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _capacity_back)(const deque_t v) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(v); \
|
||||
M_D3QU3_CONTRACT(v); \
|
||||
size_t s = 0; \
|
||||
for(node_t *n = M_C(name, _node_list_back)(v->list); \
|
||||
n != NULL ; \
|
||||
@@ -495,7 +496,7 @@
|
||||
static inline size_t \
|
||||
M_C(name, _capacity_front)(const deque_t v) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(v); \
|
||||
M_D3QU3_CONTRACT(v); \
|
||||
size_t s = 0; \
|
||||
for(node_t *n = M_C(name, _node_list_front)(v->list); \
|
||||
n != NULL ; \
|
||||
@@ -515,14 +516,14 @@
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(const deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
return d->count == 0; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _it)(it_t it, const deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->node = d->front->node; \
|
||||
it->index = d->front->index; \
|
||||
@@ -532,7 +533,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it_last)(it_t it, const deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->node = d->back->node; \
|
||||
it->index = d->back->index - 1; \
|
||||
@@ -547,7 +548,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it_end)(it_t it, const deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->node = d->back->node; \
|
||||
it->index = d->back->index; \
|
||||
@@ -651,28 +652,28 @@
|
||||
static inline void \
|
||||
M_C(name, _init_set)(deque_t d, const deque_t src) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(src); \
|
||||
M_D3QU3_CONTRACT(src); \
|
||||
M_ASSERT (d != NULL); \
|
||||
M_C(name, _node_list_init)(d->list); \
|
||||
d->default_size = DEQUEUI_DEFAULT_SIZE + src->count; \
|
||||
d->default_size = M_D3QU3_DEFAULT_SIZE + src->count; \
|
||||
d->count = src->count; \
|
||||
node_t *n = M_C(name, _int_new_node)(d); \
|
||||
node_t *n = M_C3(m_d3qu3_,name,_new_node)(d); \
|
||||
if (n == NULL) return; \
|
||||
d->default_size /= 2; \
|
||||
M_C(name, _node_list_push_back)(d->list, n); \
|
||||
d->front->node = n; \
|
||||
d->front->index = DEQUEUI_DEFAULT_SIZE/2; \
|
||||
d->front->index = M_D3QU3_DEFAULT_SIZE/2; \
|
||||
d->back->node = n; \
|
||||
d->back->index = DEQUEUI_DEFAULT_SIZE/2 + src->count; \
|
||||
d->back->index = M_D3QU3_DEFAULT_SIZE/2 + src->count; \
|
||||
it_t it; \
|
||||
size_t i = DEQUEUI_DEFAULT_SIZE/2; \
|
||||
size_t i = M_D3QU3_DEFAULT_SIZE/2; \
|
||||
for(M_C(name, _it)(it, src); !M_C(name, _end_p)(it) ; M_C(name, _next)(it)) { \
|
||||
type const *obj = M_C(name, _cref)(it); \
|
||||
M_CALL_INIT_SET(oplist, n->data[i], *obj); \
|
||||
i++; \
|
||||
M_ASSERT (i <= d->back->index); \
|
||||
} \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -688,7 +689,7 @@
|
||||
static inline void \
|
||||
M_C(name, _init_move)(deque_t d, deque_t src) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(src); \
|
||||
M_D3QU3_CONTRACT(src); \
|
||||
M_ASSERT (d!= NULL); \
|
||||
M_C(name,_node_list_init_move)(d->list, src->list); \
|
||||
d->front->node = src->front->node; \
|
||||
@@ -698,24 +699,24 @@
|
||||
d->default_size = src->default_size; \
|
||||
d->count = src->count; \
|
||||
memset(src, 0, sizeof(deque_t)); \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _move)(deque_t d, deque_t src) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
DEQUEI_CONTRACT(src); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(src); \
|
||||
M_C(name, _clear)(d); \
|
||||
M_C(name, _init_move)(d, src); \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _swap)(deque_t d, deque_t e) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
DEQUEI_CONTRACT(e); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(e); \
|
||||
M_C(name, _node_list_swap) (d->list, e->list); \
|
||||
M_SWAP(node_t *, d->front->node, e->front->node); \
|
||||
M_SWAP(node_t *, d->back->node, e->back->node); \
|
||||
@@ -723,14 +724,14 @@
|
||||
M_SWAP(size_t, d->back->index, e->back->index); \
|
||||
M_SWAP(size_t, d->default_size, e->default_size); \
|
||||
M_SWAP(size_t, d->count, e->count); \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
DEQUEI_CONTRACT(e); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(e); \
|
||||
} \
|
||||
\
|
||||
static inline type* \
|
||||
M_C(name, _get)(deque_t d, size_t key) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT_INDEX (key, d->count); \
|
||||
const size_t index0 = d->front->index; \
|
||||
size_t count = 0; \
|
||||
@@ -757,19 +758,19 @@
|
||||
static inline void \
|
||||
M_C(name, _set_at)(deque_t d, size_t key, type const x) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT_INDEX (key, d->count); \
|
||||
type *p = M_C(name, _get)(d, key); \
|
||||
M_CALL_SET(oplist, *p, x); \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
} \
|
||||
\
|
||||
M_IF_METHOD(EQUAL, oplist)( \
|
||||
static inline bool \
|
||||
M_C(name, _equal_p)(const deque_t d1, const deque_t d2) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d1); \
|
||||
DEQUEI_CONTRACT(d2); \
|
||||
M_D3QU3_CONTRACT(d1); \
|
||||
M_D3QU3_CONTRACT(d2); \
|
||||
if (d1->count != d2->count) \
|
||||
return false; \
|
||||
it_t it1; \
|
||||
@@ -791,7 +792,7 @@
|
||||
static inline size_t \
|
||||
M_C(name, _hash)(const deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_HASH_DECL(hash); \
|
||||
it_t it; \
|
||||
for(M_C(name, _it)(it, d); !M_C(name, _end_p)(it); M_C(name, _next)(it)) { \
|
||||
@@ -806,13 +807,13 @@
|
||||
static inline void \
|
||||
M_C(name, _swap_at)(deque_t d, size_t i, size_t j) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
M_ASSERT_INDEX (i, d->count); \
|
||||
M_ASSERT_INDEX (j, d->count); \
|
||||
type *obj1 = M_C(name, _get)(d, i); \
|
||||
type *obj2 = M_C(name, _get)(d, j); \
|
||||
M_CALL_SWAP(oplist, *obj1, *obj2); \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_D3QU3_CONTRACT(d); \
|
||||
} \
|
||||
, /* NO SWAP */) \
|
||||
\
|
||||
@@ -820,8 +821,7 @@
|
||||
static inline void \
|
||||
M_C(name, _get_str)(string_t str, deque_t const deque, bool append) \
|
||||
{ \
|
||||
STRINGI_CONTRACT(str); \
|
||||
DEQUEI_CONTRACT(deque); \
|
||||
M_D3QU3_CONTRACT(deque); \
|
||||
(append ? string_cat_str : string_set_str) (str, "["); \
|
||||
it_t it; \
|
||||
for (M_C(name, _it)(it, deque) ; \
|
||||
@@ -833,7 +833,6 @@
|
||||
string_push_back (str, M_GET_SEPARATOR oplist); \
|
||||
} \
|
||||
string_push_back (str, ']'); \
|
||||
STRINGI_CONTRACT(str); \
|
||||
} \
|
||||
, /* no GET_STR */ ) \
|
||||
\
|
||||
@@ -841,7 +840,7 @@
|
||||
static inline void \
|
||||
M_C(name, _out_str)(FILE *file, const deque_t deque) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(deque); \
|
||||
M_D3QU3_CONTRACT(deque); \
|
||||
M_ASSERT (file != NULL); \
|
||||
fputc ('[', file); \
|
||||
it_t it; \
|
||||
@@ -861,7 +860,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _parse_str)(deque_t deque, const char str[], const char **endp) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(deque); \
|
||||
M_D3QU3_CONTRACT(deque); \
|
||||
M_ASSERT (str != NULL); \
|
||||
M_C(name,_clean)(deque); \
|
||||
bool success = false; \
|
||||
@@ -879,7 +878,7 @@
|
||||
if (b == false || c == 0) { goto exit_clear; } \
|
||||
M_C(name, _push_back)(deque, item); \
|
||||
} while (c == M_GET_SEPARATOR oplist); \
|
||||
DEQUEI_CONTRACT(deque); \
|
||||
M_D3QU3_CONTRACT(deque); \
|
||||
success = (c == ']'); \
|
||||
exit_clear: \
|
||||
M_CALL_CLEAR(oplist, item); \
|
||||
@@ -893,7 +892,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _in_str)(deque_t deque, FILE *file) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(deque); \
|
||||
M_D3QU3_CONTRACT(deque); \
|
||||
M_ASSERT (file != NULL); \
|
||||
M_C(name,_clean)(deque); \
|
||||
int c = fgetc(file); \
|
||||
@@ -911,7 +910,7 @@
|
||||
M_C(name, _push_back)(deque, item); \
|
||||
} while (c == M_GET_SEPARATOR oplist); \
|
||||
M_CALL_CLEAR(oplist, item); \
|
||||
DEQUEI_CONTRACT(deque); \
|
||||
M_D3QU3_CONTRACT(deque); \
|
||||
return c == ']'; \
|
||||
} \
|
||||
, /* no IN_STR */ ) \
|
||||
@@ -920,7 +919,7 @@
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _out_serial)(m_serial_write_t f, const deque_t deque) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(deque); \
|
||||
M_D3QU3_CONTRACT(deque); \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_local_t local; \
|
||||
m_serial_return_code_t ret; \
|
||||
@@ -945,7 +944,7 @@
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _in_serial)(deque_t deque, m_serial_read_t f) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(deque); \
|
||||
M_D3QU3_CONTRACT(deque); \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_local_t local; \
|
||||
m_serial_return_code_t ret; \
|
||||
@@ -969,18 +968,18 @@
|
||||
|
||||
/* Deferred evaluation for the oplist definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define DEQUEI_OPLIST_P1(arg) DEQUEI_OPLIST_P2 arg
|
||||
#define M_D3QU3_OPLIST_P1(arg) M_D3QU3_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define DEQUEI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(DEQUEI_OPLIST_P3, DEQUEI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_D3QU3_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_D3QU3_OPLIST_P3, M_D3QU3_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define DEQUEI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_D3QU3_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_DEQUE_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* OPLIST definition of a deque */
|
||||
#define DEQUEI_OPLIST_P3(name, oplist) \
|
||||
#define M_D3QU3_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _init)) \
|
||||
,INIT_SET(M_C(name, _init_set)) \
|
||||
,INIT_WITH(API_1(M_INIT_VAI)) \
|
||||
|
||||
+54
-54
@@ -43,7 +43,7 @@
|
||||
*/
|
||||
#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_IF_NARGS_EQ1(__VA_ARGS__)(M_FUNC0BJ_ITF_NO_PARAM_DEF, M_FUNC0BJ_ITF_PARAM_DEF)(name, name_t, __VA_ARGS__) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
*/
|
||||
#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_IF_NARGS_EQ1(__VA_ARGS__)(M_FUNC0BJ_INS_NO_ATTR_DEF, M_FUNC0BJ_INS_ATTR_DEF)(name, name_t, base_name, param_list, __VA_ARGS__) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
* FUNC_OBJ_INS_OPLIST(name, oplist of the attr1, ...)
|
||||
*/
|
||||
#define FUNC_OBJ_INS_OPLIST(...) \
|
||||
M_IF_NARGS_EQ1(__VA_ARGS__)(FUNCOBJI_INS_NO_ATTR_OPLIST, FUNCOBJI_INS_ATTR_OPLIST_P1)( __VA_ARGS__)
|
||||
M_IF_NARGS_EQ1(__VA_ARGS__)(M_FUNC0BJ_INS_NO_ATTR_OPLIST, M_FUNC0BJ_INS_ATTR_OPLIST_P1)( __VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
*/
|
||||
|
||||
/* Specialization of the OPLIST in function if there is at least one member or not */
|
||||
#define FUNCOBJI_INS_NO_ATTR_OPLIST(name) ( \
|
||||
#define M_FUNC0BJ_INS_NO_ATTR_OPLIST(name) ( \
|
||||
NAME(name), \
|
||||
TYPE(M_C(name, _ct)), \
|
||||
CLEAR(M_C(name, _clear)), \
|
||||
@@ -117,15 +117,15 @@
|
||||
)
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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__)
|
||||
#define M_FUNC0BJ_INS_ATTR_OPLIST_P1(name, ...) \
|
||||
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(M_FUNC0BJ_INS_ATTR_OPLIST_P3, M_FUNC0BJ_INS_ATTR_OPLIST_FAILURE)(name, __VA_ARGS__)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define FUNCOBJI_INS_ATTR_OPLIST_FAILURE(name, ...) \
|
||||
#define M_FUNC0BJ_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, ...) ( \
|
||||
#define M_FUNC0BJ_INS_ATTR_OPLIST_P3(name, ...) ( \
|
||||
NAME(name), \
|
||||
TYPE(M_C(name, _ct)), \
|
||||
INIT_WITH(M_C(name, _init_with)), \
|
||||
@@ -141,7 +141,7 @@
|
||||
* - 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) \
|
||||
#define M_FUNC0BJ_ITF_NO_PARAM_DEF(name, interface_t, retcode) \
|
||||
\
|
||||
/* Forward declaration */ \
|
||||
struct M_C(name, _s); \
|
||||
@@ -175,7 +175,7 @@
|
||||
* - 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, ...) \
|
||||
#define M_FUNC0BJ_ITF_PARAM_DEF(name, interface_t, retcode, ...) \
|
||||
\
|
||||
/* Forward declaration */ \
|
||||
struct M_C(name, _s); \
|
||||
@@ -183,7 +183,7 @@
|
||||
/* Internal types for instance */ \
|
||||
typedef retcode M_C(name, _retcode_ct); \
|
||||
/* Define types for all parameters */ \
|
||||
M_MAP3(FUNCOBJI_BASE_TYPE, name, __VA_ARGS__) \
|
||||
M_MAP3(M_FUNC0BJ_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__); \
|
||||
\
|
||||
@@ -196,18 +196,18 @@
|
||||
\
|
||||
static inline retcode \
|
||||
M_C(name, _call)(interface_t funcobj \
|
||||
M_MAP3(FUNCOBJI_BASE_ARGLIST, name, __VA_ARGS__) ) \
|
||||
M_MAP3(M_FUNC0BJ_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__) ); \
|
||||
funcobj->callback(funcobj M_MAP3(M_FUNC0BJ_BASE_ARGCALL, name, __VA_ARGS__) ); \
|
||||
}
|
||||
|
||||
|
||||
/* Specialization of the definition a function object instance of name 'name'
|
||||
* with no member attribute.
|
||||
*/
|
||||
#define FUNCOBJI_INS_NO_ATTR_DEF(name, instance_t, base_name, param_list, callback_core) \
|
||||
#define M_FUNC0BJ_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]; \
|
||||
@@ -219,7 +219,7 @@
|
||||
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) \
|
||||
M_MAP3(M_FUNC0BJ_INS_ARGLIST, base_name, M_OPFLAT param_list) \
|
||||
) \
|
||||
) \
|
||||
{ \
|
||||
@@ -257,55 +257,55 @@
|
||||
* with mandatory member attribute.
|
||||
* First inject oplist in member attributes.
|
||||
*/
|
||||
#define FUNCOBJI_INS_ATTR_DEF(name, instance_t, base_name, param_list, callback_core, ...) \
|
||||
FUNCOBJI_INS_ATTR_DEF_P2(name, instance_t, base_name, param_list, callback_core, FUNCOBJI_INJECT_GLOBAL(__VA_ARGS__) )
|
||||
#define M_FUNC0BJ_INS_ATTR_DEF(name, instance_t, base_name, param_list, callback_core, ...) \
|
||||
M_FUNC0BJ_INS_ATTR_DEF_P2(name, instance_t, base_name, param_list, callback_core, M_FUNC0BJ_INJECT_GLOBAL(__VA_ARGS__) )
|
||||
|
||||
/* Inject the oplist within the list of arguments */
|
||||
#define FUNCOBJI_INJECT_GLOBAL(...) \
|
||||
M_MAP_C(FUNCOBJI_INJECT_OPLIST_A, __VA_ARGS__)
|
||||
#define M_FUNC0BJ_INJECT_GLOBAL(...) \
|
||||
M_MAP_C(M_FUNC0BJ_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 ) \
|
||||
FUNCOBJI_INJECT_OPLIST_B duo_or_trio
|
||||
#define FUNCOBJI_INJECT_OPLIST_B( f, ... ) \
|
||||
#define M_FUNC0BJ_INJECT_OPLIST_A( duo_or_trio ) \
|
||||
M_FUNC0BJ_INJECT_OPLIST_B duo_or_trio
|
||||
#define M_FUNC0BJ_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(...) \
|
||||
M_IF(M_REDUCE(FUNCOBJI_IS_OPLIST_P, M_AND, __VA_ARGS__))
|
||||
#define M_FUNC0BJ_IF_ALL_OPLIST(...) \
|
||||
M_IF(M_REDUCE(M_FUNC0BJ_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 M_FUNC0BJ_IS_OPLIST_P(a) \
|
||||
M_OPLIST_P(M_RET_ARG3 a)
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define FUNCOBJI_INS_ATTR_DEF_P2(name, instance_t, base_name, param_list, callback_core, ...) \
|
||||
FUNCOBJI_IF_ALL_OPLIST(__VA_ARGS__)(FUNCOBJI_INS_ATTR_DEF_P3, FUNCOBJI_INS_ATTR_DEF_FAILURE)(name, instance_t, base_name, param_list, callback_core, __VA_ARGS__)
|
||||
#define M_FUNC0BJ_INS_ATTR_DEF_P2(name, instance_t, base_name, param_list, callback_core, ...) \
|
||||
M_FUNC0BJ_IF_ALL_OPLIST(__VA_ARGS__)(M_FUNC0BJ_INS_ATTR_DEF_P3, M_FUNC0BJ_INS_ATTR_DEF_FAILURE)(name, instance_t, base_name, param_list, callback_core, __VA_ARGS__)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define FUNCOBJI_INS_ATTR_DEF_FAILURE(name, instance_t, base_name, param_list, callback_core, ...) \
|
||||
#define M_FUNC0BJ_INS_ATTR_DEF_FAILURE(name, instance_t, base_name, param_list, callback_core, ...) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(FUNC_OBJ_INS_DEF): at least one of the given argument is not a valid oplist: " #__VA_ARGS__)
|
||||
|
||||
/* Expand the Function Object with members */
|
||||
#define FUNCOBJI_INS_ATTR_DEF_P3(name, instance_t, base_name, param_list, callback_core, ...) \
|
||||
#define M_FUNC0BJ_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__) \
|
||||
M_MAP(M_FUNC0BJ_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__) \
|
||||
M_FUNC0BJ_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) \
|
||||
M_MAP3(M_FUNC0BJ_INS_ARGLIST, base_name, M_OPFLAT param_list) \
|
||||
) \
|
||||
) \
|
||||
{ \
|
||||
@@ -315,16 +315,16 @@
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init_with)(instance_t obj M_MAP(FUNCOBJI_INS_ATTR_LIST, __VA_ARGS__)) \
|
||||
M_C(name, _init_with)(instance_t obj M_MAP(M_FUNC0BJ_INS_ATTR_LIST, __VA_ARGS__)) \
|
||||
{ \
|
||||
obj->callback = M_C(name, _callback); \
|
||||
M_MAP(FUNCOBJI_INS_ATTR_INIT_SET, __VA_ARGS__); \
|
||||
M_MAP(M_FUNC0BJ_INS_ATTR_INIT_SET, __VA_ARGS__); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(instance_t obj) \
|
||||
{ \
|
||||
M_MAP(FUNCOBJI_INS_ATTR_CLEAR, __VA_ARGS__); \
|
||||
M_MAP(M_FUNC0BJ_INS_ATTR_CLEAR, __VA_ARGS__); \
|
||||
} \
|
||||
\
|
||||
static inline struct M_C(base_name, _s) * \
|
||||
@@ -333,65 +333,65 @@
|
||||
return (struct M_C(base_name, _s) *) obj; \
|
||||
} \
|
||||
\
|
||||
M_IF(FUNCOBJI_TEST_METHOD_P(INIT, __VA_ARGS)) \
|
||||
M_IF(M_FUNC0BJ_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__); \
|
||||
M_MAP(M_FUNC0BJ_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 M_FUNC0BJ_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 M_FUNC0BJ_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 M_FUNC0BJ_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 M_FUNC0BJ_INS_ATTR_STRUCT(arg) \
|
||||
M_RET_ARG2 arg M_RET_ARG1 arg;
|
||||
|
||||
#define FUNCOBJI_INS_ATTR_LIST(arg) \
|
||||
#define M_FUNC0BJ_INS_ATTR_LIST(arg) \
|
||||
M_DEFERRED_COMMA M_RET_ARG2 arg const M_RET_ARG1 arg
|
||||
|
||||
#define FUNCOBJI_INS_ATTR_INIT(arg) \
|
||||
#define M_FUNC0BJ_INS_ATTR_INIT(arg) \
|
||||
M_CALL_INIT(M_RET_ARG3 arg, obj -> M_RET_ARG1 arg);
|
||||
|
||||
#define FUNCOBJI_INS_ATTR_INIT_SET(arg) \
|
||||
#define M_FUNC0BJ_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 M_FUNC0BJ_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 M_FUNC0BJ_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 M_FUNC0BJ_TEST_METHOD2_P(method, op) \
|
||||
M_TEST_METHOD_P(method, op)
|
||||
#define FUNCOBJI_TEST_METHOD1_P(method, arg) \
|
||||
M_APPLY(FUNCOBJI_TEST_METHOD2_P, method, M_RET_ARG3 arg)
|
||||
#define FUNCOBJI_TEST_METHOD_P(method, ...) \
|
||||
M_IF(M_REDUCE2(FUNCOBJI_TEST_METHOD1_P, M_AND, method, __VA_ARGS__))
|
||||
#define M_FUNC0BJ_TEST_METHOD1_P(method, arg) \
|
||||
M_APPLY(M_FUNC0BJ_TEST_METHOD2_P, method, M_RET_ARG3 arg)
|
||||
#define M_FUNC0BJ_TEST_METHOD_P(method, ...) \
|
||||
M_IF(M_REDUCE2(M_FUNC0BJ_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, ...) \
|
||||
M_MAP2(FUNCOBJI_CONTROL_OPLIST, name, __VA_ARGS__)
|
||||
#define FUNCOBJI_CONTROL_OPLIST(name, a) \
|
||||
#define M_FUNC0BJ_CONTROL_ALL_OPLIST(name, ...) \
|
||||
M_MAP2(M_FUNC0BJ_CONTROL_OPLIST, name, __VA_ARGS__)
|
||||
#define M_FUNC0BJ_CONTROL_OPLIST(name, a) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, M_RET_ARG1 a, M_RET_ARG2 a, M_RET_ARG3 a)
|
||||
|
||||
|
||||
|
||||
+45
-45
@@ -61,23 +61,23 @@ typedef struct genint_s {
|
||||
} genint_t[1];
|
||||
|
||||
// Define the max absolute supported value
|
||||
#define GENINT_MAX_ALLOC (GENINT_LIMBSIZE * (GENINT_LIMBSIZE - GENINT_ABA_CPT))
|
||||
#define GENINT_MAX_ALLOC (M_GEN1NT_LIMBSIZE * (M_GEN1NT_LIMBSIZE - M_GEN1NT_ABA_CPT))
|
||||
|
||||
// Define the size of a limb in bits.
|
||||
#define GENINT_LIMBSIZE ((unsigned)(sizeof(genint_limb_ct) * CHAR_BIT))
|
||||
#define M_GEN1NT_LIMBSIZE ((unsigned)(sizeof(genint_limb_ct) * CHAR_BIT))
|
||||
|
||||
// Define the contract of a genint
|
||||
#define GENINT_CONTRACT(s) do { \
|
||||
#define M_GEN1NT_CONTRACT(s) do { \
|
||||
M_ASSERT (s != NULL); \
|
||||
M_ASSERT (s->n > 0 && s->n <= GENINT_MAX_ALLOC); \
|
||||
M_ASSERT ((s->max+1) * GENINT_LIMBSIZE >= s->n); \
|
||||
M_ASSERT ((s->max+1) * M_GEN1NT_LIMBSIZE >= s->n); \
|
||||
M_ASSERT (s->data != NULL); \
|
||||
} while (0)
|
||||
|
||||
// Define the limb one
|
||||
#define GENINT_ONE ((genint_limb_ct)1)
|
||||
#define M_GEN1NT_ONE ((genint_limb_ct)1)
|
||||
|
||||
#define GENINT_FULL_MASK ULLONG_MAX
|
||||
#define M_GEN1NT_FULL_MASK ULLONG_MAX
|
||||
|
||||
// Value returned in case of error (not integer available).
|
||||
#define GENINT_ERROR (UINT_MAX)
|
||||
@@ -85,18 +85,18 @@ typedef struct genint_s {
|
||||
/* 32 bits of the master mask are kept for handling the ABA problem.
|
||||
* NOTE: May be too much. 16 bits should be more than enough. TBC
|
||||
*/
|
||||
#define GENINT_ABA_CPT 32
|
||||
#define GENINT_ABA_CPT_T uint32_t
|
||||
#define M_GEN1NT_ABA_CPT 32
|
||||
#define M_GEN1NT_ABA_CPT_T uint32_t
|
||||
|
||||
// Set the bit 'i' of the master limb, and increase ABA counter.
|
||||
#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)))
|
||||
#define M_GEN1NT_MASTER_SET(master, i) \
|
||||
((((master)& (~((M_GEN1NT_ONE<< M_GEN1NT_ABA_CPT)-1))) | (M_GEN1NT_ONE << (M_GEN1NT_LIMBSIZE - 1 - i))) \
|
||||
|((M_GEN1NT_ABA_CPT_T)((master) + 1)))
|
||||
|
||||
// Reset the bit i of the master limb, and increase ABA counter.
|
||||
#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)))
|
||||
#define M_GEN1NT_MASTER_RESET(master, i) \
|
||||
(((master) & (~((M_GEN1NT_ONE<< M_GEN1NT_ABA_CPT)-1)) & ~(M_GEN1NT_ONE << (M_GEN1NT_LIMBSIZE - 1 - i))) \
|
||||
|((M_GEN1NT_ABA_CPT_T)((master) + 1)))
|
||||
|
||||
/* Initialize an integer generator (CONSTRUCTOR).
|
||||
* Initialy, the container is full of all the integers up to 'n-1'
|
||||
@@ -109,8 +109,8 @@ static inline void
|
||||
genint_init(genint_t s, unsigned int n)
|
||||
{
|
||||
M_ASSERT (s != NULL && n > 0 && n <= GENINT_MAX_ALLOC);
|
||||
const size_t alloc = (n + GENINT_LIMBSIZE - 1) / GENINT_LIMBSIZE;
|
||||
const unsigned int index = n % GENINT_LIMBSIZE;
|
||||
const size_t alloc = (n + M_GEN1NT_LIMBSIZE - 1) / M_GEN1NT_LIMBSIZE;
|
||||
const unsigned int index = n % M_GEN1NT_LIMBSIZE;
|
||||
atomic_ullong *ptr = M_MEMORY_REALLOC (atomic_ullong, NULL, alloc);
|
||||
if (M_UNLIKELY (ptr == NULL)) {
|
||||
M_MEMORY_FULL(alloc);
|
||||
@@ -119,19 +119,19 @@ genint_init(genint_t s, unsigned int n)
|
||||
s->n = n;
|
||||
s->data = ptr;
|
||||
s->max = (unsigned int) (alloc-1);
|
||||
s->mask0 = (index == 0) ? GENINT_FULL_MASK : ~((GENINT_ONE<<(GENINT_LIMBSIZE-index))-1);
|
||||
s->mask_master = (((GENINT_ONE << alloc) - 1) << (GENINT_LIMBSIZE-alloc)) >> GENINT_ABA_CPT;
|
||||
s->mask0 = (index == 0) ? M_GEN1NT_FULL_MASK : ~((M_GEN1NT_ONE<<(M_GEN1NT_LIMBSIZE-index))-1);
|
||||
s->mask_master = (((M_GEN1NT_ONE << alloc) - 1) << (M_GEN1NT_LIMBSIZE-alloc)) >> M_GEN1NT_ABA_CPT;
|
||||
atomic_init (&s->master, (genint_limb_ct)0);
|
||||
for(unsigned int i = 0; i < alloc; i++)
|
||||
atomic_init(&s->data[i], (genint_limb_ct)0);
|
||||
GENINT_CONTRACT(s);
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
}
|
||||
|
||||
/* Clear an integer generator (Destructor) */
|
||||
static inline void
|
||||
genint_clear(genint_t s)
|
||||
{
|
||||
GENINT_CONTRACT(s);
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
M_MEMORY_FREE(s->data);
|
||||
s->data = NULL;
|
||||
}
|
||||
@@ -140,7 +140,7 @@ genint_clear(genint_t s)
|
||||
static inline size_t
|
||||
genint_size(genint_t s)
|
||||
{
|
||||
GENINT_CONTRACT(s);
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
return s->n;
|
||||
}
|
||||
|
||||
@@ -149,17 +149,17 @@ genint_size(genint_t s)
|
||||
static inline unsigned int
|
||||
genint_pop(genint_t s)
|
||||
{
|
||||
GENINT_CONTRACT(s);
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
// First read master to see which limb is not full.
|
||||
genint_limb_ct master = atomic_load(&s->master);
|
||||
// While master is not full
|
||||
while ((master >> GENINT_ABA_CPT) != s->mask_master) {
|
||||
while ((master >> M_GEN1NT_ABA_CPT) != s->mask_master) {
|
||||
// Let's get the index i of the first not full limb according to master.
|
||||
unsigned int i = m_core_clz64(~master);
|
||||
M_ASSERT (i < GENINT_LIMBSIZE);
|
||||
M_ASSERT (i < M_GEN1NT_LIMBSIZE);
|
||||
// Let's compute the mask of this limb representing the limb as being full
|
||||
genint_limb_ct mask = s->mask0;
|
||||
mask = (i == s->max) ? mask : GENINT_FULL_MASK;
|
||||
mask = (i == s->max) ? mask : M_GEN1NT_FULL_MASK;
|
||||
unsigned int bit;
|
||||
// Let's load this limb,
|
||||
genint_limb_ct next, org = atomic_load(&s->data[i]);
|
||||
@@ -167,14 +167,14 @@ genint_pop(genint_t s)
|
||||
// If it is now full, we have been preempted by another.
|
||||
if (M_UNLIKELY (org == mask))
|
||||
goto next_element;
|
||||
M_ASSERT (org != GENINT_FULL_MASK);
|
||||
M_ASSERT (org != M_GEN1NT_FULL_MASK);
|
||||
// At least one bit is free in the limb. Find one.
|
||||
bit = GENINT_LIMBSIZE - 1 - m_core_clz64(~org);
|
||||
M_ASSERT (bit < GENINT_LIMBSIZE);
|
||||
M_ASSERT ((org & (GENINT_ONE<<bit)) == 0);
|
||||
M_ASSERT (i * GENINT_LIMBSIZE + GENINT_LIMBSIZE - 1 - bit < s->n);
|
||||
bit = M_GEN1NT_LIMBSIZE - 1 - m_core_clz64(~org);
|
||||
M_ASSERT (bit < M_GEN1NT_LIMBSIZE);
|
||||
M_ASSERT ((org & (M_GEN1NT_ONE<<bit)) == 0);
|
||||
M_ASSERT (i * M_GEN1NT_LIMBSIZE + M_GEN1NT_LIMBSIZE - 1 - bit < s->n);
|
||||
// Set the integer as being used.
|
||||
next = org | (GENINT_ONE << bit);
|
||||
next = org | (M_GEN1NT_ONE << bit);
|
||||
// Try to reserve the integer
|
||||
} while (!atomic_compare_exchange_weak (&s->data[i], &org, next));
|
||||
// We have reserved the integer.
|
||||
@@ -183,9 +183,9 @@ genint_pop(genint_t s)
|
||||
while (true) {
|
||||
genint_limb_ct newMaster;
|
||||
if (next == mask) {
|
||||
newMaster = GENINT_MASTER_SET(master, i);
|
||||
newMaster = M_GEN1NT_MASTER_SET(master, i);
|
||||
} else {
|
||||
newMaster = GENINT_MASTER_RESET(master, i);
|
||||
newMaster = M_GEN1NT_MASTER_RESET(master, i);
|
||||
}
|
||||
if (atomic_compare_exchange_weak (&s->master, &master, newMaster))
|
||||
break;
|
||||
@@ -194,13 +194,13 @@ genint_pop(genint_t s)
|
||||
}
|
||||
}
|
||||
// Return the new number
|
||||
GENINT_CONTRACT(s);
|
||||
return i * GENINT_LIMBSIZE + GENINT_LIMBSIZE - 1 - bit;
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
return i * M_GEN1NT_LIMBSIZE + M_GEN1NT_LIMBSIZE - 1 - bit;
|
||||
next_element:
|
||||
// Reload master
|
||||
master = atomic_load(&s->master);
|
||||
}
|
||||
GENINT_CONTRACT(s);
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
return GENINT_ERROR; // No more resource available
|
||||
}
|
||||
|
||||
@@ -209,31 +209,31 @@ genint_pop(genint_t s)
|
||||
static inline void
|
||||
genint_push(genint_t s, unsigned int n)
|
||||
{
|
||||
GENINT_CONTRACT(s);
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
M_ASSERT (n < s->n);
|
||||
const unsigned int i = n / GENINT_LIMBSIZE;
|
||||
const unsigned int bit = GENINT_LIMBSIZE - 1 - (n % GENINT_LIMBSIZE);
|
||||
const unsigned int i = n / M_GEN1NT_LIMBSIZE;
|
||||
const unsigned int bit = M_GEN1NT_LIMBSIZE - 1 - (n % M_GEN1NT_LIMBSIZE);
|
||||
genint_limb_ct master = atomic_load(&s->master);
|
||||
// Load the limb
|
||||
genint_limb_ct next, org = atomic_load(&s->data[i]);
|
||||
do {
|
||||
M_ASSERT ((org & (GENINT_ONE << bit)) != 0);
|
||||
M_ASSERT ((org & (M_GEN1NT_ONE << bit)) != 0);
|
||||
// Reset it
|
||||
next = org & (~(GENINT_ONE << bit));
|
||||
next = org & (~(M_GEN1NT_ONE << bit));
|
||||
// Try to unreserve it.
|
||||
} while (!atomic_compare_exchange_weak (&s->data[i], &org, next));
|
||||
// if the limb was marked as full by master
|
||||
genint_limb_ct mask = s->mask0;
|
||||
mask = (i == s->max) ? mask : GENINT_FULL_MASK;
|
||||
mask = (i == s->max) ? mask : M_GEN1NT_FULL_MASK;
|
||||
if (M_UNLIKELY (next != mask)) {
|
||||
// Let's compute the mask of this limb representing the limb as being full
|
||||
// Let's try to update master to say that this limb is not full
|
||||
while (true) {
|
||||
genint_limb_ct newMaster;
|
||||
if (next == mask) {
|
||||
newMaster = GENINT_MASTER_SET(master, i);
|
||||
newMaster = M_GEN1NT_MASTER_SET(master, i);
|
||||
} else {
|
||||
newMaster = GENINT_MASTER_RESET(master, i);
|
||||
newMaster = M_GEN1NT_MASTER_RESET(master, i);
|
||||
}
|
||||
if (atomic_compare_exchange_weak (&s->master, &master, newMaster))
|
||||
break;
|
||||
@@ -241,7 +241,7 @@ genint_push(genint_t s, unsigned int n)
|
||||
next = atomic_load(&s->data[i]);
|
||||
}
|
||||
}
|
||||
GENINT_CONTRACT(s);
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
}
|
||||
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
+74
-74
@@ -26,7 +26,7 @@
|
||||
#define MSTARLIB_I_LIST_H
|
||||
|
||||
#include "m-core.h"
|
||||
#include "m-list.h" // For LISTI_ITBASE_DEF
|
||||
#include "m-list.h" // For M_L1ST_ITBASE_DEF
|
||||
|
||||
/* Interface to add to a structure to enable intrusive doubly-linked support.
|
||||
name: name of the intrusive list.
|
||||
@@ -57,7 +57,7 @@
|
||||
ILIST_DEF_AS(name, name_t, it_t, type [, oplist_of_the_type]) */
|
||||
#define ILIST_DEF_AS(name, name_t, it_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
ILISTI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_IL1ST_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
|
||||
@@ -67,7 +67,7 @@
|
||||
USAGE:
|
||||
ILIST_OPLIST(name [, oplist_of_the_type]) */
|
||||
#define ILIST_OPLIST(...) \
|
||||
ILISTI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_IL1ST_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -81,18 +81,18 @@ typedef struct ilist_head_s {
|
||||
} ilist_head_ct;
|
||||
|
||||
/* Indirection call to allow expanding all arguments */
|
||||
#define ILISTI_OPLIST_P1(arg) ILISTI_OPLIST_P2 arg
|
||||
#define M_IL1ST_OPLIST_P1(arg) M_IL1ST_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define ILISTI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(ILISTI_OPLIST_P3, ILISTI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_IL1ST_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_IL1ST_OPLIST_P3, M_IL1ST_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define ILISTI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_IL1ST_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_ILIST_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* Define the oplist of an ilist of type */
|
||||
#define ILISTI_OPLIST_P3(name, oplist) \
|
||||
#define M_IL1ST_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _init)), \
|
||||
CLEAR(M_C(name, _clear)), \
|
||||
INIT_MOVE(M_C(name, _init_move)), \
|
||||
@@ -122,7 +122,7 @@ typedef struct ilist_head_s {
|
||||
)
|
||||
|
||||
/* Contract respected by all intrusive lists */
|
||||
#define ILISTI_CONTRACT(name, list) do { \
|
||||
#define M_IL1ST_CONTRACT(name, list) do { \
|
||||
M_ASSERT(list != NULL); \
|
||||
M_ASSERT(list->name.prev != NULL); \
|
||||
M_ASSERT(list->name.next != NULL); \
|
||||
@@ -131,7 +131,7 @@ typedef struct ilist_head_s {
|
||||
M_ASSERT(!(list->name.prev == &list->name) || list->name.prev == list->name.next); \
|
||||
} while (0)
|
||||
|
||||
#define ILISTI_NODE_CONTRACT(node) do { \
|
||||
#define M_IL1ST_NODE_CONTRACT(node) do { \
|
||||
M_ASSERT((node) != NULL); \
|
||||
M_ASSERT((node)->prev != NULL); \
|
||||
M_ASSERT((node)->next != NULL); \
|
||||
@@ -140,14 +140,14 @@ typedef struct ilist_head_s {
|
||||
} while (0)
|
||||
|
||||
/* Indirection call to allow expanding all arguments (TBC) */
|
||||
#define ILISTI_DEF_P1(arg) ILISTI_DEF_P2 arg
|
||||
#define M_IL1ST_DEF_P1(arg) M_IL1ST_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define ILISTI_DEF_P2(name, type, oplist, list_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(ILISTI_DEF_P3, ILISTI_DEF_FAILURE)(name, type, oplist, list_t, it_t)
|
||||
#define M_IL1ST_DEF_P2(name, type, oplist, list_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(M_IL1ST_DEF_P3, M_IL1ST_DEF_FAILURE)(name, type, oplist, list_t, it_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define ILISTI_DEF_FAILURE(name, type, oplist, list_t, it_t) \
|
||||
#define M_IL1ST_DEF_FAILURE(name, type, oplist, list_t, it_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(ILIST_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
/* Definition of the type and function for an intrusive doubly-linked list.
|
||||
@@ -158,7 +158,7 @@ typedef struct ilist_head_s {
|
||||
list_t: type of the intrusive list (name##_t)
|
||||
it_t: iterator of the intrusive list (name##_it_t)
|
||||
*/
|
||||
#define ILISTI_DEF_P3(name, type, oplist, list_t, it_t) \
|
||||
#define M_IL1ST_DEF_P3(name, type, oplist, list_t, it_t) \
|
||||
\
|
||||
/* Define the list as a structure containing pointers \
|
||||
* to the front & back nodes */ \
|
||||
@@ -191,13 +191,13 @@ typedef struct ilist_head_s {
|
||||
M_ASSERT (list != NULL); \
|
||||
list->name.next = &list->name; \
|
||||
list->name.prev = &list->name; \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clean)(list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
for(struct ilist_head_s *it = list->name.next, *next ; \
|
||||
it != &list->name; it = next) { \
|
||||
/* Cannot check node contract as previous node may be deleted */ \
|
||||
@@ -213,7 +213,7 @@ typedef struct ilist_head_s {
|
||||
/* Nothing remains in the list anymore */ \
|
||||
list->name.next = &list->name; \
|
||||
list->name.prev = &list->name; \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -229,7 +229,7 @@ typedef struct ilist_head_s {
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(const list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
return list->name.next == &list->name; \
|
||||
} \
|
||||
\
|
||||
@@ -237,7 +237,7 @@ typedef struct ilist_head_s {
|
||||
static inline void \
|
||||
M_C(name, _init_move)(list_t list, list_t ref) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, ref); \
|
||||
M_IL1ST_CONTRACT(name, ref); \
|
||||
M_ASSERT (list != ref); \
|
||||
M_C(name,_init)(list); \
|
||||
if (!M_C(name,_empty_p)(ref)) { \
|
||||
@@ -248,7 +248,7 @@ typedef struct ilist_head_s {
|
||||
} \
|
||||
ref->name.next = NULL; \
|
||||
ref->name.prev = NULL; \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -261,12 +261,12 @@ typedef struct ilist_head_s {
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
size_t s = 0; \
|
||||
/* Scan the full list to count the number of elements */ \
|
||||
for(const struct ilist_head_s *it = list->name.next ; \
|
||||
it != &list->name; it = it->next) { \
|
||||
ILISTI_NODE_CONTRACT(it); \
|
||||
M_IL1ST_NODE_CONTRACT(it); \
|
||||
s++; \
|
||||
} \
|
||||
return s; \
|
||||
@@ -275,27 +275,27 @@ typedef struct ilist_head_s {
|
||||
static inline void \
|
||||
M_C(name, _push_back)(list_t list, type *obj) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT (obj != NULL); \
|
||||
struct ilist_head_s *prev = list->name.prev; \
|
||||
list->name.prev = &obj->name; \
|
||||
obj->name.prev = prev; \
|
||||
obj->name.next = &list->name; \
|
||||
prev->next = &obj->name; \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _push_front)(list_t list, type *obj) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT (obj != NULL); \
|
||||
struct ilist_head_s *next = list->name.next; \
|
||||
list->name.next = &obj->name; \
|
||||
obj->name.next = next; \
|
||||
obj->name.prev = &list->name; \
|
||||
next->prev = &obj->name; \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -303,7 +303,7 @@ typedef struct ilist_head_s {
|
||||
{ \
|
||||
M_ASSERT (obj_pos != NULL && obj != NULL); \
|
||||
/* We don't have the list, so we have no contract at list level */ \
|
||||
ILISTI_NODE_CONTRACT(&obj_pos->name); \
|
||||
M_IL1ST_NODE_CONTRACT(&obj_pos->name); \
|
||||
struct ilist_head_s *next = obj_pos->name.next; \
|
||||
obj_pos->name.next = &obj->name; \
|
||||
obj->name.next = next; \
|
||||
@@ -325,7 +325,7 @@ typedef struct ilist_head_s {
|
||||
{ \
|
||||
M_ASSERT (obj != NULL); \
|
||||
/* We don't have the list, so we have no contract at list level */ \
|
||||
ILISTI_NODE_CONTRACT(&obj->name); \
|
||||
M_IL1ST_NODE_CONTRACT(&obj->name); \
|
||||
struct ilist_head_s *next = obj->name.next; \
|
||||
struct ilist_head_s *prev = obj->name.prev; \
|
||||
next->prev = prev; \
|
||||
@@ -338,7 +338,7 @@ typedef struct ilist_head_s {
|
||||
static inline type * \
|
||||
M_C(name, _back)(const list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT(!M_C(name, _empty_p)(list)); \
|
||||
return M_TYPE_FROM_FIELD(type, list->name.prev, \
|
||||
struct ilist_head_s, name); \
|
||||
@@ -347,7 +347,7 @@ typedef struct ilist_head_s {
|
||||
static inline type * \
|
||||
M_C(name, _front)(const list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT(!M_C(name, _empty_p)(list)); \
|
||||
return M_TYPE_FROM_FIELD(type, list->name.next, \
|
||||
struct ilist_head_s, name); \
|
||||
@@ -356,9 +356,9 @@ typedef struct ilist_head_s {
|
||||
static inline type * \
|
||||
M_C(name, _next_obj)(const list_t list, type const *obj) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT (obj != NULL); \
|
||||
ILISTI_NODE_CONTRACT(&obj->name); \
|
||||
M_IL1ST_NODE_CONTRACT(&obj->name); \
|
||||
return obj->name.next == &list->name ? NULL : \
|
||||
M_TYPE_FROM_FIELD(type, obj->name.next, \
|
||||
struct ilist_head_s, name); \
|
||||
@@ -367,9 +367,9 @@ typedef struct ilist_head_s {
|
||||
static inline type * \
|
||||
M_C(name, _previous_obj)(const list_t list, type const *obj) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT (obj != NULL); \
|
||||
ILISTI_NODE_CONTRACT(&obj->name); \
|
||||
M_IL1ST_NODE_CONTRACT(&obj->name); \
|
||||
return obj->name.prev == &list->name ? NULL : \
|
||||
M_TYPE_FROM_FIELD(type, obj->name.prev, \
|
||||
struct ilist_head_s, name); \
|
||||
@@ -378,13 +378,13 @@ typedef struct ilist_head_s {
|
||||
static inline void \
|
||||
M_C(name, _it)(it_t it, const list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->head = list->name.next->prev; \
|
||||
it->current = list->name.next; \
|
||||
it->next = list->name.next->next; \
|
||||
it->previous = it->head; \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -395,19 +395,19 @@ typedef struct ilist_head_s {
|
||||
it->current = cit->current; \
|
||||
it->next = cit->next; \
|
||||
it->previous = cit->previous; \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _it_last)(it_t it, list_t const list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->head = list->name.next->prev; \
|
||||
it->current = list->name.prev; \
|
||||
it->next = it->head; \
|
||||
it->previous = list->name.prev->prev; \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -418,14 +418,14 @@ typedef struct ilist_head_s {
|
||||
it->current = it->head; \
|
||||
it->next = list->name.next; \
|
||||
it->previous = list->name.prev; \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _end_p)(const it_t it) \
|
||||
{ \
|
||||
M_ASSERT (it != NULL); \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
return it->current == it->head; \
|
||||
} \
|
||||
\
|
||||
@@ -433,7 +433,7 @@ typedef struct ilist_head_s {
|
||||
M_C(name, _last_p)(const it_t it) \
|
||||
{ \
|
||||
M_ASSERT (it != NULL); \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
return it->next == it->head || it->current == it->head; \
|
||||
} \
|
||||
\
|
||||
@@ -449,7 +449,7 @@ typedef struct ilist_head_s {
|
||||
it->next = it->current->next; \
|
||||
it->previous = it->current->prev; \
|
||||
M_ASSERT (it->next != NULL && it->previous != NULL); \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -464,7 +464,7 @@ typedef struct ilist_head_s {
|
||||
it->next = it->current->next; \
|
||||
it->previous = it->current->prev; \
|
||||
M_ASSERT (it->next != NULL && it->previous != NULL); \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
@@ -479,7 +479,7 @@ typedef struct ilist_head_s {
|
||||
M_C(name, _ref)(const it_t it) \
|
||||
{ \
|
||||
M_ASSERT (it != NULL && it->current != NULL); \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
/* check if 'it' was not deleted */ \
|
||||
M_ASSERT (it->current->next == it->next); \
|
||||
M_ASSERT (it->current->prev == it->previous); \
|
||||
@@ -498,8 +498,8 @@ typedef struct ilist_head_s {
|
||||
static inline void \
|
||||
M_C(name, _remove)(list_t list, it_t it) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
(void)list; /* list param is not used */ \
|
||||
type *obj = M_TYPE_FROM_FIELD(type, it->current, \
|
||||
struct ilist_head_s, name); \
|
||||
@@ -513,8 +513,8 @@ typedef struct ilist_head_s {
|
||||
static inline void \
|
||||
M_C(name, _insert)(list_t list, it_t it, type x) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
type *p = M_CALL_NEW(oplist, type); \
|
||||
if (M_UNLIKELY (p == NULL)) { \
|
||||
M_MEMORY_FULL (sizeof (type)); \
|
||||
@@ -525,14 +525,14 @@ typedef struct ilist_head_s {
|
||||
M_C(name, _push_after)(obj, p); \
|
||||
it->current = p; \
|
||||
(void) list; \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
} \
|
||||
, /* NEW not defined */) \
|
||||
\
|
||||
static inline type * \
|
||||
M_C(name, _pop_back)(list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT (!M_C(name, _empty_p)(list)); \
|
||||
type *obj = M_C(name, _back)(list); \
|
||||
list->name.prev = list->name.prev->prev; \
|
||||
@@ -543,7 +543,7 @@ typedef struct ilist_head_s {
|
||||
static inline type * \
|
||||
M_C(name, _pop_front)(list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
M_ASSERT (!M_C(name, _empty_p)(list)); \
|
||||
type *obj = M_C(name, _front)(list); \
|
||||
list->name.next = list->name.next->next; \
|
||||
@@ -554,8 +554,8 @@ typedef struct ilist_head_s {
|
||||
static inline void \
|
||||
M_C(name, _splice)(list_t list1, list_t list2) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list1); \
|
||||
ILISTI_CONTRACT(name, list2); \
|
||||
M_IL1ST_CONTRACT(name, list1); \
|
||||
M_IL1ST_CONTRACT(name, list2); \
|
||||
struct ilist_head_s *midle1 = list1->name.prev; \
|
||||
struct ilist_head_s *midle2 = list2->name.next; \
|
||||
midle1->next = midle2; \
|
||||
@@ -564,32 +564,32 @@ typedef struct ilist_head_s {
|
||||
list2->name.prev->next = &list1->name; \
|
||||
list2->name.next = &list2->name; \
|
||||
list2->name.prev = &list2->name; \
|
||||
ILISTI_CONTRACT(name, list1); \
|
||||
ILISTI_CONTRACT(name, list2); \
|
||||
M_IL1ST_CONTRACT(name, list1); \
|
||||
M_IL1ST_CONTRACT(name, list2); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _splice_back)(list_t nv, list_t ov, it_t it) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, nv); \
|
||||
ILISTI_CONTRACT(name, ov); \
|
||||
ILISTI_NODE_CONTRACT(it->current); \
|
||||
M_IL1ST_CONTRACT(name, nv); \
|
||||
M_IL1ST_CONTRACT(name, ov); \
|
||||
M_IL1ST_NODE_CONTRACT(it->current); \
|
||||
M_ASSERT (it != NULL); \
|
||||
(void) ov; \
|
||||
type *obj = M_C(name, _ref)(it); \
|
||||
M_C(name, _unlink)(obj); \
|
||||
M_C(name, _push_back)(nv, obj); \
|
||||
M_C(name, _next)(it); \
|
||||
ILISTI_CONTRACT(name, nv); \
|
||||
ILISTI_CONTRACT(name, ov); \
|
||||
M_IL1ST_CONTRACT(name, nv); \
|
||||
M_IL1ST_CONTRACT(name, ov); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _splice_at)(list_t nlist, it_t npos, \
|
||||
list_t olist, it_t opos) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, nlist); \
|
||||
ILISTI_CONTRACT(name, olist); \
|
||||
M_IL1ST_CONTRACT(name, nlist); \
|
||||
M_IL1ST_CONTRACT(name, olist); \
|
||||
M_ASSERT (npos != NULL && opos != NULL); \
|
||||
M_ASSERT (!M_C(name, _end_p)(opos)); \
|
||||
/* npos may be end */ \
|
||||
@@ -610,15 +610,15 @@ typedef struct ilist_head_s {
|
||||
npos->previous = ref; \
|
||||
npos->current = &obj->name; \
|
||||
npos->next = next; \
|
||||
ILISTI_CONTRACT(name, nlist); \
|
||||
ILISTI_CONTRACT(name, olist); \
|
||||
M_IL1ST_CONTRACT(name, nlist); \
|
||||
M_IL1ST_CONTRACT(name, olist); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _swap)(list_t d, list_t e) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, d); \
|
||||
ILISTI_CONTRACT(name, e); \
|
||||
M_IL1ST_CONTRACT(name, d); \
|
||||
M_IL1ST_CONTRACT(name, e); \
|
||||
struct ilist_head_s *d_item = d->name.next; \
|
||||
struct ilist_head_s *e_item = e->name.next; \
|
||||
d->name.next = e_item == &e->name ? &d->name : e_item; \
|
||||
@@ -631,14 +631,14 @@ typedef struct ilist_head_s {
|
||||
d->name.prev->next = &d->name; \
|
||||
e->name.next->prev = &e->name; \
|
||||
e->name.prev->next = &e->name; \
|
||||
ILISTI_CONTRACT(name, d); \
|
||||
ILISTI_CONTRACT(name, e); \
|
||||
M_IL1ST_CONTRACT(name, d); \
|
||||
M_IL1ST_CONTRACT(name, e); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _reverse)(list_t list) \
|
||||
{ \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
struct ilist_head_s *next, *it; \
|
||||
for(it = list->name.next ; it != &list->name; it = next) { \
|
||||
next = it->next; \
|
||||
@@ -648,11 +648,11 @@ typedef struct ilist_head_s {
|
||||
next = it->next; \
|
||||
it->next = it->prev; \
|
||||
it->prev = next; \
|
||||
ILISTI_CONTRACT(name, list); \
|
||||
M_IL1ST_CONTRACT(name, list); \
|
||||
} \
|
||||
\
|
||||
/* Used of macro from m-list */ \
|
||||
LISTI_ITBASE_DEF(name, type, oplist, list_t, it_t)
|
||||
/* Used of internal macro from m-list */ \
|
||||
M_L1ST_ITBASE_DEF(name, type, oplist, list_t, it_t)
|
||||
|
||||
|
||||
#endif
|
||||
+12
-12
@@ -33,7 +33,7 @@ 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__) \
|
||||
M_ISHAR3D_PTR_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -66,7 +66,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
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__) \
|
||||
M_ISHAR3D_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
|
||||
@@ -75,18 +75,18 @@ M_BEGIN_PROTECTED_CODE
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
// Deferred evaluation
|
||||
#define ISHAREDI_PTR_OPLIST_P1(arg) ISHAREDI_PTR_OPLIST_P2 arg
|
||||
#define M_ISHAR3D_PTR_OPLIST_P1(arg) M_ISHAR3D_PTR_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define ISHAREDI_PTR_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(ISHAREDI_PTR_OPLIST_P3, ISHAREDI_PTR_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_ISHAR3D_PTR_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_ISHAR3D_PTR_OPLIST_P3, M_ISHAR3D_PTR_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define ISHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_ISHAR3D_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) ( \
|
||||
#define M_ISHAR3D_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), \
|
||||
@@ -101,17 +101,17 @@ M_BEGIN_PROTECTED_CODE
|
||||
)
|
||||
|
||||
// Deferred evaluatioin
|
||||
#define ISHAREDI_PTR_DEF_P1(arg) ISHAREDI_PTR_DEF_P2 arg
|
||||
#define M_ISHAR3D_PTR_DEF_P1(arg) M_ISHAR3D_PTR_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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)
|
||||
#define M_ISHAR3D_PTR_DEF_P2(name, type, oplist, shared_t) \
|
||||
M_IF_OPLIST(oplist)(M_ISHAR3D_PTR_DEF_P3, M_ISHAR3D_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 M_ISHAR3D_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) \
|
||||
#define M_ISHAR3D_PTR_DEF_P3(name, type, oplist, shared_t) \
|
||||
\
|
||||
/* The shared pointer is only a pointer to the type */ \
|
||||
typedef type *shared_t; \
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
USAGE: LIST_DEF_AS(name, name_t, it_t, type [, oplist_of_the_type]) */
|
||||
#define LIST_DEF_AS(name, name_t, it_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
LISTI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_L1ST_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
|
||||
@@ -55,7 +55,7 @@
|
||||
USAGE: LIST_DUAL_PUSH_DEF(name, type [, oplist_of_the_type]) */
|
||||
#define LIST_DUAL_PUSH_DEF_AS(name, name_t, it_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
LISTI_DUAL_PUSH_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_L1ST_DUAL_PUSH_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
|
||||
@@ -64,7 +64,7 @@
|
||||
/* Define the oplist of a list of the given type.
|
||||
USAGE: LIST_OPLIST(name [, oplist_of_the_type]) */
|
||||
#define LIST_OPLIST(...) \
|
||||
LISTI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_L1ST_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST ), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -73,18 +73,18 @@
|
||||
|
||||
/* Deferred evaluation for the oplist definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define LISTI_OPLIST_P1(arg) LISTI_OPLIST_P2 arg
|
||||
#define M_L1ST_OPLIST_P1(arg) M_L1ST_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define LISTI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(LISTI_OPLIST_P3, LISTI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_L1ST_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_L1ST_OPLIST_P3, M_L1ST_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define LISTI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_L1ST_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_LIST_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* OPLIST definition of a list and list_dual_push */
|
||||
#define LISTI_OPLIST_P3(name, oplist) \
|
||||
#define M_L1ST_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _init)), \
|
||||
INIT_SET(M_C(name, _init_set)), \
|
||||
INIT_WITH(API_1(M_INIT_VAI)), \
|
||||
@@ -132,35 +132,35 @@
|
||||
|
||||
/* Deferred evaluation for the list definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define LISTI_DEF_P1(arg) LISTI_DEF_P2 arg
|
||||
#define M_L1ST_DEF_P1(arg) M_L1ST_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define LISTI_DEF_P2(name, type, oplist, list_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(LISTI_DEF_P3, LISTI_DEF_FAILURE)(name, type, oplist, list_t, it_t)
|
||||
#define M_L1ST_DEF_P2(name, type, oplist, list_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(M_L1ST_DEF_P3, M_L1ST_DEF_FAILURE)(name, type, oplist, list_t, it_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define LISTI_DEF_FAILURE(name, type, oplist, list_t, it_t) \
|
||||
#define M_L1ST_DEF_FAILURE(name, type, oplist, list_t, it_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(LIST_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
/* Define allocation functions. If MEMPOOL, we need to define it */
|
||||
#define LISTI_MEMPOOL_DEF(name, type, oplist, list_t, list_it_t) \
|
||||
#define M_L1ST_MEMPOOL_DEF(name, type, oplist, list_t, list_it_t) \
|
||||
M_IF_METHOD(MEMPOOL, oplist)( \
|
||||
\
|
||||
MEMPOOL_DEF(M_C(name, _mempool), struct M_C(name, _s)) \
|
||||
M_GET_MEMPOOL_LINKAGE oplist M_C(name, _mempool_t) M_GET_MEMPOOL oplist; \
|
||||
static inline struct M_C(name, _s) *M_C(name, _int_new)(void) { \
|
||||
static inline struct M_C(name, _s) *M_C3(m_l1st_,name,_new)(void) { \
|
||||
return M_C(name, _mempool_alloc)(M_GET_MEMPOOL oplist); \
|
||||
} \
|
||||
static inline void M_C(name,_int_del)(struct M_C(name, _s) *ptr) { \
|
||||
static inline void M_C3(m_l1st_,name,_del)(struct M_C(name, _s) *ptr) { \
|
||||
M_C(name, _mempool_free)(M_GET_MEMPOOL oplist, ptr); \
|
||||
} \
|
||||
\
|
||||
, /* No mempool allocation */ \
|
||||
\
|
||||
static inline struct M_C(name, _s) *M_C(name, _int_new)(void) { \
|
||||
static inline struct M_C(name, _s) *M_C3(m_l1st_,name,_new)(void) { \
|
||||
return M_CALL_NEW(oplist, struct M_C(name, _s)); \
|
||||
} \
|
||||
static inline void M_C(name,_int_del)(struct M_C(name, _s) *ptr) { \
|
||||
static inline void M_C3(m_l1st_,name,_del)(struct M_C(name, _s) *ptr) { \
|
||||
M_CALL_DEL(oplist, ptr); \
|
||||
} \
|
||||
) \
|
||||
@@ -174,7 +174,7 @@
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
- node_t: alias for M_C(name, _node_t) [ node ]
|
||||
*/
|
||||
#define LISTI_DEF_P3(name, type, oplist, list_t, it_t) \
|
||||
#define M_L1ST_DEF_P3(name, type, oplist, list_t, it_t) \
|
||||
\
|
||||
/* Define the node of a list, and the list as a pointer to a node */ \
|
||||
typedef struct M_C(name, _s) { \
|
||||
@@ -197,14 +197,14 @@
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
LISTI_MEMPOOL_DEF(name, type, oplist, list_t, it_t) \
|
||||
LISTI_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
LISTI_ITBASE_DEF(name, type, oplist, list_t, it_t)
|
||||
M_L1ST_MEMPOOL_DEF(name, type, oplist, list_t, it_t) \
|
||||
M_L1ST_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
M_L1ST_ITBASE_DEF(name, type, oplist, list_t, it_t)
|
||||
|
||||
|
||||
/* Define the internal contract of a list
|
||||
(there is nothing worthy to be checked) */
|
||||
#define LISTI_CONTRACT(v) do { \
|
||||
#define M_L1ST_CONTRACT(v) do { \
|
||||
M_ASSERT (v != NULL); \
|
||||
} while (0)
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
- list_t: alias for type of the container
|
||||
- it_t: alias for iterator of the container
|
||||
*/
|
||||
#define LISTI_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
#define M_L1ST_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init)(list_t v) \
|
||||
@@ -228,16 +228,16 @@
|
||||
static inline void \
|
||||
M_C(name, _clean)(list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
struct M_C(name, _s) *it = *v; \
|
||||
*v = NULL; \
|
||||
while (it != NULL) { \
|
||||
struct M_C(name, _s) *next = it->next; \
|
||||
M_CALL_CLEAR(oplist, it->data); \
|
||||
M_C(name,_int_del)(it); \
|
||||
M_C3(m_l1st_,name,_del)(it); \
|
||||
it = next; \
|
||||
} \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -249,7 +249,7 @@
|
||||
static inline type const * \
|
||||
M_C(name, _back)(const list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
M_ASSERT(*v != NULL); \
|
||||
return M_CONST_CAST(type, &((*v)->data)); \
|
||||
} \
|
||||
@@ -257,9 +257,9 @@
|
||||
static inline type * \
|
||||
M_C(name, _push_raw)(list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
struct M_C(name, _s) *next; \
|
||||
next = M_C(name, _int_new)(); \
|
||||
next = M_C3(m_l1st_,name,_new)(); \
|
||||
if (M_UNLIKELY (next == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof (struct M_C(name, _s))); \
|
||||
return NULL; \
|
||||
@@ -267,7 +267,7 @@
|
||||
type *ret = &next->data; \
|
||||
next->next = *v; \
|
||||
*v = next; \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
@@ -295,7 +295,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_back)(type *data, list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
M_ASSERT(*v != NULL); \
|
||||
if (data != NULL) { \
|
||||
M_DO_MOVE (oplist, *data, (*v)->data); \
|
||||
@@ -304,8 +304,8 @@
|
||||
} \
|
||||
struct M_C(name, _s) *tofree = *v; \
|
||||
*v = (*v)->next; \
|
||||
M_C(name,_int_del)(tofree); \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_C3(m_l1st_,name,_del)(tofree); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -321,38 +321,38 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_move)(type *data, list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
M_ASSERT(*v != NULL && data != NULL); \
|
||||
M_DO_INIT_MOVE (oplist, *data, (*v)->data); \
|
||||
struct M_C(name, _s) *tofree = *v; \
|
||||
*v = (*v)->next; \
|
||||
M_C(name,_int_del)(tofree); \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_C3(m_l1st_,name,_del)(tofree); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(const list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
return *v == NULL; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _swap)(list_t l, list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(l); \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(l); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
struct M_C(name, _s) *tmp = *l; \
|
||||
*l = *v; \
|
||||
*v = tmp; \
|
||||
LISTI_CONTRACT(l); \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(l); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _it)(it_t it, const list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->current = *v; \
|
||||
it->previous = NULL; \
|
||||
@@ -369,7 +369,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it_end)(it_t it1, const list_t v) \
|
||||
{ \
|
||||
LISTI_CONTRACT(v); \
|
||||
M_L1ST_CONTRACT(v); \
|
||||
M_ASSERT (it1 != NULL); \
|
||||
(void)v; /* unused */ \
|
||||
it1->current = NULL; \
|
||||
@@ -422,7 +422,7 @@
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const list_t list) \
|
||||
{ \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
size_t size = 0; \
|
||||
struct M_C(name, _s) *it = *list; \
|
||||
while (it != NULL) { \
|
||||
@@ -435,7 +435,7 @@
|
||||
static inline bool \
|
||||
M_C(name, _sublist_p)(const list_t list, const it_t itsub) \
|
||||
{ \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
M_ASSERT (itsub != NULL); \
|
||||
struct M_C(name, _s) *it = *list; \
|
||||
while (it != NULL) { \
|
||||
@@ -449,7 +449,7 @@
|
||||
static inline type * \
|
||||
M_C(name, _get)(const list_t list, size_t i) \
|
||||
{ \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
struct M_C(name, _s) *it = *list; \
|
||||
/* FIXME: How to avoid the double iteration over the list? */ \
|
||||
size_t len = M_C(name,_size)(list); \
|
||||
@@ -473,10 +473,10 @@
|
||||
M_C(name, _insert)(list_t list, it_t insertion_point, \
|
||||
type const x) \
|
||||
{ \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
M_ASSERT (insertion_point != NULL); \
|
||||
M_ASSERT(M_C(name, _sublist_p)(list, insertion_point)); \
|
||||
struct M_C(name, _s) *next = M_C(name, _int_new)(); \
|
||||
struct M_C(name, _s) *next = M_C3(m_l1st_,name,_new)(); \
|
||||
if (M_UNLIKELY (next == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof (struct M_C(name, _s))); \
|
||||
return; \
|
||||
@@ -492,13 +492,13 @@
|
||||
} \
|
||||
/* Update insertion_point to this element */ \
|
||||
insertion_point->current = next; \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _remove)(list_t list, it_t removing_point) \
|
||||
{ \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
M_ASSERT (removing_point != NULL); \
|
||||
M_ASSERT (removing_point->current != NULL); \
|
||||
M_ASSERT(M_C(name, _sublist_p)(list, removing_point)); \
|
||||
@@ -509,21 +509,21 @@
|
||||
removing_point->previous->next = next; \
|
||||
} \
|
||||
M_CALL_CLEAR(oplist, removing_point->current->data); \
|
||||
M_C(name,_int_del) (removing_point->current); \
|
||||
M_C3(m_l1st_,name,_del) (removing_point->current); \
|
||||
removing_point->current = next; \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init_set)(list_t list, const list_t org) \
|
||||
{ \
|
||||
LISTI_CONTRACT(org); \
|
||||
M_L1ST_CONTRACT(org); \
|
||||
struct M_C(name, _s) *next, *it_org; \
|
||||
struct M_C(name, _s) **update_list; \
|
||||
update_list = list; \
|
||||
it_org = *org; \
|
||||
while (it_org != NULL) { \
|
||||
next = M_C(name, _int_new)(); \
|
||||
next = M_C3(m_l1st_,name,_new)(); \
|
||||
*update_list = next; \
|
||||
if (M_UNLIKELY (next == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof (struct M_C(name, _s))); \
|
||||
@@ -535,7 +535,7 @@
|
||||
it_org = it_org->next; \
|
||||
} \
|
||||
*update_list = NULL; \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -549,7 +549,7 @@
|
||||
static inline void \
|
||||
M_C(name, _init_move)(list_t list, list_t org) \
|
||||
{ \
|
||||
LISTI_CONTRACT(org); \
|
||||
M_L1ST_CONTRACT(org); \
|
||||
M_ASSERT (list != NULL && list != org); \
|
||||
*list = *org; \
|
||||
*org = NULL; /* safer */ \
|
||||
@@ -566,8 +566,8 @@
|
||||
static inline void \
|
||||
M_C(name, _splice_back)(list_t nv, list_t ov, it_t it) \
|
||||
{ \
|
||||
LISTI_CONTRACT(nv); \
|
||||
LISTI_CONTRACT(ov); \
|
||||
M_L1ST_CONTRACT(nv); \
|
||||
M_L1ST_CONTRACT(ov); \
|
||||
M_ASSERT (it != NULL); \
|
||||
M_ASSERT (it->current != NULL); \
|
||||
M_ASSERT (M_C(name, _sublist_p)(ov, it)); \
|
||||
@@ -591,8 +591,8 @@
|
||||
M_C(name, _splice_at)(list_t nlist, it_t npos, \
|
||||
list_t olist, it_t opos) \
|
||||
{ \
|
||||
LISTI_CONTRACT(nlist); \
|
||||
LISTI_CONTRACT(olist); \
|
||||
M_L1ST_CONTRACT(nlist); \
|
||||
M_L1ST_CONTRACT(olist); \
|
||||
M_ASSERT (npos != NULL); \
|
||||
M_ASSERT (opos != NULL); \
|
||||
M_ASSERT (M_C(name, _sublist_p)(nlist, npos)); \
|
||||
@@ -619,15 +619,15 @@
|
||||
/* Update 'npos' to point to the new current element */ \
|
||||
npos->previous = npos->current; \
|
||||
npos->current = current; \
|
||||
LISTI_CONTRACT(nlist); \
|
||||
LISTI_CONTRACT(olist); \
|
||||
M_L1ST_CONTRACT(nlist); \
|
||||
M_L1ST_CONTRACT(olist); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _splice)(list_t list1, list_t list2) \
|
||||
{ \
|
||||
LISTI_CONTRACT(list1); \
|
||||
LISTI_CONTRACT(list2); \
|
||||
M_L1ST_CONTRACT(list1); \
|
||||
M_L1ST_CONTRACT(list2); \
|
||||
M_ASSERT (list1 != list2); \
|
||||
struct M_C(name, _s) **update_list = list1; \
|
||||
struct M_C(name, _s) *it = *list1; \
|
||||
@@ -642,7 +642,7 @@
|
||||
static inline void \
|
||||
M_C(name, _reverse)(list_t list) \
|
||||
{ \
|
||||
LISTI_CONTRACT(list); \
|
||||
M_L1ST_CONTRACT(list); \
|
||||
struct M_C(name, _s) *previous = NULL, *it = *list, *next; \
|
||||
while (it != NULL) { \
|
||||
next = it->next; \
|
||||
@@ -664,7 +664,7 @@
|
||||
- list_t: alias for M_C(name, _t) [ type of the container ]
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
*/
|
||||
#define LISTI_ITBASE_DEF(name, type, oplist, list_t, it_t) \
|
||||
#define M_L1ST_ITBASE_DEF(name, type, oplist, list_t, it_t) \
|
||||
\
|
||||
M_IF_METHOD(GET_STR, oplist)( \
|
||||
static inline void \
|
||||
@@ -858,14 +858,14 @@
|
||||
|
||||
/* Deferred evaluation for the dual-push list definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define LISTI_DUAL_PUSH_DEF_P1(arg) LISTI_DUAL_PUSH_DEF_P2 arg
|
||||
#define M_L1ST_DUAL_PUSH_DEF_P1(arg) M_L1ST_DUAL_PUSH_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define LISTI_DUAL_PUSH_DEF_P2(name, type, oplist, list_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(LISTI_DUAL_PUSH_DEF_P3, LISTI_DUAL_PUSH_DEF_FAILURE)(name, type, oplist, list_t, it_t)
|
||||
#define M_L1ST_DUAL_PUSH_DEF_P2(name, type, oplist, list_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(M_L1ST_DUAL_PUSH_DEF_P3, M_L1ST_DUAL_PUSH_DEF_FAILURE)(name, type, oplist, list_t, it_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define LISTI_DUAL_PUSH_DEF_FAILURE(name, type, oplist, list_t, it_t) \
|
||||
#define M_L1ST_DUAL_PUSH_DEF_FAILURE(name, type, oplist, list_t, it_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(LIST_DUAL_PUSH_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
/* Internal dual-push list definition
|
||||
@@ -875,7 +875,7 @@
|
||||
- list_t: alias for M_C(name, _t) [ type of the container ]
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
*/
|
||||
#define LISTI_DUAL_PUSH_DEF_P3(name, type, oplist, list_t, it_t) \
|
||||
#define M_L1ST_DUAL_PUSH_DEF_P3(name, type, oplist, list_t, it_t) \
|
||||
\
|
||||
/* Node of a list (it is liked the singly linked list) */ \
|
||||
struct M_C(name, _s) { \
|
||||
@@ -908,13 +908,13 @@
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
LISTI_MEMPOOL_DEF(name, type, oplist, list_t, it_t) \
|
||||
LISTI_DUAL_PUSH_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
LISTI_ITBASE_DEF(name, type, oplist, list_t, it_t)
|
||||
M_L1ST_MEMPOOL_DEF(name, type, oplist, list_t, it_t) \
|
||||
M_L1ST_DUAL_PUSH_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
M_L1ST_ITBASE_DEF(name, type, oplist, list_t, it_t)
|
||||
|
||||
|
||||
/* Define the internal contract of an dual-push list */
|
||||
#define LISTI_DUAL_PUSH_CONTRACT(l) do { \
|
||||
#define M_L1ST_DUAL_PUSH_CONTRACT(l) do { \
|
||||
M_ASSERT (l != NULL); \
|
||||
M_ASSERT ( (l->back == NULL && l->front == NULL) \
|
||||
|| (l->back != NULL && l->front != NULL)); \
|
||||
@@ -927,7 +927,7 @@
|
||||
- list_t: alias for type of the container
|
||||
- it_t: alias for iterator of the container
|
||||
*/
|
||||
#define LISTI_DUAL_PUSH_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
#define M_L1ST_DUAL_PUSH_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init)(list_t v) \
|
||||
@@ -935,23 +935,23 @@
|
||||
M_ASSERT( v != NULL); \
|
||||
v->front = NULL; \
|
||||
v->back = NULL; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clean)(list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
struct M_C(name, _s) *it = v->back; \
|
||||
while (it != NULL) { \
|
||||
struct M_C(name, _s) *next = it->next; \
|
||||
M_CALL_CLEAR(oplist, it->data); \
|
||||
M_C(name,_int_del)(it); \
|
||||
M_C3(m_l1st_,name,_del)(it); \
|
||||
it = next; \
|
||||
} \
|
||||
v->front = NULL; \
|
||||
v->back = NULL; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -963,7 +963,7 @@
|
||||
static inline type const * \
|
||||
M_C(name, _back)(const list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
M_ASSERT (v->back != NULL); \
|
||||
return M_CONST_CAST(type, &(v->back->data)); \
|
||||
} \
|
||||
@@ -971,8 +971,8 @@
|
||||
static inline type * \
|
||||
M_C(name, _push_back_raw)(list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
struct M_C(name, _s) *next = M_C(name, _int_new)(); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
struct M_C(name, _s) *next = M_C3(m_l1st_,name,_new)(); \
|
||||
if (M_UNLIKELY (next == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof (struct M_C(name, _s))); \
|
||||
return NULL; \
|
||||
@@ -985,7 +985,7 @@
|
||||
struct M_C(name, _s) *front = v->front; \
|
||||
front = (front == NULL) ? next : front; \
|
||||
v->front = front; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
@@ -1029,7 +1029,7 @@
|
||||
static inline void \
|
||||
M_C(name, _pop_back)(type *data, list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
M_ASSERT (v->back != NULL); \
|
||||
struct M_C(name, _s) *tofree = v->back; \
|
||||
if (data != NULL) { \
|
||||
@@ -1038,37 +1038,37 @@
|
||||
M_CALL_CLEAR(oplist, tofree->data); \
|
||||
} \
|
||||
v->back = tofree->next; \
|
||||
M_C(name,_int_del)(tofree); \
|
||||
M_C3(m_l1st_,name,_del)(tofree); \
|
||||
/* Update front too if the list became empty */ \
|
||||
/* This C code shall generate branchless code */ \
|
||||
struct M_C(name, _s) *front = v->front; \
|
||||
front = (front == tofree) ? NULL : front; \
|
||||
v->front = front; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _pop_move)(type *data, list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
M_ASSERT (v->back != NULL); \
|
||||
M_ASSERT (data != NULL); \
|
||||
struct M_C(name, _s) *tofree = v->back; \
|
||||
M_DO_INIT_MOVE (oplist, *data, tofree->data); \
|
||||
v->back = tofree->next; \
|
||||
M_C(name,_int_del)(tofree); \
|
||||
M_C3(m_l1st_,name,_del)(tofree); \
|
||||
/* Update front too if the list became empty */ \
|
||||
/* This C code shall generate branchless code */ \
|
||||
struct M_C(name, _s) *front = v->front; \
|
||||
front = (front == tofree) ? NULL : front; \
|
||||
v->front = front; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
} \
|
||||
\
|
||||
static inline type const * \
|
||||
M_C(name, _front)(list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
M_ASSERT (v->front != NULL); \
|
||||
return M_CONST_CAST(type, &(v->front->data)); \
|
||||
} \
|
||||
@@ -1076,8 +1076,8 @@
|
||||
static inline type * \
|
||||
M_C(name, _push_front_raw)(list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
struct M_C(name, _s) *next = M_C(name, _int_new)(); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
struct M_C(name, _s) *next = M_C3(m_l1st_,name,_new)(); \
|
||||
if (M_UNLIKELY (next == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof (struct M_C(name, _s))); \
|
||||
return NULL; \
|
||||
@@ -1091,7 +1091,7 @@
|
||||
v->back = next; \
|
||||
} \
|
||||
v->front = next; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
@@ -1129,15 +1129,15 @@
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(const list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
return v->back == NULL; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _swap)(list_t l, list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(l); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(l); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
M_SWAP(struct M_C(name, _s) *, l->front, v->front); \
|
||||
M_SWAP(struct M_C(name, _s) *, l->back, v->back); \
|
||||
} \
|
||||
@@ -1145,7 +1145,7 @@
|
||||
static inline void \
|
||||
M_C(name, _it)(it_t it, const list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->current = v->back; \
|
||||
it->previous = NULL; \
|
||||
@@ -1163,7 +1163,7 @@
|
||||
M_C(name, _it_end)(it_t it1, const list_t v) \
|
||||
{ \
|
||||
M_ASSERT (it1 != NULL); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
(void)v; /* unused */ \
|
||||
it1->current = NULL; \
|
||||
it1->previous = NULL; \
|
||||
@@ -1215,7 +1215,7 @@
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const list_t v) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(v); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(v); \
|
||||
size_t size = 0; \
|
||||
struct M_C(name, _s) *it = v->back; \
|
||||
while (it != NULL) { \
|
||||
@@ -1229,9 +1229,9 @@
|
||||
M_C(name, _insert)(list_t list, it_t insertion_point, \
|
||||
type const x) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list); \
|
||||
M_ASSERT (insertion_point != NULL); \
|
||||
struct M_C(name, _s) *next = M_C(name, _int_new)(); \
|
||||
struct M_C(name, _s) *next = M_C3(m_l1st_,name,_new)(); \
|
||||
if (M_UNLIKELY (next == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof (struct M_C(name, _s))); \
|
||||
return; \
|
||||
@@ -1257,7 +1257,7 @@
|
||||
static inline void \
|
||||
M_C(name, _remove)(list_t list, it_t removing_point) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list); \
|
||||
M_ASSERT (removing_point != NULL); \
|
||||
M_ASSERT(removing_point->current != NULL); \
|
||||
struct M_C(name, _s) *next = removing_point->current->next; \
|
||||
@@ -1273,15 +1273,15 @@
|
||||
list->front = front; \
|
||||
/* Remove node */ \
|
||||
M_CALL_CLEAR(oplist, removing_point->current->data); \
|
||||
M_C(name,_int_del) (removing_point->current); \
|
||||
M_C3(m_l1st_,name,_del) (removing_point->current); \
|
||||
removing_point->current = next; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _set)(list_t list, const list_t org) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(org); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(org); \
|
||||
struct M_C(name, _s) *next = NULL; \
|
||||
struct M_C(name, _s) *it_org; \
|
||||
struct M_C(name, _s) **update_list; \
|
||||
@@ -1290,7 +1290,7 @@
|
||||
update_list = &list->back; \
|
||||
it_org = org->back; \
|
||||
while (it_org != NULL) { \
|
||||
next = M_C(name, _int_new)(); \
|
||||
next = M_C3(m_l1st_,name,_new)(); \
|
||||
*update_list = next; \
|
||||
if (M_UNLIKELY (next == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof (struct M_C(name, _s))); \
|
||||
@@ -1332,8 +1332,8 @@
|
||||
static inline void \
|
||||
M_C(name, _splice_back)(list_t list1, list_t list2, it_t it) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list1); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list2); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list1); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list2); \
|
||||
M_ASSERT (it->current != NULL); \
|
||||
/* First remove the item 'it' from the list 'list2' */ \
|
||||
struct M_C(name, _s) *current = it->current; \
|
||||
@@ -1357,16 +1357,16 @@
|
||||
front = list1->front; \
|
||||
front = (front == NULL) ? current : front; \
|
||||
list1->front = front; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list1); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list2); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list1); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list2); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _splice_at)(list_t nlist, it_t npos, \
|
||||
list_t olist, it_t opos) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(nlist); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(olist); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(nlist); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(olist); \
|
||||
M_ASSERT (npos != NULL && opos != NULL); \
|
||||
/* First remove the item 'opos' from the list 'olist' */ \
|
||||
struct M_C(name, _s) *current = opos->current; \
|
||||
@@ -1403,15 +1403,15 @@
|
||||
/* Update 'npos' to point to 'current'. */ \
|
||||
npos->previous = npos_current; \
|
||||
npos->current = current; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(nlist); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(olist); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(nlist); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(olist); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _splice)(list_t list1, list_t list2) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list1); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list2); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list1); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list2); \
|
||||
M_ASSERT (list1 != list2); \
|
||||
if (M_LIKELY (list1->front != NULL)) { \
|
||||
list1->front->next = list2->back; \
|
||||
@@ -1423,14 +1423,14 @@
|
||||
} \
|
||||
list2->back = NULL; \
|
||||
list2->front = NULL; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list1); \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list2); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list1); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list2); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _reverse)(list_t list) \
|
||||
{ \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list); \
|
||||
list->front = list->back; \
|
||||
struct M_C(name, _s) *previous = NULL, *it = list->back, *next; \
|
||||
while (it != NULL) { \
|
||||
@@ -1440,7 +1440,7 @@
|
||||
it = next; \
|
||||
} \
|
||||
list->back = previous; \
|
||||
LISTI_DUAL_PUSH_CONTRACT(list); \
|
||||
M_L1ST_DUAL_PUSH_CONTRACT(list); \
|
||||
} \
|
||||
|
||||
#endif
|
||||
+9
-9
@@ -49,7 +49,7 @@
|
||||
*/
|
||||
#define MEMPOOL_DEF_AS(name, name_t, type) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
MEMPOOL_DEF_P2(name, type, name_t ) \
|
||||
M_M3MPOOL_DEF_P2(name, type, name_t ) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
#define MEMPOOL_DEF_P2(name, type, name_t) \
|
||||
#define M_M3MPOOL_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. */ \
|
||||
@@ -101,13 +101,13 @@
|
||||
} \
|
||||
mem->current_segment->next = NULL; \
|
||||
mem->current_segment->count = 0; \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
M_M3MPOOL_CONTRACT(mem, type); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name,_clear)(name_t mem) \
|
||||
{ \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
M_M3MPOOL_CONTRACT(mem, type); \
|
||||
M_C(name,_segment_ct) *segment = mem->current_segment; \
|
||||
while (segment != NULL) { \
|
||||
M_C(name,_segment_ct) *next = segment->next; \
|
||||
@@ -122,7 +122,7 @@
|
||||
static inline type * \
|
||||
M_C(name,_alloc)(name_t mem) \
|
||||
{ \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
M_M3MPOOL_CONTRACT(mem, type); \
|
||||
/* Test if one object is in the free list */ \
|
||||
M_C(name,_union_ct) *ret = mem->free_list; \
|
||||
if (ret != NULL) { \
|
||||
@@ -150,14 +150,14 @@
|
||||
/* Return the object as the last element of the current segment */ \
|
||||
ret = &segment->tab[count]; \
|
||||
segment->count = count + 1; \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
M_M3MPOOL_CONTRACT(mem, type); \
|
||||
return &ret->t; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name,_free)(name_t mem, type *ptr) \
|
||||
{ \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
M_M3MPOOL_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; \
|
||||
@@ -166,11 +166,11 @@
|
||||
mem->free_list = ret; \
|
||||
/* NOTE: the objects are NOT given back to the system until the mempool \
|
||||
is fully cleared */ \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
M_M3MPOOL_CONTRACT(mem, type); \
|
||||
} \
|
||||
|
||||
/* MEMPOOL contract */
|
||||
#define MEMPOOLI_CONTRACT(mempool, type) do { \
|
||||
#define M_M3MPOOL_CONTRACT(mempool, type) do { \
|
||||
M_ASSERT((mempool) != NULL); \
|
||||
M_ASSERT((mempool)->current_segment != NULL); \
|
||||
M_ASSERT((mempool)->current_segment->count <= MEMPOOL_MAX_PER_SEGMENT(type)); \
|
||||
|
||||
+12
-12
@@ -41,7 +41,7 @@
|
||||
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__) \
|
||||
M_PR1OQUEUE_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
|
||||
@@ -50,7 +50,7 @@
|
||||
/* 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__) \
|
||||
M_PR1OQUEUE_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -60,18 +60,18 @@
|
||||
|
||||
/* Deferred evaluation for the definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define PRIOQUEUEI_OPLIST_P1(arg) PRIOQUEUEI_OPLIST_P2 arg
|
||||
#define M_PR1OQUEUE_OPLIST_P1(arg) M_PR1OQUEUE_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define PRIOQUEUEI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(PRIOQUEUEI_OPLIST_P3, PRIOQUEUEI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_PR1OQUEUE_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_PR1OQUEUE_OPLIST_P3, M_PR1OQUEUE_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define PRIOQUEUEI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_PR1OQUEUE_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) \
|
||||
#define M_PR1OQUEUE_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _init)) \
|
||||
,INIT_SET(M_C(name, _init_set)) \
|
||||
,INIT_WITH(API_1(M_INIT_VAI)) \
|
||||
@@ -102,14 +102,14 @@
|
||||
|
||||
/* Deferred evaluation for the definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define PRIOQUEUEI_DEF_P1(arg) PRIOQUEUEI_DEF_P2 arg
|
||||
#define M_PR1OQUEUE_DEF_P1(arg) M_PR1OQUEUE_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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)
|
||||
#define M_PR1OQUEUE_DEF_P2(name, type, oplist, prioqueue_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(M_PR1OQUEUE_DEF_P3, M_PR1OQUEUE_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 M_PR1OQUEUE_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:
|
||||
@@ -119,7 +119,7 @@
|
||||
- prioqueue_t: type of the container,
|
||||
- it_t: iterator of the container
|
||||
*/
|
||||
#define PRIOQUEUEI_DEF_P3(name, type, oplist, prioqueue_t, it_t) \
|
||||
#define M_PR1OQUEUE_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) \
|
||||
|
||||
+128
-128
@@ -38,7 +38,7 @@
|
||||
USAGE: RBTREE_DEF_AS(name, name_t, it_t, type [, oplist_of_the_type]) */
|
||||
#define RBTREE_DEF_AS(name, name_t, it_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
RBTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_RBTR33_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t, M_C(name, _node_ct), it_t ), \
|
||||
(name, __VA_ARGS__, name_t, M_C(name, _node_ct), it_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
@@ -47,7 +47,7 @@
|
||||
/* Define the oplist of a rbtree of type.
|
||||
USAGE: RBTREE_OPLIST(name [, oplist_of_the_type]) */
|
||||
#define RBTREE_OPLIST(...) \
|
||||
RBTREEI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
M_RBTR33_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -56,20 +56,20 @@
|
||||
|
||||
/* Deferred evaluation for the oplist definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define RBTREEI_OPLIST_P1(arg) RBTREEI_OPLIST_P2 arg
|
||||
#define M_RBTR33_OPLIST_P1(arg) M_RBTR33_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define RBTREEI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(RBTREEI_OPLIST_P3, RBTREEI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_RBTR33_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_RBTR33_OPLIST_P3, M_RBTR33_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define RBTREEI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_RBTR33_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_RBTREE_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* OPLIST definition of a rbtree
|
||||
NOTE: IT_REF is not exported so that the contained appears as not modifiable
|
||||
by algorithm.*/
|
||||
#define RBTREEI_OPLIST_P3(name, oplist) \
|
||||
#define M_RBTR33_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _init)), \
|
||||
INIT_SET(M_C(name, _init_set)), \
|
||||
INIT_WITH(API_1(M_INIT_VAI)), \
|
||||
@@ -114,18 +114,18 @@
|
||||
The maximum number of elements is the max of size_t.
|
||||
A perfectly even tree is of depth log2(max(size_t))=CHAR_BIT*sizeof(size_t)
|
||||
*/
|
||||
#define RBTREEI_MAX_STACK (2*CHAR_BIT*sizeof (size_t))
|
||||
#define M_RBTR33_MAX_STACK (2*CHAR_BIT*sizeof (size_t))
|
||||
|
||||
/* Encapsulation of the color of the nodes. */
|
||||
#define RBTREEI_SET_RED(x) ((x)->color = RBTREE_RED)
|
||||
#define RBTREEI_SET_BLACK(x) ((x)->color = RBTREE_BLACK)
|
||||
#define RBTREEI_IS_RED(x) ((x)->color == RBTREE_RED)
|
||||
#define RBTREEI_IS_BLACK(x) ((x)->color == RBTREE_BLACK)
|
||||
#define RBTREEI_COPY_COLOR(x,y) ((x)->color = (y)->color)
|
||||
#define RBTREEI_GET_COLOR(x) (true ? (x)->color : (x)->color)
|
||||
#define RBTREEI_SET_COLOR(x, c) ((x)->color = (c))
|
||||
#define RBTREEI_GET_CHILD(x, n) ((x)->child[n])
|
||||
#define RBTREEI_SET_CHILD(x, n, y) ((x)->child[n] = (y))
|
||||
#define M_RBTR33_SET_RED(x) ((x)->color = RBTREE_RED)
|
||||
#define M_RBTR33_SET_BLACK(x) ((x)->color = RBTREE_BLACK)
|
||||
#define M_RBTR33_IS_RED(x) ((x)->color == RBTREE_RED)
|
||||
#define M_RBTR33_IS_BLACK(x) ((x)->color == RBTREE_BLACK)
|
||||
#define M_RBTR33_COPY_COLOR(x,y) ((x)->color = (y)->color)
|
||||
#define M_RBTR33_GET_COLOR(x) (true ? (x)->color : (x)->color)
|
||||
#define M_RBTR33_SET_COLOR(x, c) ((x)->color = (c))
|
||||
#define M_RBTR33_GET_CHILD(x, n) ((x)->child[n])
|
||||
#define M_RBTR33_SET_CHILD(x, n, y) ((x)->child[n] = (y))
|
||||
|
||||
// Color of a node of a Red/Black tree
|
||||
typedef enum {
|
||||
@@ -133,33 +133,33 @@ typedef enum {
|
||||
} rbtreei_color_e;
|
||||
|
||||
// General contact of a Read/Black tree
|
||||
#define RBTREEI_CONTRACT(tree) do { \
|
||||
#define M_RBTR33_CONTRACT(tree) do { \
|
||||
M_ASSERT ((tree) != NULL); \
|
||||
M_ASSERT ((tree)->node == NULL || RBTREEI_IS_BLACK((tree)->node)); \
|
||||
M_ASSERT ((tree)->node == NULL || M_RBTR33_IS_BLACK((tree)->node)); \
|
||||
M_ASSERT ((tree)->size != 0 || (tree)->node == NULL); \
|
||||
} while (0)
|
||||
|
||||
// Contract of a node (doesn't check for equal depth in black)
|
||||
#define RBTREEI_CONTRACT_NODE(node) do { \
|
||||
#define M_RBTR33_CONTRACT_NODE(node) do { \
|
||||
M_ASSERT((node) != NULL); \
|
||||
M_ASSERT(RBTREEI_IS_BLACK(node) || RBTREEI_IS_RED(node)); \
|
||||
M_ASSERT(RBTREEI_IS_BLACK(node) \
|
||||
|| (((node)->child[0] == NULL || RBTREEI_IS_BLACK(node->child[0])) \
|
||||
&& ((node)->child[1] == NULL || RBTREEI_IS_BLACK(node->child[1])))); \
|
||||
M_ASSERT(M_RBTR33_IS_BLACK(node) || M_RBTR33_IS_RED(node)); \
|
||||
M_ASSERT(M_RBTR33_IS_BLACK(node) \
|
||||
|| (((node)->child[0] == NULL || M_RBTR33_IS_BLACK(node->child[0])) \
|
||||
&& ((node)->child[1] == NULL || M_RBTR33_IS_BLACK(node->child[1])))); \
|
||||
} while (0)
|
||||
|
||||
//TODO: UPDATE method shall be a separate method than push method
|
||||
|
||||
/* Deferred evaluation for the rbtree definition,
|
||||
so that all arguments are evaluated before further expansion */
|
||||
#define RBTREEI_DEF_P1(arg) RBTREEI_DEF_P2 arg
|
||||
#define M_RBTR33_DEF_P1(arg) M_RBTR33_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define RBTREEI_DEF_P2(name, type, oplist, tree_t, node_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(RBTREEI_DEF_P3, RBTREEI_DEF_FAILURE)(name, type, oplist, tree_t, node_t, it_t)
|
||||
#define M_RBTR33_DEF_P2(name, type, oplist, tree_t, node_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(M_RBTR33_DEF_P3, M_RBTR33_DEF_FAILURE)(name, type, oplist, tree_t, node_t, it_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define RBTREEI_DEF_FAILURE(name, type, oplist, tree_t, note_t, it_t) \
|
||||
#define M_RBTR33_DEF_FAILURE(name, type, oplist, tree_t, note_t, it_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(RBTREE_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
/* Internal rbtree definition
|
||||
@@ -170,7 +170,7 @@ typedef enum {
|
||||
- it_t: alias for the iterator of the container
|
||||
- node_t: alias for the node of an element of the container
|
||||
*/
|
||||
#define RBTREEI_DEF_P3(name, type, oplist, tree_t, node_t, it_t) \
|
||||
#define M_RBTR33_DEF_P3(name, type, oplist, tree_t, node_t, it_t) \
|
||||
\
|
||||
/* Node of Red/Black tree. \
|
||||
Each node has up to two child, a color (Red or black) \
|
||||
@@ -192,8 +192,8 @@ typedef enum {
|
||||
/* Iterator on a tree. The iterator stores the full path to the \
|
||||
current node through all its parents and its depth */ \
|
||||
typedef struct M_C(name, _it_s) { \
|
||||
node_t *stack[RBTREEI_MAX_STACK]; \
|
||||
int8_t which[RBTREEI_MAX_STACK]; \
|
||||
node_t *stack[M_RBTR33_MAX_STACK]; \
|
||||
int8_t which[M_RBTR33_MAX_STACK]; \
|
||||
unsigned int cpt; \
|
||||
} it_t[1]; \
|
||||
\
|
||||
@@ -231,10 +231,10 @@ typedef enum {
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
/* Generate all functions */ \
|
||||
RBTREEI_DEF_P4(name, type, oplist, tree_t, node_t, it_t)
|
||||
M_RBTR33_DEF_P4(name, type, oplist, tree_t, node_t, it_t)
|
||||
|
||||
|
||||
#define RBTREEI_DEF_P4(name, type, oplist, tree_t, node_t, it_t) \
|
||||
#define M_RBTR33_DEF_P4(name, type, oplist, tree_t, node_t, it_t) \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init)(tree_t tree) \
|
||||
@@ -242,14 +242,14 @@ typedef enum {
|
||||
M_ASSERT (tree != NULL); \
|
||||
tree->size = 0; \
|
||||
tree->node = NULL; \
|
||||
RBTREEI_CONTRACT(tree); \
|
||||
M_RBTR33_CONTRACT(tree); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clean)(tree_t tree) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT(tree); \
|
||||
node_t *stack[RBTREEI_MAX_STACK]; \
|
||||
M_RBTR33_CONTRACT(tree); \
|
||||
node_t *stack[M_RBTR33_MAX_STACK]; \
|
||||
unsigned int cpt = 0; \
|
||||
/* If nothing (no node) nothing to clean: return */ \
|
||||
if (tree->node == NULL) return; \
|
||||
@@ -259,16 +259,16 @@ typedef enum {
|
||||
node_t *n = stack[cpt-1]; \
|
||||
/* Go down to the bottom left node that exists */ \
|
||||
while (true) { \
|
||||
RBTREEI_CONTRACT_NODE(n); \
|
||||
M_RBTR33_CONTRACT_NODE(n); \
|
||||
/* If there is a left child, get it */ \
|
||||
if (n->child[0] != NULL) { \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
stack[cpt++] = n->child[0]; \
|
||||
n = n->child[0]; \
|
||||
stack[cpt-2]->child[0] = NULL; \
|
||||
/* If there is a right child, get it */ \
|
||||
} else if (n->child[1] != NULL) { \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
stack[cpt++] = n->child[1]; \
|
||||
n = n->child[1]; \
|
||||
stack[cpt-2]->child[1] = NULL; \
|
||||
@@ -300,9 +300,9 @@ typedef enum {
|
||||
static inline void \
|
||||
M_C(name, _push)(tree_t tree, type const data) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT(tree); \
|
||||
node_t *tab[RBTREEI_MAX_STACK]; \
|
||||
int8_t which[RBTREEI_MAX_STACK]; \
|
||||
M_RBTR33_CONTRACT(tree); \
|
||||
node_t *tab[M_RBTR33_MAX_STACK]; \
|
||||
int8_t which[M_RBTR33_MAX_STACK]; \
|
||||
unsigned int cpt = 0; \
|
||||
node_t *n = tree->node; \
|
||||
/* If there is no root node, create a new node */ \
|
||||
@@ -316,17 +316,17 @@ typedef enum {
|
||||
M_CALL_INIT_SET(oplist, n->data, data); \
|
||||
/* Mark the root node as black */ \
|
||||
n->child[0] = n->child[1] = NULL; \
|
||||
RBTREEI_SET_BLACK (n); \
|
||||
M_RBTR33_SET_BLACK (n); \
|
||||
tree->node = n; \
|
||||
M_ASSERT(tree->size == 0); \
|
||||
tree->size = 1; \
|
||||
RBTREEI_CONTRACT(tree); \
|
||||
M_RBTR33_CONTRACT(tree); \
|
||||
return; \
|
||||
} \
|
||||
/* Search for insertion point in the tree */ \
|
||||
tab[cpt] = n; \
|
||||
while (n != NULL) { \
|
||||
RBTREEI_CONTRACT_NODE(n); \
|
||||
M_RBTR33_CONTRACT_NODE(n); \
|
||||
int cmp = M_CALL_CMP(oplist, n->data, data); \
|
||||
if (cmp == 0) { \
|
||||
/* key found ==> stop analysis */ \
|
||||
@@ -338,7 +338,7 @@ typedef enum {
|
||||
n = n->child[s]; \
|
||||
} \
|
||||
/* We cannot overflow the max depth of a tree */ \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
tab[cpt] = n; \
|
||||
} \
|
||||
/* If found, update the data (default is set) */ \
|
||||
@@ -346,7 +346,7 @@ typedef enum {
|
||||
/* FIXME: Use of SET method instead of UPDATE ? */ \
|
||||
M_IF_METHOD (UPDATE, oplist)(M_CALL_UPDATE(oplist, n->data, data) \
|
||||
, M_CALL_SET(oplist, n->data, data)); \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
return; \
|
||||
} \
|
||||
/* Create new node to store the data */ \
|
||||
@@ -358,7 +358,7 @@ typedef enum {
|
||||
/* Copy the data and mark the node as red */ \
|
||||
M_CALL_INIT_SET(oplist, n->data, data); \
|
||||
n->child[0] = n->child[1] = NULL; \
|
||||
RBTREEI_SET_RED (n); \
|
||||
M_RBTR33_SET_RED (n); \
|
||||
/* Add it in the iterator */ \
|
||||
M_ASSERT (tab[cpt] == NULL); \
|
||||
tab[cpt] = n; \
|
||||
@@ -368,18 +368,18 @@ typedef enum {
|
||||
tab[cpt-1]->child[0+which[cpt-1]] = n; \
|
||||
/* Fix the tree to still respect the red/back properties */ \
|
||||
while (cpt >= 2 \
|
||||
&& RBTREEI_IS_RED(tab[cpt-1]) \
|
||||
&& M_RBTR33_IS_RED(tab[cpt-1]) \
|
||||
&& tab[cpt-2]->child[1-which[cpt-2]] != NULL \
|
||||
&& RBTREEI_IS_RED(tab[cpt-2]->child[1-which[cpt-2]])) { \
|
||||
RBTREEI_SET_BLACK(tab[cpt-1]); \
|
||||
RBTREEI_SET_BLACK(tab[cpt-2]->child[1-which[cpt-2]]); \
|
||||
RBTREEI_SET_RED(tab[cpt-2]); \
|
||||
&& M_RBTR33_IS_RED(tab[cpt-2]->child[1-which[cpt-2]])) { \
|
||||
M_RBTR33_SET_BLACK(tab[cpt-1]); \
|
||||
M_RBTR33_SET_BLACK(tab[cpt-2]->child[1-which[cpt-2]]); \
|
||||
M_RBTR33_SET_RED(tab[cpt-2]); \
|
||||
cpt-=2; \
|
||||
} \
|
||||
/* root is always black */ \
|
||||
RBTREEI_SET_BLACK(tab[0]); \
|
||||
if (cpt <= 1 || RBTREEI_IS_BLACK(tab[cpt-1])) { \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_SET_BLACK(tab[0]); \
|
||||
if (cpt <= 1 || M_RBTR33_IS_BLACK(tab[cpt-1])) { \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
return; \
|
||||
} \
|
||||
/* Read the grand-parent, the parent and the element */ \
|
||||
@@ -398,8 +398,8 @@ typedef enum {
|
||||
pp->child[i] = p->child[j]; \
|
||||
p->child[i] = x; \
|
||||
p->child[j] = pp; \
|
||||
RBTREEI_SET_BLACK(p); \
|
||||
RBTREEI_SET_RED(pp); \
|
||||
M_RBTR33_SET_BLACK(p); \
|
||||
M_RBTR33_SET_RED(pp); \
|
||||
} else { \
|
||||
M_ASSERT (j == which[cpt-1]); \
|
||||
/* The child is the right child of its parent */ \
|
||||
@@ -409,9 +409,9 @@ typedef enum {
|
||||
p->child[j] = x->child[i]; \
|
||||
x->child[i] = p; \
|
||||
x->child[j] = pp; \
|
||||
RBTREEI_SET_BLACK(x); \
|
||||
RBTREEI_SET_RED(p); \
|
||||
RBTREEI_SET_RED(pp); \
|
||||
M_RBTR33_SET_BLACK(x); \
|
||||
M_RBTR33_SET_RED(p); \
|
||||
M_RBTR33_SET_RED(pp); \
|
||||
p = x; \
|
||||
} \
|
||||
/* Insert the new grand parent */ \
|
||||
@@ -422,13 +422,13 @@ typedef enum {
|
||||
tab[cpt-3]->child[which[cpt-3]] = p; \
|
||||
} \
|
||||
/* Done */ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const tree_t tree) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
return tree->size; \
|
||||
} \
|
||||
\
|
||||
@@ -436,7 +436,7 @@ typedef enum {
|
||||
static inline void \
|
||||
M_C(name, _int_it)(it_t it, const tree_t tree, int child) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
M_ASSERT (it != NULL); \
|
||||
M_ASSERT (child == 0 || child == 1); \
|
||||
unsigned int cpt = 0; \
|
||||
@@ -445,7 +445,7 @@ typedef enum {
|
||||
node_t *n = it->stack[cpt++] = tree->node; \
|
||||
/* Go down the tree and fill in the iterator */ \
|
||||
while (n->child[child] != NULL) { \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
n = n->child[child]; \
|
||||
it->which[cpt] = (int8_t) child; \
|
||||
it->stack[cpt++] = n; \
|
||||
@@ -470,7 +470,7 @@ typedef enum {
|
||||
static inline void \
|
||||
M_C(name, _it_end)(it_t it, const tree_t tree) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
M_ASSERT (it != NULL); \
|
||||
it->cpt = 0; \
|
||||
} \
|
||||
@@ -502,14 +502,14 @@ typedef enum {
|
||||
const int right = 1 ^ child; \
|
||||
if (n->child[right] != NULL && it->which[cpt] == child) { \
|
||||
/* Going right */ \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
n = n->child[right]; \
|
||||
it->which[cpt++] = (int8_t) right; \
|
||||
it->stack[cpt] = n; \
|
||||
it->which[cpt++] = (int8_t) child; \
|
||||
/* Going left */ \
|
||||
while (n->child[child] != NULL) { \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
n = n->child[child]; \
|
||||
it->which[cpt] = (int8_t) child; \
|
||||
it->stack[cpt++] = n; \
|
||||
@@ -560,7 +560,7 @@ typedef enum {
|
||||
static inline void \
|
||||
M_C(name, _it_from)(it_t it, const tree_t tree, type const data) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
M_ASSERT (it != NULL); \
|
||||
unsigned int cpt = 0; \
|
||||
node_t *n = tree->node; \
|
||||
@@ -572,7 +572,7 @@ typedef enum {
|
||||
int child = (cmp < 0); \
|
||||
it->which[cpt++] = (int8_t) child; \
|
||||
n = n->child[child]; \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
it->stack[cpt] = n; \
|
||||
} \
|
||||
it->cpt = cpt; \
|
||||
@@ -583,7 +583,7 @@ typedef enum {
|
||||
{ \
|
||||
M_ASSERT (it != NULL); \
|
||||
if (it->cpt == 0) return true; \
|
||||
M_ASSERT (it->cpt > 0 && it->cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (it->cpt > 0 && it->cpt < M_RBTR33_MAX_STACK); \
|
||||
node_t *n = it->stack[it->cpt-1]; \
|
||||
int cmp = M_CALL_CMP(oplist, n->data, data); \
|
||||
return (cmp >= 0); \
|
||||
@@ -594,7 +594,7 @@ typedef enum {
|
||||
{ \
|
||||
M_ASSERT (it != NULL); \
|
||||
if (it->cpt == 0) return true; \
|
||||
M_ASSERT (it->cpt > 0 && it->cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (it->cpt > 0 && it->cpt < M_RBTR33_MAX_STACK); \
|
||||
node_t *n = it->stack[it->cpt-1]; \
|
||||
int cmp = M_CALL_CMP(oplist, n->data, data); \
|
||||
return (cmp <= 0); \
|
||||
@@ -609,11 +609,11 @@ typedef enum {
|
||||
static inline type * \
|
||||
M_C(name, _min)(const tree_t tree) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
node_t *n = tree->node; \
|
||||
if (M_UNLIKELY (n == NULL) ) return NULL; \
|
||||
while (n->child[0] != NULL) { \
|
||||
RBTREEI_CONTRACT_NODE (n); \
|
||||
M_RBTR33_CONTRACT_NODE (n); \
|
||||
n = n->child[0]; \
|
||||
} \
|
||||
return &n->data; \
|
||||
@@ -622,11 +622,11 @@ typedef enum {
|
||||
static inline type * \
|
||||
M_C(name, _max)(const tree_t tree) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
node_t *n = tree->node; \
|
||||
if (M_UNLIKELY (n == NULL) ) return NULL; \
|
||||
while (n->child[1] != NULL) { \
|
||||
RBTREEI_CONTRACT_NODE (n); \
|
||||
M_RBTR33_CONTRACT_NODE (n); \
|
||||
n = n->child[1]; \
|
||||
} \
|
||||
return &n->data; \
|
||||
@@ -647,11 +647,11 @@ typedef enum {
|
||||
static inline type * \
|
||||
M_C(name, _get)(const tree_t tree, type const data) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
node_t *n = tree->node; \
|
||||
/* Go down the tree */ \
|
||||
while (n != NULL) { \
|
||||
RBTREEI_CONTRACT_NODE (n); \
|
||||
M_RBTR33_CONTRACT_NODE (n); \
|
||||
int cmp = M_CALL_CMP(oplist, n->data, data); \
|
||||
if (cmp == 0) { \
|
||||
return &n->data; \
|
||||
@@ -682,26 +682,26 @@ typedef enum {
|
||||
M_CALL_INIT_SET(oplist, n->data, o->data); \
|
||||
n->child[0] = M_C(name, _int_copyn)(o->child[0]); \
|
||||
n->child[1] = M_C(name, _int_copyn)(o->child[1]); \
|
||||
RBTREEI_COPY_COLOR (n, o); \
|
||||
M_RBTR33_COPY_COLOR (n, o); \
|
||||
return n; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init_set)(tree_t tree, const tree_t ref) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (ref); \
|
||||
M_RBTR33_CONTRACT (ref); \
|
||||
M_ASSERT (tree != NULL && tree != ref); \
|
||||
tree->size = ref->size; \
|
||||
/* Copy the root node recursively */ \
|
||||
tree->node = M_C(name, _int_copyn)(ref->node); \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _set)(tree_t tree, const tree_t ref) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
RBTREEI_CONTRACT (ref); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (ref); \
|
||||
if (tree == ref) return; \
|
||||
M_C(name,_clear)(tree); \
|
||||
M_C(name,_init_set)(tree, ref); \
|
||||
@@ -710,41 +710,41 @@ typedef enum {
|
||||
static inline void \
|
||||
M_C(name, _init_move)(tree_t tree, tree_t ref) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (ref); \
|
||||
M_RBTR33_CONTRACT (ref); \
|
||||
M_ASSERT (tree != NULL && tree != ref); \
|
||||
tree->size = ref->size; \
|
||||
tree->node = ref->node; \
|
||||
ref->node = NULL; \
|
||||
ref->size = 0; \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _move)(tree_t tree, tree_t ref) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
RBTREEI_CONTRACT (ref); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (ref); \
|
||||
M_ASSERT (tree != ref); \
|
||||
M_C(name,_clear)(tree); \
|
||||
M_C(name,_init_move)(tree, ref); \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _swap)(tree_t tree1, tree_t tree2) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree1); \
|
||||
RBTREEI_CONTRACT (tree2); \
|
||||
M_RBTR33_CONTRACT (tree1); \
|
||||
M_RBTR33_CONTRACT (tree2); \
|
||||
M_SWAP(size_t, tree1->size, tree2->size); \
|
||||
M_SWAP(node_t *, tree1->node, tree2->node); \
|
||||
RBTREEI_CONTRACT (tree1); \
|
||||
RBTREEI_CONTRACT (tree2); \
|
||||
M_RBTR33_CONTRACT (tree1); \
|
||||
M_RBTR33_CONTRACT (tree2); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(const tree_t tree) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
return tree->size == 0; \
|
||||
} \
|
||||
\
|
||||
@@ -752,13 +752,13 @@ typedef enum {
|
||||
static inline bool \
|
||||
M_C(name, _int_is_black)(const node_t *n) \
|
||||
{ \
|
||||
return (n == NULL) ? true : RBTREEI_IS_BLACK(n); \
|
||||
return (n == NULL) ? true : M_RBTR33_IS_BLACK(n); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _int_set_black)(node_t *n) \
|
||||
{ \
|
||||
if (n != NULL) RBTREEI_SET_BLACK(n); \
|
||||
if (n != NULL) M_RBTR33_SET_BLACK(n); \
|
||||
} \
|
||||
\
|
||||
static inline node_t * \
|
||||
@@ -782,7 +782,7 @@ typedef enum {
|
||||
M_C(name, _int_depth)(const node_t *n) \
|
||||
{ \
|
||||
if (n == NULL) return 1; \
|
||||
return RBTREEI_IS_BLACK (n) \
|
||||
return M_RBTR33_IS_BLACK (n) \
|
||||
+ M_C(name, _int_depth)(n->child[0]); \
|
||||
} \
|
||||
) \
|
||||
@@ -790,9 +790,9 @@ typedef enum {
|
||||
static inline bool \
|
||||
M_C(name, _pop_at)(type *data_ptr, tree_t tree, type const key) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
node_t *tab[RBTREEI_MAX_STACK]; \
|
||||
int8_t which[RBTREEI_MAX_STACK]; \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
node_t *tab[M_RBTR33_MAX_STACK]; \
|
||||
int8_t which[M_RBTR33_MAX_STACK]; \
|
||||
unsigned int cpt = 0; \
|
||||
node_t *n = tree->node; \
|
||||
which[0] = 0; \
|
||||
@@ -800,7 +800,7 @@ typedef enum {
|
||||
/* Search for the deletion point */ \
|
||||
tab[cpt] = n; \
|
||||
while (n != NULL) { \
|
||||
RBTREEI_CONTRACT_NODE (n); \
|
||||
M_RBTR33_CONTRACT_NODE (n); \
|
||||
M_ASSERT(M_C(name, _int_depth)(n->child[0]) \
|
||||
== M_C(name, _int_depth)(n->child[1])); \
|
||||
int cmp = M_CALL_CMP(oplist, n->data, key); \
|
||||
@@ -810,7 +810,7 @@ typedef enum {
|
||||
int i = (cmp < 0); \
|
||||
which[cpt++] = (int8_t) i; \
|
||||
n = n->child[i]; \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
tab[cpt] = n; \
|
||||
} \
|
||||
M_ASSERT (tab[cpt] == n); \
|
||||
@@ -821,7 +821,7 @@ typedef enum {
|
||||
unsigned int cpt_n = cpt; \
|
||||
node_t *v = n; /* the replacement node */ \
|
||||
node_t *u; /* the deleted node */ \
|
||||
rbtreei_color_e v_color = RBTREEI_GET_COLOR(v); \
|
||||
rbtreei_color_e v_color = M_RBTR33_GET_COLOR(v); \
|
||||
/* Classical removal of a node from a binary tree */ \
|
||||
if (v->child[0] != NULL && v->child[1] != NULL) { \
|
||||
/* node has 2 child. */ \
|
||||
@@ -831,12 +831,12 @@ typedef enum {
|
||||
tab[cpt] = v; \
|
||||
while (v != NULL) { \
|
||||
/* Always left node */ \
|
||||
RBTREEI_CONTRACT_NODE (v); \
|
||||
M_RBTR33_CONTRACT_NODE (v); \
|
||||
M_ASSERT(M_C(name, _int_depth)(v->child[0]) \
|
||||
== M_C(name, _int_depth)(v->child[1])); \
|
||||
which[cpt++] = 0; \
|
||||
v = v->child[0]; \
|
||||
M_ASSERT (cpt < RBTREEI_MAX_STACK); \
|
||||
M_ASSERT (cpt < M_RBTR33_MAX_STACK); \
|
||||
tab[cpt] = v; \
|
||||
} \
|
||||
/* Pop the last element to get the last non-null element */ \
|
||||
@@ -852,8 +852,8 @@ typedef enum {
|
||||
tab[cpt_n-1]->child[which[cpt_n-1]] = v; \
|
||||
v->child[0] = n->child[0]; \
|
||||
v->child[1] = n->child[1]; \
|
||||
v_color = RBTREEI_GET_COLOR(v); \
|
||||
RBTREEI_COPY_COLOR(v, n); \
|
||||
v_color = M_RBTR33_GET_COLOR(v); \
|
||||
M_RBTR33_COPY_COLOR(v, n); \
|
||||
tab[cpt_n] = v; \
|
||||
/* For the algorithm, 'u' is now the deleted node */ \
|
||||
} else { \
|
||||
@@ -879,12 +879,12 @@ typedef enum {
|
||||
/* if sibling is red, perform a rotation to move sibling up */ \
|
||||
if (!M_C(name, _int_is_black)(s)) { \
|
||||
p = M_C(name, _int_rotate) (p, tab[cpt-1], !nbChild); \
|
||||
RBTREEI_SET_BLACK(p); /* was sibling */ \
|
||||
M_RBTR33_SET_BLACK(p); /* was sibling */ \
|
||||
tab[cpt] = p; \
|
||||
which[cpt++] = nbChild; \
|
||||
p = p->child[nbChild]; /* was parent */ \
|
||||
M_ASSERT (p != NULL); \
|
||||
RBTREEI_SET_RED(p); \
|
||||
M_RBTR33_SET_RED(p); \
|
||||
s = p->child[!nbChild]; \
|
||||
M_ASSERT (M_C(name, _int_is_black)(s)); \
|
||||
} \
|
||||
@@ -895,10 +895,10 @@ typedef enum {
|
||||
&& M_C(name, _int_is_black)(s->child[0]) \
|
||||
&& M_C(name, _int_is_black)(s->child[1])) { \
|
||||
M_ASSERT(M_C(name, _int_depth)(s->child[0]) == M_C(name, _int_depth)(s->child[1])); \
|
||||
RBTREEI_SET_RED(s); \
|
||||
if (RBTREEI_IS_RED(p)) { \
|
||||
RBTREEI_SET_BLACK(p); \
|
||||
RBTREEI_CONTRACT_NODE(p); \
|
||||
M_RBTR33_SET_RED(s); \
|
||||
if (M_RBTR33_IS_RED(p)) { \
|
||||
M_RBTR33_SET_BLACK(p); \
|
||||
M_RBTR33_CONTRACT_NODE(p); \
|
||||
M_ASSERT(M_C(name, _int_depth)(p->child[0]) == M_C(name, _int_depth)(p->child[1])); \
|
||||
break; \
|
||||
} \
|
||||
@@ -908,7 +908,7 @@ typedef enum {
|
||||
/* at least one child of 's' is red */ \
|
||||
/* perform rotation(s) */ \
|
||||
bool childIsRight = !M_C(name, _int_is_black)(s->child[1]); \
|
||||
rbtreei_color_e p_color = RBTREEI_GET_COLOR (p); \
|
||||
rbtreei_color_e p_color = M_RBTR33_GET_COLOR (p); \
|
||||
if (childIsRight != nbChild) { \
|
||||
/* left-left or right-right case */ \
|
||||
p = M_C(name, _int_rotate) (p, tab[cpt-1], childIsRight); \
|
||||
@@ -916,11 +916,11 @@ typedef enum {
|
||||
s = M_C(name, _int_rotate) (s, p, childIsRight); \
|
||||
p = M_C(name, _int_rotate) (p, tab[cpt-1], !nbChild); \
|
||||
} \
|
||||
RBTREEI_SET_COLOR(p, p_color); \
|
||||
M_RBTR33_SET_COLOR(p, p_color); \
|
||||
M_ASSERT(p->child[0] != NULL && p->child[1] != NULL); \
|
||||
RBTREEI_SET_BLACK(p->child[0]); \
|
||||
RBTREEI_SET_BLACK(p->child[1]); \
|
||||
RBTREEI_CONTRACT_NODE(p); \
|
||||
M_RBTR33_SET_BLACK(p->child[0]); \
|
||||
M_RBTR33_SET_BLACK(p->child[1]); \
|
||||
M_RBTR33_CONTRACT_NODE(p); \
|
||||
M_ASSERT(M_C(name, _int_depth)(p->child[0]) == M_C(name, _int_depth)(p->child[1])); \
|
||||
break; \
|
||||
} \
|
||||
@@ -932,7 +932,7 @@ typedef enum {
|
||||
} else { \
|
||||
M_C(name, _int_set_black)(u); \
|
||||
} \
|
||||
M_ASSERT (tree->node == NULL || RBTREEI_IS_BLACK(tree->node)); \
|
||||
M_ASSERT (tree->node == NULL || M_RBTR33_IS_BLACK(tree->node)); \
|
||||
/* delete it */ \
|
||||
if (data_ptr != NULL) \
|
||||
M_DO_MOVE(oplist, *data_ptr, n->data); \
|
||||
@@ -940,14 +940,14 @@ typedef enum {
|
||||
M_CALL_CLEAR(oplist, n->data); \
|
||||
M_C(name,_int_del) (n); \
|
||||
tree->size --; \
|
||||
RBTREEI_CONTRACT (tree); \
|
||||
M_RBTR33_CONTRACT (tree); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
M_IF_METHOD(EQUAL, oplist)( \
|
||||
static inline bool M_C(name,_equal_p)(const tree_t t1, const tree_t t2) { \
|
||||
RBTREEI_CONTRACT(t1); \
|
||||
RBTREEI_CONTRACT(t2); \
|
||||
M_RBTR33_CONTRACT(t1); \
|
||||
M_RBTR33_CONTRACT(t2); \
|
||||
if (t1->size != t2->size) return false; \
|
||||
it_t it1; \
|
||||
it_t it2; \
|
||||
@@ -973,7 +973,7 @@ typedef enum {
|
||||
\
|
||||
M_IF_METHOD(HASH, oplist)( \
|
||||
static inline size_t M_C(name,_hash)(const tree_t t1) { \
|
||||
RBTREEI_CONTRACT(t1); \
|
||||
M_RBTR33_CONTRACT(t1); \
|
||||
M_HASH_DECL(hash); \
|
||||
/* NOTE: We can't compute the hash directly for the same reason \
|
||||
than for EQUAL operator. */ \
|
||||
@@ -991,7 +991,7 @@ typedef enum {
|
||||
M_IF_METHOD(GET_STR, oplist)( \
|
||||
static inline void M_C(name, _get_str)(string_t str, \
|
||||
tree_t const t1, bool append) { \
|
||||
RBTREEI_CONTRACT(t1); \
|
||||
M_RBTR33_CONTRACT(t1); \
|
||||
M_ASSERT(str != NULL); \
|
||||
(append ? string_cat_str : string_set_str) (str, "["); \
|
||||
/* NOTE: The print is really naive, and not really efficient */ \
|
||||
@@ -1014,7 +1014,7 @@ typedef enum {
|
||||
static inline void \
|
||||
M_C(name, _out_str)(FILE *file, tree_t const rbtree) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT(rbtree); \
|
||||
M_RBTR33_CONTRACT(rbtree); \
|
||||
M_ASSERT (file != NULL); \
|
||||
fputc ('[', file); \
|
||||
it_t it; \
|
||||
@@ -1036,7 +1036,7 @@ typedef enum {
|
||||
static inline bool \
|
||||
M_C(name, _parse_str)(tree_t rbtree, const char str[], const char **endp) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT(rbtree); \
|
||||
M_RBTR33_CONTRACT(rbtree); \
|
||||
M_ASSERT (str != NULL); \
|
||||
M_C(name,_clean)(rbtree); \
|
||||
bool success = false; \
|
||||
@@ -1067,7 +1067,7 @@ typedef enum {
|
||||
static inline bool \
|
||||
M_C(name, _in_str)(tree_t rbtree, FILE *file) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT(rbtree); \
|
||||
M_RBTR33_CONTRACT(rbtree); \
|
||||
M_ASSERT (file != NULL); \
|
||||
M_C(name,_clean)(rbtree); \
|
||||
int c = fgetc(file); \
|
||||
@@ -1093,7 +1093,7 @@ typedef enum {
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _out_serial)(m_serial_write_t f, tree_t const t1) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT(t1); \
|
||||
M_RBTR33_CONTRACT(t1); \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_local_t local; \
|
||||
m_serial_return_code_t ret; \
|
||||
@@ -1119,7 +1119,7 @@ typedef enum {
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _in_serial)(tree_t t1, m_serial_read_t f) \
|
||||
{ \
|
||||
RBTREEI_CONTRACT(t1); \
|
||||
M_RBTR33_CONTRACT(t1); \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_local_t local; \
|
||||
m_serial_return_code_t ret; \
|
||||
|
||||
+63
-63
@@ -34,7 +34,7 @@ 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__) \
|
||||
M_SHAR3D_PTR_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST ), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -50,9 +50,9 @@ M_BEGIN_PROTECTED_CODE
|
||||
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__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_ATOMIC_OPLIST, name_t ), \
|
||||
(name, __VA_ARGS__ , SHAREDI_ATOMIC_OPLIST, name_t ))) \
|
||||
M_SHAR3D_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_SHAR3D_ATOMIC_OPLIST, name_t ), \
|
||||
(name, __VA_ARGS__ , M_SHAR3D_ATOMIC_OPLIST, name_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -67,9 +67,9 @@ M_BEGIN_PROTECTED_CODE
|
||||
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__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_INTEGER_OPLIST, name_t ), \
|
||||
(name, __VA_ARGS__, SHAREDI_INTEGER_OPLIST, name_t ))) \
|
||||
M_SHAR3D_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_SHAR3D_INTEGER_OPLIST, name_t ), \
|
||||
(name, __VA_ARGS__, M_SHAR3D_INTEGER_OPLIST, name_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
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__) \
|
||||
M_SHAR3D_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
|
||||
@@ -96,17 +96,17 @@ M_BEGIN_PROTECTED_CODE
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
// deferred evaluation
|
||||
#define SHAREDI_PTR_OPLIST_P1(arg) SHAREDI_PTR_OPLIST_P2 arg
|
||||
#define M_SHAR3D_PTR_OPLIST_P1(arg) M_SHAR3D_PTR_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given, shared_t oplist */
|
||||
#define SHAREDI_PTR_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(SHAREDI_PTR_OPLIST_P3, SHAREDI_PTR_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_SHAR3D_PTR_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_SHAR3D_PTR_OPLIST_P3, M_SHAR3D_PTR_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define SHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_SHAR3D_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) ( \
|
||||
#define M_SHAR3D_PTR_OPLIST_P3(name, oplist) ( \
|
||||
INIT(M_C(name, _init)), \
|
||||
CLEAR(M_C(name, _clear)), \
|
||||
INIT_SET(M_C(name, _init_set)), \
|
||||
@@ -122,44 +122,44 @@ M_BEGIN_PROTECTED_CODE
|
||||
)
|
||||
|
||||
// OPLIST to handle a counter of atomic type
|
||||
#define SHAREDI_ATOMIC_OPLIST (TYPE(atomic_int), \
|
||||
#define M_SHAR3D_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), \
|
||||
IT_CREF(sharedi_integer_cref))
|
||||
#define M_SHAR3D_INTEGER_OPLIST (TYPE(int), \
|
||||
INIT_SET(m_shar3d_integer_init_set), \
|
||||
ADD(m_shar3d_integer_add), \
|
||||
SUB(m_shar3d_integer_sub), \
|
||||
IT_CREF(m_shar3d_integer_cref))
|
||||
|
||||
/* Atomic like interface for basic integers */
|
||||
static inline void sharedi_integer_init_set(int *p, int val) { *p = val; }
|
||||
static inline int sharedi_integer_add(int *p, int val) { int r = *p; *p += val; return r; }
|
||||
static inline int sharedi_integer_sub(int *p, int val) { int r = *p; *p -= val; return r; }
|
||||
static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
static inline void m_shar3d_integer_init_set(int *p, int val) { *p = val; }
|
||||
static inline int m_shar3d_integer_add(int *p, int val) { int r = *p; *p += val; return r; }
|
||||
static inline int m_shar3d_integer_sub(int *p, int val) { int r = *p; *p -= val; return r; }
|
||||
static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
|
||||
/* Contract of a shared pointer */
|
||||
#define SHAREDI_CONTRACT(shared, cpt_oplist) do { \
|
||||
#define M_SHAR3D_CONTRACT(shared, cpt_oplist) do { \
|
||||
M_ASSERT(shared != NULL); \
|
||||
M_ASSERT(*shared == NULL || M_CALL_IT_CREF(cpt_oplist, &(*shared)->cpt) >= 1); \
|
||||
} while (0)
|
||||
|
||||
// deferred evaluation
|
||||
#define SHAREDI_PTR_DEF_P1(arg) SHAREDI_PTR_DEF_P2 arg
|
||||
#define M_SHAR3D_PTR_DEF_P1(arg) M_SHAR3D_PTR_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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)
|
||||
#define M_SHAR3D_PTR_DEF_P2(name, type, oplist, cpt_oplist, shared_t) \
|
||||
M_IF_OPLIST(oplist)(M_SHAR3D_PTR_DEF_P3, M_SHAR3D_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 M_SHAR3D_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) \
|
||||
#define M_SHAR3D_PTR_DEF_P3(name, type, oplist, cpt_oplist, shared_t) \
|
||||
\
|
||||
typedef struct M_C(name, _s){ \
|
||||
type *data; /* Pointer to the data */ \
|
||||
@@ -204,7 +204,7 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_CALL_INIT_SET(cpt_oplist, &ptr->cpt, 1); \
|
||||
ptr->combineAlloc = false; \
|
||||
*shared = ptr; \
|
||||
SHAREDI_CONTRACT(shared, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -224,13 +224,13 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_CALL_INIT_SET(cpt_oplist, &ptr->cpt, 1); \
|
||||
ptr->combineAlloc = true; \
|
||||
*shared = ptr; \
|
||||
SHAREDI_CONTRACT(shared, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _NULL_p)(const shared_t shared) \
|
||||
{ \
|
||||
SHAREDI_CONTRACT(shared, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
return *shared == NULL; \
|
||||
} \
|
||||
\
|
||||
@@ -238,20 +238,20 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _init_set)(shared_t dest, \
|
||||
const shared_t shared) \
|
||||
{ \
|
||||
SHAREDI_CONTRACT(shared, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
M_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); \
|
||||
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(shared_t dest) \
|
||||
{ \
|
||||
SHAREDI_CONTRACT(dest, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
|
||||
if (*dest != NULL) { \
|
||||
if (M_CALL_SUB(cpt_oplist, &((*dest)->cpt), 1) == 1) { \
|
||||
bool combineAlloc = (*dest)->combineAlloc; \
|
||||
@@ -266,7 +266,7 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
} \
|
||||
*dest = NULL; \
|
||||
} \
|
||||
SHAREDI_CONTRACT(dest, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -280,8 +280,8 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _set)(shared_t dest, \
|
||||
const shared_t shared) \
|
||||
{ \
|
||||
SHAREDI_CONTRACT(dest, cpt_oplist); \
|
||||
SHAREDI_CONTRACT(shared, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
M_C(name, _clear)(dest); \
|
||||
M_C(name, _init_set)(dest, shared); \
|
||||
} \
|
||||
@@ -290,19 +290,19 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _init_move)(shared_t dest, \
|
||||
shared_t shared) \
|
||||
{ \
|
||||
SHAREDI_CONTRACT(shared, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
M_ASSERT (dest != NULL && dest != shared); \
|
||||
*dest = *shared; \
|
||||
*shared = NULL; \
|
||||
SHAREDI_CONTRACT(dest, cpt_oplist); \
|
||||
M_SHAR3D_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); \
|
||||
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
M_ASSERT (dest != shared); \
|
||||
M_C(name, _clear)(dest); \
|
||||
M_C(name, _init_move)(dest, shared); \
|
||||
@@ -312,27 +312,27 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _swap)(shared_t p1, \
|
||||
shared_t p2) \
|
||||
{ \
|
||||
SHAREDI_CONTRACT(p1, cpt_oplist); \
|
||||
SHAREDI_CONTRACT(p2, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(p1, cpt_oplist); \
|
||||
M_SHAR3D_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); \
|
||||
M_SHAR3D_CONTRACT(p1, cpt_oplist); \
|
||||
M_SHAR3D_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); \
|
||||
M_SHAR3D_CONTRACT(p1, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(p2, cpt_oplist); \
|
||||
return *p1 == *p2; \
|
||||
} \
|
||||
\
|
||||
static inline type const * \
|
||||
M_C(name, _cref)(const shared_t shared) \
|
||||
{ \
|
||||
SHAREDI_CONTRACT(shared, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
M_ASSERT(*shared != NULL); \
|
||||
type *data = (*shared)->data; \
|
||||
M_ASSERT (data != NULL); \
|
||||
@@ -342,7 +342,7 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
static inline type * \
|
||||
M_C(name, _ref)(shared_t shared) \
|
||||
{ \
|
||||
SHAREDI_CONTRACT(shared, cpt_oplist); \
|
||||
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
|
||||
M_ASSERT(*shared != NULL); \
|
||||
type *data = (*shared)->data; \
|
||||
M_ASSERT (data != NULL); \
|
||||
@@ -353,23 +353,23 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
|
||||
/********************************** SHARED RESOURCE ************************************/
|
||||
|
||||
#define SHAREDI_RESOURCE_CONTRACT(s) do { \
|
||||
#define M_SHAR3D_RESOURCE_CONTRACT(s) do { \
|
||||
M_ASSERT (s != NULL); \
|
||||
M_ASSERT (s->buffer != NULL); \
|
||||
} while (0)
|
||||
|
||||
// deferred
|
||||
#define SHAREDI_RESOURCE_DEF_P1(arg) SHAREDI_RESOURCE_DEF_P2 arg
|
||||
#define M_SHAR3D_RESOURCE_DEF_P1(arg) M_SHAR3D_RESOURCE_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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)
|
||||
#define M_SHAR3D_RESOURCE_DEF_P2(name, type, oplist, shared_t, it_t) \
|
||||
M_IF_OPLIST(oplist)(M_SHAR3D_RESOURCE_DEF_P3, M_SHAR3D_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 M_SHAR3D_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) \
|
||||
#define M_SHAR3D_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) { \
|
||||
@@ -406,13 +406,13 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
atomic_init (&s->buffer[i].cpt, 0U); \
|
||||
} \
|
||||
genint_init(s->core, (unsigned int) n); \
|
||||
SHAREDI_RESOURCE_CONTRACT(s); \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(s); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(shared_t s) \
|
||||
{ \
|
||||
SHAREDI_RESOURCE_CONTRACT(s); \
|
||||
M_SHAR3D_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); \
|
||||
@@ -425,7 +425,7 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
static inline void \
|
||||
M_C(name, _it)(it_t it, shared_t s) \
|
||||
{ \
|
||||
SHAREDI_RESOURCE_CONTRACT(s); \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(s); \
|
||||
M_ASSERT (it != NULL); \
|
||||
unsigned int idx = genint_pop(s->core); \
|
||||
it->idx = idx; \
|
||||
@@ -447,7 +447,7 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _ref)(it_t it) \
|
||||
{ \
|
||||
M_ASSERT (it != NULL && it->ref != NULL && it->idx != GENINT_ERROR); \
|
||||
SHAREDI_RESOURCE_CONTRACT(it->ref); \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(it->ref); \
|
||||
return &it->ref->buffer[it->idx].x; \
|
||||
} \
|
||||
\
|
||||
@@ -455,14 +455,14 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _cref)(it_t it) \
|
||||
{ \
|
||||
M_ASSERT (it != NULL && it->ref != NULL && it->idx != GENINT_ERROR); \
|
||||
SHAREDI_RESOURCE_CONTRACT(it->ref); \
|
||||
M_SHAR3D_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); \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(s); \
|
||||
M_ASSERT (it != NULL); \
|
||||
M_ASSERT (it->ref == s); \
|
||||
unsigned int idx = it->idx; \
|
||||
@@ -479,7 +479,7 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _it_set)(it_t itd, it_t its) \
|
||||
{ \
|
||||
M_ASSERT (itd != NULL && its != NULL); \
|
||||
SHAREDI_RESOURCE_CONTRACT(its->ref); \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(its->ref); \
|
||||
itd->ref = its->ref; \
|
||||
unsigned int idx = its->idx; \
|
||||
itd->idx = idx; \
|
||||
|
||||
+135
-135
@@ -42,7 +42,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
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__) \
|
||||
M_SNAPSH0T_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
|
||||
@@ -59,7 +59,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
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__) \
|
||||
M_SNAPSH0T_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
|
||||
@@ -76,7 +76,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
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__) \
|
||||
M_SNAPSH0T_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
|
||||
@@ -85,7 +85,7 @@ 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__) \
|
||||
M_SNAPSH0T_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
@@ -93,18 +93,18 @@ M_BEGIN_PROTECTED_CODE
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
// deferred evaluation of the input
|
||||
#define SNAPSHOTI_OPLIST_P1(arg) SNAPSHOTI_OPLIST_P2 arg
|
||||
#define M_SNAPSH0T_OPLIST_P1(arg) M_SNAPSH0T_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define SNAPSHOTI_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(SNAPSHOTI_OPLIST_P3, SNAPSHOTI_OPLIST_FAILURE)(name, oplist)
|
||||
#define M_SNAPSH0T_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_SNAPSH0T_OPLIST_P3, M_SNAPSH0T_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define SNAPSHOTI_OPLIST_FAILURE(name, oplist) \
|
||||
#define M_SNAPSH0T_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) \
|
||||
#define M_SNAPSH0T_OPLIST_P3(name, oplist) \
|
||||
(INIT(M_C(name, _init)) \
|
||||
,INIT_SET(M_C(name, _init_set)) \
|
||||
,SET(M_C(name, _set)) \
|
||||
@@ -126,47 +126,47 @@ 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 M_SNAPSH0T_SPSC_FLAG(r, w, f, b) \
|
||||
((unsigned char)( ( (r) << 4) | ((w) << 2) | ((f)) | ((b) << 6)))
|
||||
#define SNAPSHOTI_SPSC_R(flags) \
|
||||
#define M_SNAPSH0T_SPSC_R(flags) \
|
||||
(((unsigned int) (flags) >> 4) & 0x03u)
|
||||
#define SNAPSHOTI_SPSC_W(flags) \
|
||||
#define M_SNAPSH0T_SPSC_W(flags) \
|
||||
(((unsigned int) (flags) >> 2) & 0x03u)
|
||||
#define SNAPSHOTI_SPSC_F(flags) \
|
||||
#define M_SNAPSH0T_SPSC_F(flags) \
|
||||
(((unsigned int) (flags) >> 0) & 0x03u)
|
||||
#define SNAPSHOTI_SPSC_B(flags) \
|
||||
#define M_SNAPSH0T_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) \
|
||||
M_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 M_SNAPSH0T_SPSC_FLAGS_CONTRACT(flags) \
|
||||
M_ASSERT(M_SNAPSH0T_SPSC_R(flags) != M_SNAPSH0T_SPSC_W(flags) \
|
||||
&& M_SNAPSH0T_SPSC_R(flags) != M_SNAPSH0T_SPSC_F(flags) \
|
||||
&& M_SNAPSH0T_SPSC_W(flags) != M_SNAPSH0T_SPSC_F(flags))
|
||||
|
||||
#define SNAPSHOTI_SPSC_CONTRACT(snap) do { \
|
||||
#define M_SNAPSH0T_SPSC_CONTRACT(snap) do { \
|
||||
M_ASSERT((snap) != NULL); \
|
||||
unsigned char f = atomic_load (&(snap)->flags); \
|
||||
SNAPSHOTI_SPSC_FLAGS_CONTRACT(f); \
|
||||
M_SNAPSH0T_SPSC_FLAGS_CONTRACT(f); \
|
||||
} while (0)
|
||||
|
||||
// A snapshot is basically an atomic triple buffer (Lock Free)
|
||||
// between a single producer thread and a single consummer thread.
|
||||
#define SNAPSHOTI_SPSC_MAX_BUFFER 3
|
||||
#define M_SNAPSH0T_SPSC_MAX_BUFFER 3
|
||||
|
||||
// Defered evaluation of the arguments.
|
||||
#define SNAPSHOTI_SPSC_DEF_P1(arg) SNAPSHOTI_SPSC_DEF_P2 arg
|
||||
#define M_SNAPSH0T_SPSC_DEF_P1(arg) M_SNAPSH0T_SPSC_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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)
|
||||
#define M_SNAPSH0T_SPSC_DEF_P2(name, type, oplist, snapshot_t) \
|
||||
M_IF_OPLIST(oplist)(M_SNAPSH0T_SPSC_DEF_P3, M_SNAPSH0T_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 M_SNAPSH0T_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) \
|
||||
#define M_SNAPSH0T_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) { \
|
||||
@@ -175,7 +175,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
} M_C(name, _aligned_type_ct); \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(name, _aligned_type_ct) data[SNAPSHOTI_SPSC_MAX_BUFFER]; \
|
||||
M_C(name, _aligned_type_ct) data[M_SNAPSH0T_SPSC_MAX_BUFFER]; \
|
||||
atomic_uchar flags; \
|
||||
} snapshot_t[1]; \
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
@@ -191,18 +191,18 @@ M_BEGIN_PROTECTED_CODE
|
||||
M_C(name, _init)(snapshot_t snap) \
|
||||
{ \
|
||||
M_ASSERT(snap != NULL); \
|
||||
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
|
||||
for(int i = 0; i < M_SNAPSH0T_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); \
|
||||
atomic_init (&snap->flags, M_SNAPSH0T_SPSC_FLAG(0, 1, 2, 0)); \
|
||||
M_SNAPSH0T_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_SNAPSH0T_SPSC_CONTRACT(snap); \
|
||||
for(int i = 0; i < M_SNAPSH0T_SPSC_MAX_BUFFER; i++) { \
|
||||
M_CALL_CLEAR(oplist, snap->data[i].x); \
|
||||
} \
|
||||
} \
|
||||
@@ -211,40 +211,40 @@ M_BEGIN_PROTECTED_CODE
|
||||
static inline void \
|
||||
M_C(name, _init_set)(snapshot_t snap, snapshot_t org) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(org); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(org); \
|
||||
M_ASSERT(snap != NULL && snap != org); \
|
||||
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
|
||||
for(int i = 0; i < M_SNAPSH0T_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); \
|
||||
M_SNAPSH0T_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_SNAPSH0T_SPSC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(org); \
|
||||
for(int i = 0; i < M_SNAPSH0T_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_SNAPSH0T_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); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(org); \
|
||||
M_ASSERT(snap != NULL && snap != org); \
|
||||
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
|
||||
for(int i = 0; i < M_SNAPSH0T_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); \
|
||||
atomic_store (&org->flags, M_SNAPSH0T_SPSC_FLAG(0,0,0,0) ); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(snap); \
|
||||
} \
|
||||
,) /* IF_METHOD (INIT_MOVE) */ \
|
||||
\
|
||||
@@ -253,103 +253,103 @@ M_BEGIN_PROTECTED_CODE
|
||||
M_C(name, _move)(snapshot_t snap, \
|
||||
snapshot_t org) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
SNAPSHOTI_SPSC_CONTRACT(org); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(org); \
|
||||
M_ASSERT(snap != org); \
|
||||
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
|
||||
for(int i = 0; i < M_SNAPSH0T_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); \
|
||||
atomic_store (&org->flags, M_SNAPSH0T_SPSC_FLAG(0,0,0,0) ); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(snap); \
|
||||
} \
|
||||
,) /* IF_METHOD (MOVE) */ \
|
||||
\
|
||||
static inline type * \
|
||||
M_C(name, _write)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_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); \
|
||||
nextFlags = M_SNAPSH0T_SPSC_FLAG(M_SNAPSH0T_SPSC_R(origFlags), \
|
||||
M_SNAPSH0T_SPSC_F(origFlags), \
|
||||
M_SNAPSH0T_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; \
|
||||
return &snap->data[M_SNAPSH0T_SPSC_W(nextFlags)].x; \
|
||||
} \
|
||||
\
|
||||
static inline type const * \
|
||||
M_C(name, _read)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_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)) { \
|
||||
if (!M_SNAPSH0T_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); \
|
||||
nextFlags = M_SNAPSH0T_SPSC_FLAG(M_SNAPSH0T_SPSC_F(origFlags), \
|
||||
M_SNAPSH0T_SPSC_W(origFlags), \
|
||||
M_SNAPSH0T_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); \
|
||||
return M_CONST_CAST(type, &snap->data[M_SNAPSH0T_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); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(snap); \
|
||||
unsigned char flags = atomic_load (&snap->flags); \
|
||||
return SNAPSHOTI_SPSC_B(flags); \
|
||||
return M_SNAPSH0T_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); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(snap); \
|
||||
unsigned char flags = atomic_load(&snap->flags); \
|
||||
return &snap->data[SNAPSHOTI_SPSC_W(flags)].x; \
|
||||
return &snap->data[M_SNAPSH0T_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); \
|
||||
M_SNAPSH0T_SPSC_CONTRACT(snap); \
|
||||
unsigned char flags = atomic_load(&snap->flags); \
|
||||
return M_CONST_CAST(type, &snap->data[SNAPSHOTI_SPSC_R(flags)].x); \
|
||||
return M_CONST_CAST(type, &snap->data[M_SNAPSH0T_SPSC_R(flags)].x); \
|
||||
} \
|
||||
|
||||
|
||||
|
||||
/******************************** INTERNAL SPMC **********************************/
|
||||
|
||||
#define SNAPSHOTI_SPMC_INT_FLAG(w, n) ( ((w) << 1) | (n) )
|
||||
#define SNAPSHOTI_SPMC_INT_FLAG_W(f) ((f) >> 1)
|
||||
#define SNAPSHOTI_SPMC_INT_FLAG_N(f) ((f) & 1)
|
||||
#define M_SNAPSH0T_SPMC_INT_FLAG(w, n) ( ((w) << 1) | (n) )
|
||||
#define M_SNAPSH0T_SPMC_INT_FLAG_W(f) ((f) >> 1)
|
||||
#define M_SNAPSH0T_SPMC_INT_FLAG_N(f) ((f) & 1)
|
||||
|
||||
// 2 more buffer than the number of readers are needed
|
||||
#define SNAPSHOTI_SPMC_EXTRA_BUFFER 2
|
||||
#define M_SNAPSH0T_SPMC_EXTRA_BUFFER 2
|
||||
|
||||
#define SNAPSHOTI_SPMC_MAX_READER (GENINT_MAX_ALLOC-SNAPSHOTI_SPMC_EXTRA_BUFFER)
|
||||
#define M_SNAPSH0T_SPMC_MAX_READER (GENINT_MAX_ALLOC-M_SNAPSH0T_SPMC_EXTRA_BUFFER)
|
||||
|
||||
/* Internal structure to handle SPMC snapshot but return an unique index in the buffer array.
|
||||
- lastNext: last published written index + next flag (format SNAPSHOTI_SPMC_INT_FLAG)
|
||||
- lastNext: last published written index + next flag (format M_SNAPSH0T_SPMC_INT_FLAG)
|
||||
- currentWrite: the index being currently written.
|
||||
- n_reader : number of readers
|
||||
- cptTab: ref counter array to keep track of how many readers use the corresponding buffer.
|
||||
@@ -364,11 +364,11 @@ 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 { \
|
||||
#define M_SNAPSH0T_SPMC_INT_CONTRACT(s) do { \
|
||||
M_ASSERT (s != NULL); \
|
||||
M_ASSERT (s->n_reader > 0 && s->n_reader <= SNAPSHOTI_SPMC_MAX_READER); \
|
||||
M_ASSERT ((size_t)SNAPSHOTI_SPMC_INT_FLAG_W(atomic_load(&s->lastNext)) \
|
||||
<= s->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER); \
|
||||
M_ASSERT (s->n_reader > 0 && s->n_reader <= M_SNAPSH0T_SPMC_MAX_READER); \
|
||||
M_ASSERT ((size_t)M_SNAPSH0T_SPMC_INT_FLAG_W(atomic_load(&s->lastNext)) \
|
||||
<= s->n_reader + M_SNAPSH0T_SPMC_EXTRA_BUFFER); \
|
||||
M_ASSERT (s->cptTab != NULL); \
|
||||
} while (0)
|
||||
|
||||
@@ -377,9 +377,9 @@ static inline void
|
||||
snapshot_mrsw_int_init(snapshot_mrsw_int_ct s, size_t n)
|
||||
{
|
||||
M_ASSERT (s != NULL);
|
||||
M_ASSERT (n >= 1 && n <= SNAPSHOTI_SPMC_MAX_READER);
|
||||
M_ASSERT (n >= 1 && n <= M_SNAPSH0T_SPMC_MAX_READER);
|
||||
s->n_reader = n;
|
||||
n += SNAPSHOTI_SPMC_EXTRA_BUFFER;
|
||||
n += M_SNAPSH0T_SPMC_EXTRA_BUFFER;
|
||||
|
||||
// Initialize the counters to zero (no reader use it)
|
||||
atomic_uint *ptr = M_MEMORY_REALLOC (atomic_uint, NULL, n);
|
||||
@@ -396,20 +396,20 @@ snapshot_mrsw_int_init(snapshot_mrsw_int_ct s, size_t n)
|
||||
unsigned int w = genint_pop(s->freeList);
|
||||
M_ASSERT (w != GENINT_ERROR);
|
||||
atomic_store(&s->cptTab[w], 1U);
|
||||
atomic_init(&s->lastNext, SNAPSHOTI_SPMC_INT_FLAG(w, true));
|
||||
atomic_init(&s->lastNext, M_SNAPSH0T_SPMC_INT_FLAG(w, true));
|
||||
|
||||
// Get working buffer
|
||||
s->currentWrite = genint_pop(s->freeList);
|
||||
M_ASSERT (s->currentWrite != GENINT_ERROR);
|
||||
atomic_store(&s->cptTab[s->currentWrite], 1U);
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
}
|
||||
|
||||
/* Clear snapshot_mrsw_int_ct (destructor) */
|
||||
static inline void
|
||||
snapshot_mrsw_int_clear(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
M_MEMORY_FREE (s->cptTab);
|
||||
genint_clear(s->freeList);
|
||||
s->cptTab = NULL;
|
||||
@@ -420,7 +420,7 @@ snapshot_mrsw_int_clear(snapshot_mrsw_int_ct s)
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_get_write_idx(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
return s->currentWrite;
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ snapshot_mrsw_int_get_write_idx(snapshot_mrsw_int_ct s)
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_size(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
return (unsigned int) s->n_reader;
|
||||
}
|
||||
|
||||
@@ -437,24 +437,24 @@ snapshot_mrsw_int_size(snapshot_mrsw_int_ct s)
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_write_idx(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
|
||||
// Provide the finalized written buffer to the readers.
|
||||
unsigned int newNext, previous = atomic_load(&s->lastNext);
|
||||
do {
|
||||
newNext = SNAPSHOTI_SPMC_INT_FLAG(idx, true);
|
||||
newNext = M_SNAPSH0T_SPMC_INT_FLAG(idx, true);
|
||||
} while (!atomic_compare_exchange_weak(&s->lastNext, &previous, newNext));
|
||||
|
||||
if (SNAPSHOTI_SPMC_INT_FLAG_N(previous)) {
|
||||
if (M_SNAPSH0T_SPMC_INT_FLAG_N(previous)) {
|
||||
// Reuse previous buffer as it was not used by any reader
|
||||
idx = SNAPSHOTI_SPMC_INT_FLAG_W(previous);
|
||||
idx = M_SNAPSH0T_SPMC_INT_FLAG_W(previous);
|
||||
// Some other read threads may already have try to reserve this index
|
||||
// So atomic_load(&s->cptTab[idx]) can be greater than 1.
|
||||
// However they will fail to ack it in lastNext,
|
||||
// so they will remove their reservation later
|
||||
} else {
|
||||
// Remove the writer thread counter from the count of the previous buffer
|
||||
idx = SNAPSHOTI_SPMC_INT_FLAG_W(previous);
|
||||
idx = M_SNAPSH0T_SPMC_INT_FLAG_W(previous);
|
||||
unsigned int c = atomic_fetch_sub(&s->cptTab[idx], 1U);
|
||||
M_ASSERT (c != 0 && c <= s->n_reader + 1);
|
||||
// Get a new buffer.
|
||||
@@ -467,11 +467,11 @@ snapshot_mrsw_int_write_idx(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
// No other thread keep track of this buffer.
|
||||
// Reuse it.
|
||||
}
|
||||
M_ASSERT (idx < s->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER);
|
||||
M_ASSERT (idx < s->n_reader + M_SNAPSH0T_SPMC_EXTRA_BUFFER);
|
||||
M_ASSERT (atomic_load(&s->cptTab[idx]) == 0);
|
||||
atomic_store(&s->cptTab[idx], 1U);
|
||||
}
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
return idx;
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ static inline unsigned int
|
||||
snapshot_mrsw_int_write(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
s->currentWrite = snapshot_mrsw_int_write_idx(s, s->currentWrite);
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
return s->currentWrite;
|
||||
}
|
||||
|
||||
@@ -488,14 +488,14 @@ snapshot_mrsw_int_write(snapshot_mrsw_int_ct s)
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_write_start(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
// Get a new buffer.
|
||||
unsigned int idx = genint_pop(s->freeList);
|
||||
M_ASSERT (idx != GENINT_ERROR);
|
||||
M_ASSERT (idx < s->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER);
|
||||
M_ASSERT (idx < s->n_reader + M_SNAPSH0T_SPMC_EXTRA_BUFFER);
|
||||
M_ASSERT (atomic_load(&s->cptTab[idx]) == 0);
|
||||
atomic_store(&s->cptTab[idx], 1U);
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
return idx;
|
||||
}
|
||||
|
||||
@@ -503,36 +503,36 @@ snapshot_mrsw_int_write_start(snapshot_mrsw_int_ct s)
|
||||
static inline void
|
||||
snapshot_mrsw_int_write_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
|
||||
// Provide this write bufer to the readers
|
||||
unsigned int newNext, previous = atomic_load(&s->lastNext);
|
||||
do {
|
||||
newNext = SNAPSHOTI_SPMC_INT_FLAG(idx, true);
|
||||
newNext = M_SNAPSH0T_SPMC_INT_FLAG(idx, true);
|
||||
} while (!atomic_compare_exchange_weak(&s->lastNext, &previous, newNext));
|
||||
|
||||
// Free the previous write buffer
|
||||
idx = SNAPSHOTI_SPMC_INT_FLAG_W(previous);
|
||||
idx = M_SNAPSH0T_SPMC_INT_FLAG_W(previous);
|
||||
unsigned int c = atomic_fetch_sub(&s->cptTab[idx], 1U);
|
||||
M_ASSERT (c != 0 && c <= s->n_reader + 1);
|
||||
if (c == 1) {
|
||||
genint_push(s->freeList, idx);
|
||||
}
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
}
|
||||
|
||||
/* Start reading the latest written buffer and return the index to it */
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_read_start(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
unsigned int idx, previous;
|
||||
reload:
|
||||
// Load the last published index + Next flag
|
||||
previous = atomic_load(&s->lastNext);
|
||||
while (true) {
|
||||
// Get the last published index
|
||||
idx = SNAPSHOTI_SPMC_INT_FLAG_W(previous);
|
||||
idx = M_SNAPSH0T_SPMC_INT_FLAG_W(previous);
|
||||
// Load the number of threads using this index
|
||||
unsigned int c = atomic_load(&s->cptTab[idx]);
|
||||
M_ASSERT (c <= s->n_reader + 1);
|
||||
@@ -541,16 +541,16 @@ snapshot_mrsw_int_read_start(snapshot_mrsw_int_ct s)
|
||||
|| !atomic_compare_exchange_strong(&s->cptTab[idx], &c, c+1)))
|
||||
goto reload;
|
||||
// Try to ack it
|
||||
unsigned int newNext = SNAPSHOTI_SPMC_INT_FLAG(idx, false);
|
||||
unsigned int newNext = M_SNAPSH0T_SPMC_INT_FLAG(idx, false);
|
||||
reforce:
|
||||
if (M_LIKELY (atomic_compare_exchange_strong(&s->lastNext, &previous, newNext)))
|
||||
break;
|
||||
// We have been preempted by another thread
|
||||
if (idx == SNAPSHOTI_SPMC_INT_FLAG_W(previous)) {
|
||||
if (idx == M_SNAPSH0T_SPMC_INT_FLAG_W(previous)) {
|
||||
// This is still ok if the index has not changed
|
||||
// We can get previous to true again if the writer has recycled the index,
|
||||
// while we reserved it, and the reader get prempted until its CAS.
|
||||
if (M_UNLIKELY (SNAPSHOTI_SPMC_INT_FLAG_N(previous) == true)) goto reforce;
|
||||
if (M_UNLIKELY (M_SNAPSH0T_SPMC_INT_FLAG_N(previous) == true)) goto reforce;
|
||||
break;
|
||||
}
|
||||
// Free the reserved index as we failed it to ack it
|
||||
@@ -560,7 +560,7 @@ snapshot_mrsw_int_read_start(snapshot_mrsw_int_ct s)
|
||||
genint_push(s->freeList, idx);
|
||||
}
|
||||
}
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
return idx;
|
||||
}
|
||||
|
||||
@@ -568,8 +568,8 @@ snapshot_mrsw_int_read_start(snapshot_mrsw_int_ct s)
|
||||
static inline void
|
||||
snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_ASSERT (idx < s->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
M_ASSERT (idx < s->n_reader + M_SNAPSH0T_SPMC_EXTRA_BUFFER);
|
||||
// Decrement reference counter of the buffer
|
||||
unsigned int c = atomic_fetch_sub(&s->cptTab[idx], 1U);
|
||||
M_ASSERT (c != 0 && c <= s->n_reader + 1);
|
||||
@@ -578,30 +578,30 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
// Push back index in free list
|
||||
genint_push(s->freeList, idx);
|
||||
}
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
}
|
||||
|
||||
/* Contract of a SPMC snapshot.
|
||||
Nothing notable as it can be accessed concurrently */
|
||||
#define SNAPSHOTI_SPMC_CONTRACT(snap) do { \
|
||||
#define M_SNAPSH0T_SPMC_CONTRACT(snap) do { \
|
||||
M_ASSERT (snap != NULL); \
|
||||
M_ASSERT (snap->data != NULL); \
|
||||
} while (0)
|
||||
|
||||
|
||||
// Defered evaluation
|
||||
#define SNAPSHOTI_SPMC_DEF_P1(arg) SNAPSHOTI_SPMC_DEF_P2 arg
|
||||
#define M_SNAPSH0T_SPMC_DEF_P1(arg) M_SNAPSH0T_SPMC_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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)
|
||||
#define M_SNAPSH0T_SPMC_DEF_P2(name, type, oplist, snapshot_t) \
|
||||
M_IF_OPLIST(oplist)(M_SNAPSH0T_SPMC_DEF_P3, M_SNAPSH0T_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 M_SNAPSH0T_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) \
|
||||
#define M_SNAPSH0T_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) { \
|
||||
@@ -624,27 +624,27 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
M_C(name, _init)(snapshot_t snap, size_t nReader) \
|
||||
{ \
|
||||
M_ASSERT (snap != NULL); \
|
||||
M_ASSERT (nReader > 0 && nReader <= SNAPSHOTI_SPMC_MAX_READER); \
|
||||
M_ASSERT (nReader > 0 && nReader <= M_SNAPSH0T_SPMC_MAX_READER); \
|
||||
snap->data = M_CALL_REALLOC(oplist, M_C(name, _aligned_type_ct), \
|
||||
NULL, nReader+SNAPSHOTI_SPMC_EXTRA_BUFFER); \
|
||||
NULL, nReader+M_SNAPSH0T_SPMC_EXTRA_BUFFER); \
|
||||
if (M_UNLIKELY (snap->data == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof(M_C(name, _aligned_type_ct)) * \
|
||||
(nReader+SNAPSHOTI_SPMC_EXTRA_BUFFER)); \
|
||||
(nReader+M_SNAPSH0T_SPMC_EXTRA_BUFFER)); \
|
||||
return; \
|
||||
} \
|
||||
for(size_t i = 0; i < nReader + SNAPSHOTI_SPMC_EXTRA_BUFFER; i++) { \
|
||||
for(size_t i = 0; i < nReader + M_SNAPSH0T_SPMC_EXTRA_BUFFER; i++) { \
|
||||
M_CALL_INIT(oplist, snap->data[i].x); \
|
||||
} \
|
||||
snapshot_mrsw_int_init(snap->core, nReader); \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_SPMC_CONTRACT(snap); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_SPMC_CONTRACT(snap); \
|
||||
size_t nReader = snapshot_mrsw_int_size(snap->core); \
|
||||
for(size_t i = 0; i < nReader + SNAPSHOTI_SPMC_EXTRA_BUFFER; i++) { \
|
||||
for(size_t i = 0; i < nReader + M_SNAPSH0T_SPMC_EXTRA_BUFFER; i++) { \
|
||||
M_CALL_CLEAR(oplist, snap->data[i].x); \
|
||||
} \
|
||||
M_CALL_FREE(oplist, snap->data); \
|
||||
@@ -654,7 +654,7 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
static inline type * \
|
||||
M_C(name, _write)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_SPMC_CONTRACT(snap); \
|
||||
const unsigned int idx = snapshot_mrsw_int_write(snap->core); \
|
||||
return &snap->data[idx].x; \
|
||||
} \
|
||||
@@ -662,7 +662,7 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
static inline type const * \
|
||||
M_C(name, _read_start)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_SPMC_CONTRACT(snap); \
|
||||
const unsigned int idx = snapshot_mrsw_int_read_start(snap->core); \
|
||||
return M_CONST_CAST(type, &snap->data[idx].x); \
|
||||
} \
|
||||
@@ -670,13 +670,13 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
static inline void \
|
||||
M_C(name, _read_end)(snapshot_t snap, type const *old) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_SPMC_CONTRACT(snap); \
|
||||
M_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); \
|
||||
M_ASSERT (oldx >= snap->data); \
|
||||
M_ASSERT (oldx < snap->data + snap->core->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER); \
|
||||
M_ASSERT(snap->core->n_reader +SNAPSHOTI_SPMC_EXTRA_BUFFER < UINT_MAX); \
|
||||
M_ASSERT (oldx < snap->data + snap->core->n_reader + M_SNAPSH0T_SPMC_EXTRA_BUFFER); \
|
||||
M_ASSERT(snap->core->n_reader +M_SNAPSH0T_SPMC_EXTRA_BUFFER < UINT_MAX); \
|
||||
const unsigned int idx = (unsigned int) (oldx - snap->data); \
|
||||
snapshot_mrsw_int_read_end(snap->core, idx); \
|
||||
} \
|
||||
@@ -684,7 +684,7 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
static inline type * \
|
||||
M_C(name, _get_write_buffer)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
M_SNAPSH0T_SPMC_CONTRACT(snap); \
|
||||
const unsigned int idx = snapshot_mrsw_int_get_write_idx(snap->core); \
|
||||
return &snap->data[idx].x; \
|
||||
} \
|
||||
@@ -699,20 +699,20 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
// MPMC is built upon SPMC
|
||||
|
||||
// Defered evaluation
|
||||
#define SNAPSHOTI_MPMC_DEF_P1(arg) SNAPSHOTI_MPMC_DEF_P2 arg
|
||||
#define M_SNAPSH0T_MPMC_DEF_P1(arg) M_SNAPSH0T_MPMC_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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)
|
||||
#define M_SNAPSH0T_MPMC_DEF_P2(name, type, oplist, snapshot_t) \
|
||||
M_IF_OPLIST(oplist)(M_SNAPSH0T_MPMC_DEF_P3, M_SNAPSH0T_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 M_SNAPSH0T_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 M_SNAPSH0T_MPMC_DEF_P3(name, type, oplist, snapshot_t) \
|
||||
\
|
||||
SNAPSHOTI_SPMC_DEF_P1((M_C(name, _mrsw), type, oplist, M_C(name, _mrsw_pct))) \
|
||||
M_SNAPSH0T_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; \
|
||||
@@ -742,7 +742,7 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
static inline type * \
|
||||
M_C(name, _write_start)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap->core); \
|
||||
M_SNAPSH0T_SPMC_CONTRACT(snap->core); \
|
||||
const unsigned int idx = snapshot_mrsw_int_write_start(snap->core->core); \
|
||||
return &snap->core->data[idx].x; \
|
||||
} \
|
||||
@@ -750,12 +750,12 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
static inline void \
|
||||
M_C(name, _write_end)(snapshot_t snap, type *old) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap->core); \
|
||||
M_SNAPSH0T_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); \
|
||||
M_ASSERT (oldx >= snap->core->data); \
|
||||
M_ASSERT (oldx < snap->core->data + snap->core->core->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER); \
|
||||
M_ASSERT(snap->core->core->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER < UINT_MAX); \
|
||||
M_ASSERT (oldx < snap->core->data + snap->core->core->n_reader + M_SNAPSH0T_SPMC_EXTRA_BUFFER); \
|
||||
M_ASSERT(snap->core->core->n_reader + M_SNAPSH0T_SPMC_EXTRA_BUFFER < UINT_MAX); \
|
||||
const unsigned int idx = (unsigned int) (oldx - snap->core->data); \
|
||||
snapshot_mrsw_int_write_end(snap->core->core, idx); \
|
||||
} \
|
||||
|
||||
+163
-163
File diff suppressed because it is too large.
Load diff
@@ -42,7 +42,7 @@
|
||||
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__)) ) \
|
||||
M_TUPL3_DEF2_P1( (name, name_t M_TUPL3_INJECT_GLOBAL(__VA_ARGS__)) ) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
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 )), \
|
||||
TUPLEI_OPLIST_P1((__VA_ARGS__ )))
|
||||
(M_TUPL3_OPLIST_P1((__VA_ARGS__, M_DEFAULT_OPLIST )), \
|
||||
M_TUPL3_OPLIST_P1((__VA_ARGS__ )))
|
||||
|
||||
|
||||
/* Return an array suitable for the WIP _cmp_order function.
|
||||
@@ -61,14 +61,14 @@
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
#define TUPLE_ORDER(name, ...) \
|
||||
( (const int[]) {M_MAP2_C(TUPLEI_ORDER_CONVERT, name, __VA_ARGS__), 0})
|
||||
( (const int[]) {M_MAP2_C(M_TUPL3_ORDER_CONVERT, name, __VA_ARGS__), 0})
|
||||
#else
|
||||
#include <initializer_list>
|
||||
namespace m_lib {
|
||||
template <unsigned int N>
|
||||
struct m_int_array {
|
||||
struct m_tupl3_int_va {
|
||||
int data[N];
|
||||
/*constexpr*/ inline m_int_array(std::initializer_list<int> init){
|
||||
/*constexpr*/ inline m_tupl3_int_va(std::initializer_list<int> init){
|
||||
int j = 0;
|
||||
for(auto i:init) {
|
||||
data[j++] = i;
|
||||
@@ -77,132 +77,132 @@ namespace m_lib {
|
||||
};
|
||||
}
|
||||
#define TUPLE_ORDER(name, ...) \
|
||||
(m_lib::m_int_array<M_NARGS(__VA_ARGS__,0)>({M_MAP2_C(TUPLEI_ORDER_CONVERT, name, __VA_ARGS__), 0}).data)
|
||||
(m_lib::m_tupl3_int_va<M_NARGS(__VA_ARGS__,0)>({M_MAP2_C(M_TUPL3_ORDER_CONVERT, name, __VA_ARGS__), 0}).data)
|
||||
#endif
|
||||
|
||||
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
/* Contract of a tuple. Nothing notable */
|
||||
#define TUPLEI_CONTRACT(tup) do { \
|
||||
#define M_TUPL3_CONTRACT(tup) do { \
|
||||
M_ASSERT(tup != NULL); \
|
||||
} while (0)
|
||||
|
||||
/* Inject the oplist within the list of arguments */
|
||||
#define TUPLEI_INJECT_GLOBAL(...) \
|
||||
M_MAP(TUPLEI_INJECT_OPLIST_A, __VA_ARGS__)
|
||||
#define M_TUPL3_INJECT_GLOBAL(...) \
|
||||
M_MAP(M_TUPL3_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 TUPLEI_INJECT_OPLIST_A( duo_or_trio ) \
|
||||
TUPLEI_INJECT_OPLIST_B duo_or_trio
|
||||
#define M_TUPL3_INJECT_OPLIST_A( duo_or_trio ) \
|
||||
M_TUPL3_INJECT_OPLIST_B duo_or_trio
|
||||
|
||||
#define TUPLEI_INJECT_OPLIST_B( f, ... ) \
|
||||
#define M_TUPL3_INJECT_OPLIST_B( f, ... ) \
|
||||
M_DEFERRED_COMMA \
|
||||
M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) )
|
||||
|
||||
// Deferred evaluation
|
||||
#define TUPLEI_DEF2_P1(...) TUPLEI_DEF2_P2 __VA_ARGS__
|
||||
#define M_TUPL3_DEF2_P1(...) M_TUPL3_DEF2_P2 __VA_ARGS__
|
||||
|
||||
// Test if all third argument of all arguments is an oplist
|
||||
#define TUPLEI_IF_ALL_OPLIST(...) \
|
||||
M_IF(M_REDUCE(TUPLEI_IS_OPLIST_P, M_AND, __VA_ARGS__))
|
||||
#define M_TUPL3_IF_ALL_OPLIST(...) \
|
||||
M_IF(M_REDUCE(M_TUPL3_IS_OPLIST_P, M_AND, __VA_ARGS__))
|
||||
|
||||
// Test if the third argument of (name, type, oplist) is an oplist
|
||||
#define TUPLEI_IS_OPLIST_P(a) \
|
||||
#define M_TUPL3_IS_OPLIST_P(a) \
|
||||
M_OPLIST_P(M_RET_ARG3 a)
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define TUPLEI_DEF2_P2(name, name_t, ...) \
|
||||
TUPLEI_IF_ALL_OPLIST(__VA_ARGS__)(TUPLEI_DEF2_P3, TUPLEI_DEF2_FAILURE)(name, name_t, __VA_ARGS__)
|
||||
#define M_TUPL3_DEF2_P2(name, name_t, ...) \
|
||||
M_TUPL3_IF_ALL_OPLIST(__VA_ARGS__)(M_TUPL3_DEF2_P3, M_TUPL3_DEF2_FAILURE)(name, name_t, __VA_ARGS__)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define TUPLEI_DEF2_FAILURE(name, name_t, ...) \
|
||||
#define M_TUPL3_DEF2_FAILURE(name, name_t, ...) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(TUPLE_DEF2): at least one of the given argument is not a valid oplist: " #__VA_ARGS__)
|
||||
|
||||
/* Define the tuple */
|
||||
#define TUPLEI_DEF2_P3(name, name_t, ...) \
|
||||
TUPLEI_DEFINE_TYPE(name, name_t, __VA_ARGS__) \
|
||||
TUPLEI_DEFINE_ENUM(name, __VA_ARGS__) \
|
||||
TUPLEI_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
|
||||
TUPLEI_IF_ALL(INIT, __VA_ARGS__)(TUPLEI_DEFINE_INIT(name, __VA_ARGS__),) \
|
||||
TUPLEI_DEFINE_INIT_SET(name, __VA_ARGS__) \
|
||||
TUPLEI_DEFINE_INIT_SET2(name, __VA_ARGS__) \
|
||||
TUPLEI_DEFINE_SET(name, __VA_ARGS__) \
|
||||
TUPLEI_DEFINE_SET2(name, __VA_ARGS__) \
|
||||
TUPLEI_DEFINE_CLEAR(name, __VA_ARGS__) \
|
||||
TUPLEI_DEFINE_GETTER_FIELD(name, __VA_ARGS__) \
|
||||
TUPLEI_DEFINE_SETTER_FIELD(name, __VA_ARGS__) \
|
||||
TUPLEI_IF_ALL(CMP, __VA_ARGS__)(TUPLEI_DEFINE_CMP(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(CMP, __VA_ARGS__)(TUPLEI_DEFINE_CMP_ORDER(name, __VA_ARGS__),) \
|
||||
TUPLEI_DEFINE_CMP_FIELD(name, __VA_ARGS__) \
|
||||
TUPLEI_IF_ALL(HASH, __VA_ARGS__)(TUPLEI_DEFINE_HASH(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(EQUAL, __VA_ARGS__)(TUPLEI_DEFINE_EQUAL(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(GET_STR, __VA_ARGS__)(TUPLEI_DEFINE_GET_STR(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(OUT_STR, __VA_ARGS__)(TUPLEI_DEFINE_OUT_STR(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(IN_STR, __VA_ARGS__)(TUPLEI_DEFINE_IN_STR(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(PARSE_STR, __VA_ARGS__)(TUPLEI_DEFINE_PARSE_STR(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(OUT_SERIAL, __VA_ARGS__)(TUPLEI_DEFINE_OUT_SERIAL(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(IN_SERIAL, __VA_ARGS__)(TUPLEI_DEFINE_IN_SERIAL(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(INIT_MOVE, __VA_ARGS__)(TUPLEI_DEFINE_INIT_MOVE(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(MOVE, __VA_ARGS__)(TUPLEI_DEFINE_MOVE(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(SWAP, __VA_ARGS__)(TUPLEI_DEFINE_SWAP(name, __VA_ARGS__),) \
|
||||
TUPLEI_IF_ALL(CLEAN, __VA_ARGS__)(TUPLEI_DEFINE_CLEAN(name, __VA_ARGS__),)
|
||||
#define M_TUPL3_DEF2_P3(name, name_t, ...) \
|
||||
M_TUPL3_DEFINE_TYPE(name, name_t, __VA_ARGS__) \
|
||||
M_TUPL3_DEFINE_ENUM(name, __VA_ARGS__) \
|
||||
M_TUPL3_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
|
||||
M_TUPL3_IF_ALL(INIT, __VA_ARGS__)(M_TUPL3_DEFINE_INIT(name, __VA_ARGS__),) \
|
||||
M_TUPL3_DEFINE_INIT_SET(name, __VA_ARGS__) \
|
||||
M_TUPL3_DEFINE_INIT_SET2(name, __VA_ARGS__) \
|
||||
M_TUPL3_DEFINE_SET(name, __VA_ARGS__) \
|
||||
M_TUPL3_DEFINE_SET2(name, __VA_ARGS__) \
|
||||
M_TUPL3_DEFINE_CLEAR(name, __VA_ARGS__) \
|
||||
M_TUPL3_DEFINE_GETTER_FIELD(name, __VA_ARGS__) \
|
||||
M_TUPL3_DEFINE_SETTER_FIELD(name, __VA_ARGS__) \
|
||||
M_TUPL3_IF_ALL(CMP, __VA_ARGS__)(M_TUPL3_DEFINE_CMP(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(CMP, __VA_ARGS__)(M_TUPL3_DEFINE_CMP_ORDER(name, __VA_ARGS__),) \
|
||||
M_TUPL3_DEFINE_CMP_FIELD(name, __VA_ARGS__) \
|
||||
M_TUPL3_IF_ALL(HASH, __VA_ARGS__)(M_TUPL3_DEFINE_HASH(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(EQUAL, __VA_ARGS__)(M_TUPL3_DEFINE_EQUAL(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(GET_STR, __VA_ARGS__)(M_TUPL3_DEFINE_GET_STR(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(OUT_STR, __VA_ARGS__)(M_TUPL3_DEFINE_OUT_STR(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(IN_STR, __VA_ARGS__)(M_TUPL3_DEFINE_IN_STR(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(PARSE_STR, __VA_ARGS__)(M_TUPL3_DEFINE_PARSE_STR(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(OUT_SERIAL, __VA_ARGS__)(M_TUPL3_DEFINE_OUT_SERIAL(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(IN_SERIAL, __VA_ARGS__)(M_TUPL3_DEFINE_IN_SERIAL(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(INIT_MOVE, __VA_ARGS__)(M_TUPL3_DEFINE_INIT_MOVE(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(MOVE, __VA_ARGS__)(M_TUPL3_DEFINE_MOVE(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(SWAP, __VA_ARGS__)(M_TUPL3_DEFINE_SWAP(name, __VA_ARGS__),) \
|
||||
M_TUPL3_IF_ALL(CLEAN, __VA_ARGS__)(M_TUPL3_DEFINE_CLEAN(name, __VA_ARGS__),)
|
||||
|
||||
/* Provide order for _cmp_order */
|
||||
#define TUPLEI_ORDER_CONVERT(name, x) M_C(name, M_C(TUPLEI_ORDER_CONVERT_, x))
|
||||
#define TUPLEI_ORDER_CONVERT_ASC(x) M_C3(_,x,_value)
|
||||
#define TUPLEI_ORDER_CONVERT_DSC(x) M_C3(_,x,_value)*-1
|
||||
#define M_TUPL3_ORDER_CONVERT(name, x) M_C(name, M_C(M_TUPL3_ORDER_CONVERT_, x))
|
||||
#define M_TUPL3_ORDER_CONVERT_ASC(x) M_C3(_,x,_value)
|
||||
#define M_TUPL3_ORDER_CONVERT_DSC(x) M_C3(_,x,_value)*-1
|
||||
|
||||
/* Get the field name, the type, the oplist or the methods
|
||||
based on the tuple (field, type, oplist) */
|
||||
#define TUPLEI_GET_FIELD(f,t,o) f
|
||||
#define TUPLEI_GET_TYPE(f,t,o) t
|
||||
#define TUPLEI_GET_OPLIST(f,t,o) o
|
||||
#define TUPLEI_GET_INIT(f,t,o) M_GET_INIT o
|
||||
#define TUPLEI_GET_INIT_SET(f,t,o) M_GET_INIT_SET o
|
||||
#define TUPLEI_GET_INIT_MOVE(f,t,o) M_GET_INIT_MOVE o
|
||||
#define TUPLEI_GET_MOVE(f,t,o) M_GET_MOVE o
|
||||
#define TUPLEI_GET_SET(f,t,o) M_GET_SET o
|
||||
#define TUPLEI_GET_CLEAR(f,t,o) M_GET_CLEAR o
|
||||
#define TUPLEI_GET_CMP(f,t,o) M_GET_CMP o
|
||||
#define TUPLEI_GET_HASH(f,t,o) M_GET_HASH o
|
||||
#define TUPLEI_GET_EQUAL(f,t,o) M_GET_EQUAL o
|
||||
#define TUPLEI_GET_STR(f,t,o) M_GET_GET_STR o
|
||||
#define TUPLEI_GET_OUT_STR(f,t,o) M_GET_OUT_STR o
|
||||
#define TUPLEI_GET_IN_STR(f,t,o) M_GET_IN_STR o
|
||||
#define TUPLEI_GET_OUT_SERIAL(f,t,o) M_GET_OUT_SERIAL o
|
||||
#define TUPLEI_GET_IN_SERIAL(f,t,o) M_GET_IN_SERIAL o
|
||||
#define TUPLEI_GET_PARSE_STR(f,t,o) M_GET_PARSE_STR o
|
||||
#define TUPLEI_GET_SWAP(f,t,o) M_GET_SWAP o
|
||||
#define TUPLEI_GET_CLEAN(f,t,o) M_GET_CLEAN o
|
||||
#define M_TUPL3_GET_FIELD(f,t,o) f
|
||||
#define M_TUPL3_GET_TYPE(f,t,o) t
|
||||
#define M_TUPL3_GET_OPLIST(f,t,o) o
|
||||
#define M_TUPL3_GET_INIT(f,t,o) M_GET_INIT o
|
||||
#define M_TUPL3_GET_INIT_SET(f,t,o) M_GET_INIT_SET o
|
||||
#define M_TUPL3_GET_INIT_MOVE(f,t,o) M_GET_INIT_MOVE o
|
||||
#define M_TUPL3_GET_MOVE(f,t,o) M_GET_MOVE o
|
||||
#define M_TUPL3_GET_SET(f,t,o) M_GET_SET o
|
||||
#define M_TUPL3_GET_CLEAR(f,t,o) M_GET_CLEAR o
|
||||
#define M_TUPL3_GET_CMP(f,t,o) M_GET_CMP o
|
||||
#define M_TUPL3_GET_HASH(f,t,o) M_GET_HASH o
|
||||
#define M_TUPL3_GET_EQUAL(f,t,o) M_GET_EQUAL o
|
||||
#define M_TUPL3_GET_STR(f,t,o) M_GET_GET_STR o
|
||||
#define M_TUPL3_GET_OUT_STR(f,t,o) M_GET_OUT_STR o
|
||||
#define M_TUPL3_GET_IN_STR(f,t,o) M_GET_IN_STR o
|
||||
#define M_TUPL3_GET_OUT_SERIAL(f,t,o) M_GET_OUT_SERIAL o
|
||||
#define M_TUPL3_GET_IN_SERIAL(f,t,o) M_GET_IN_SERIAL o
|
||||
#define M_TUPL3_GET_PARSE_STR(f,t,o) M_GET_PARSE_STR o
|
||||
#define M_TUPL3_GET_SWAP(f,t,o) M_GET_SWAP o
|
||||
#define M_TUPL3_GET_CLEAN(f,t,o) M_GET_CLEAN o
|
||||
|
||||
/* Call the method associated to the given operator for the given parameter
|
||||
of the tuple t=(name, type, oplist) */
|
||||
#define TUPLEI_CALL_INIT(t, ...) M_APPLY_API(TUPLEI_GET_INIT t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_INIT_SET(t, ...) M_APPLY_API(TUPLEI_GET_INIT_SET t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_INIT_MOVE(t, ...) M_APPLY_API(TUPLEI_GET_INIT_MOVE t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_MOVE(t, ...) M_APPLY_API(TUPLEI_GET_MOVE t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_SET(t, ...) M_APPLY_API(TUPLEI_GET_SET t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_CLEAR(t, ...) M_APPLY_API(TUPLEI_GET_CLEAR t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_CMP(t, ...) M_APPLY_API(TUPLEI_GET_CMP t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_HASH(t, ...) M_APPLY_API(TUPLEI_GET_HASH t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_EQUAL(t, ...) M_APPLY_API(TUPLEI_GET_EQUAL t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_GET_STR(t, ...) M_APPLY_API(TUPLEI_GET_STR t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_OUT_STR(t, ...) M_APPLY_API(TUPLEI_GET_OUT_STR t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_IN_STR(t, ...) M_APPLY_API(TUPLEI_GET_IN_STR t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_PARSE_STR(t, ...) M_APPLY_API(TUPLEI_GET_PARSE_STR t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_OUT_SERIAL(t, ...) M_APPLY_API(TUPLEI_GET_OUT_SERIAL t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_IN_SERIAL(t, ...) M_APPLY_API(TUPLEI_GET_IN_SERIAL t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_SWAP(t, ...) M_APPLY_API(TUPLEI_GET_SWAP t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define TUPLEI_CALL_CLEAN(t, ...) M_APPLY_API(TUPLEI_GET_CLEAN t, TUPLEI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_INIT(t, ...) M_APPLY_API(M_TUPL3_GET_INIT t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_INIT_SET(t, ...) M_APPLY_API(M_TUPL3_GET_INIT_SET t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_INIT_MOVE(t, ...) M_APPLY_API(M_TUPL3_GET_INIT_MOVE t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_MOVE(t, ...) M_APPLY_API(M_TUPL3_GET_MOVE t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_SET(t, ...) M_APPLY_API(M_TUPL3_GET_SET t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_CLEAR(t, ...) M_APPLY_API(M_TUPL3_GET_CLEAR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_CMP(t, ...) M_APPLY_API(M_TUPL3_GET_CMP t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_HASH(t, ...) M_APPLY_API(M_TUPL3_GET_HASH t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_EQUAL(t, ...) M_APPLY_API(M_TUPL3_GET_EQUAL t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_GET_STR(t, ...) M_APPLY_API(M_TUPL3_GET_STR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_OUT_STR(t, ...) M_APPLY_API(M_TUPL3_GET_OUT_STR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_IN_STR(t, ...) M_APPLY_API(M_TUPL3_GET_IN_STR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_PARSE_STR(t, ...) M_APPLY_API(M_TUPL3_GET_PARSE_STR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_OUT_SERIAL(t, ...) M_APPLY_API(M_TUPL3_GET_OUT_SERIAL t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_IN_SERIAL(t, ...) M_APPLY_API(M_TUPL3_GET_IN_SERIAL t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_SWAP(t, ...) M_APPLY_API(M_TUPL3_GET_SWAP t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_TUPL3_CALL_CLEAN(t, ...) M_APPLY_API(M_TUPL3_GET_CLEAN t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
||||
|
||||
|
||||
/* Define the type of a tuple */
|
||||
#define TUPLEI_DEFINE_TYPE(name, name_t, ...) \
|
||||
#define M_TUPL3_DEFINE_TYPE(name, name_t, ...) \
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_MAP(TUPLEI_DEFINE_RECUR_TYPE_ELE , __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_RECUR_TYPE_ELE , __VA_ARGS__) \
|
||||
} name_t[1]; \
|
||||
\
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
@@ -210,141 +210,141 @@ namespace m_lib {
|
||||
/* Define internal type for oplist */ \
|
||||
typedef name_t M_C(name, _ct);
|
||||
|
||||
#define TUPLEI_DEFINE_RECUR_TYPE_ELE(a) \
|
||||
TUPLEI_GET_TYPE a TUPLEI_GET_FIELD a ;
|
||||
#define M_TUPL3_DEFINE_RECUR_TYPE_ELE(a) \
|
||||
M_TUPL3_GET_TYPE a M_TUPL3_GET_FIELD a ;
|
||||
|
||||
/* Define the basic enumerate, identifying a parameter */
|
||||
#define TUPLEI_DEFINE_ENUM(name, ...) \
|
||||
#define M_TUPL3_DEFINE_ENUM(name, ...) \
|
||||
typedef enum { \
|
||||
M_C(name, _first_one_val), \
|
||||
M_MAP2_C(TUPLEI_DEFINE_ENUM_ELE , name, __VA_ARGS__) \
|
||||
M_MAP2_C(M_TUPL3_DEFINE_ENUM_ELE , name, __VA_ARGS__) \
|
||||
} M_C(name,_field_e);
|
||||
|
||||
#define TUPLEI_DEFINE_ENUM_ELE(name, a) \
|
||||
M_C4(name, _, TUPLEI_GET_FIELD a, _value)
|
||||
#define M_TUPL3_DEFINE_ENUM_ELE(name, a) \
|
||||
M_C4(name, _, M_TUPL3_GET_FIELD a, _value)
|
||||
|
||||
/* Control that all given oplists of all parameters are really oplists */
|
||||
#define TUPLEI_CONTROL_ALL_OPLIST(name, ...) \
|
||||
M_MAP2(TUPLEI_CONTROL_OPLIST, name, __VA_ARGS__)
|
||||
#define M_TUPL3_CONTROL_ALL_OPLIST(name, ...) \
|
||||
M_MAP2(M_TUPL3_CONTROL_OPLIST, name, __VA_ARGS__)
|
||||
|
||||
#define TUPLEI_CONTROL_OPLIST(name, a) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, TUPLEI_GET_FIELD a, \
|
||||
TUPLEI_GET_TYPE a, TUPLEI_GET_OPLIST a)
|
||||
#define M_TUPL3_CONTROL_OPLIST(name, a) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, M_TUPL3_GET_FIELD a, \
|
||||
M_TUPL3_GET_TYPE a, M_TUPL3_GET_OPLIST a)
|
||||
|
||||
/* Define the INIT method calling the INIT method for all params */
|
||||
#define TUPLEI_DEFINE_INIT(name, ...) \
|
||||
#define M_TUPL3_DEFINE_INIT(name, ...) \
|
||||
static inline void M_C(name, _init)(M_C(name,_ct) my) { \
|
||||
M_MAP(TUPLEI_DEFINE_INIT_FUNC , __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_INIT_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_INIT_FUNC(a) \
|
||||
TUPLEI_CALL_INIT(a, my -> TUPLEI_GET_FIELD a );
|
||||
#define M_TUPL3_DEFINE_INIT_FUNC(a) \
|
||||
M_TUPL3_CALL_INIT(a, my -> M_TUPL3_GET_FIELD a );
|
||||
|
||||
/* Define the INIT_SET method calling the INIT_SET method for all params */
|
||||
#define TUPLEI_DEFINE_INIT_SET(name, ...) \
|
||||
#define M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(org); \
|
||||
M_MAP(M_TUPL3_DEFINE_INIT_SET_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
#define TUPLEI_DEFINE_INIT_SET_FUNC(a) \
|
||||
TUPLEI_CALL_INIT_SET(a, my -> TUPLEI_GET_FIELD a , org -> TUPLEI_GET_FIELD a );
|
||||
#define M_TUPL3_DEFINE_INIT_SET_FUNC(a) \
|
||||
M_TUPL3_CALL_INIT_SET(a, my -> M_TUPL3_GET_FIELD a , org -> M_TUPL3_GET_FIELD a );
|
||||
|
||||
/* Define the INIT_WITH method calling the INIT_SET method for all params. */
|
||||
#define TUPLEI_DEFINE_INIT_SET2(name, ...) \
|
||||
#define M_TUPL3_DEFINE_INIT_SET2(name, ...) \
|
||||
static inline void M_C(name, _init_emplace)(M_C(name,_ct) my \
|
||||
M_MAP(TUPLEI_DEFINE_INIT_SET2_PROTO, __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_INIT_SET2_PROTO, __VA_ARGS__) \
|
||||
) { \
|
||||
M_MAP(TUPLEI_DEFINE_INIT_SET2_FUNC , __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_INIT_SET2_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_INIT_SET2_PROTO(a) \
|
||||
, TUPLEI_GET_TYPE a const TUPLEI_GET_FIELD a
|
||||
#define M_TUPL3_DEFINE_INIT_SET2_PROTO(a) \
|
||||
, M_TUPL3_GET_TYPE a const M_TUPL3_GET_FIELD a
|
||||
|
||||
#define TUPLEI_DEFINE_INIT_SET2_FUNC(a) \
|
||||
TUPLEI_CALL_INIT_SET(a, my -> TUPLEI_GET_FIELD a , TUPLEI_GET_FIELD a );
|
||||
#define M_TUPL3_DEFINE_INIT_SET2_FUNC(a) \
|
||||
M_TUPL3_CALL_INIT_SET(a, my -> M_TUPL3_GET_FIELD a , M_TUPL3_GET_FIELD a );
|
||||
|
||||
|
||||
/* Define the SET method calling the SET method for all params. */
|
||||
#define TUPLEI_DEFINE_SET(name, ...) \
|
||||
#define M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(my); \
|
||||
M_TUPL3_CONTRACT(org); \
|
||||
M_MAP(M_TUPL3_DEFINE_SET_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_SET_FUNC(a) \
|
||||
TUPLEI_CALL_SET(a, my -> TUPLEI_GET_FIELD a , org -> TUPLEI_GET_FIELD a );
|
||||
#define M_TUPL3_DEFINE_SET_FUNC(a) \
|
||||
M_TUPL3_CALL_SET(a, my -> M_TUPL3_GET_FIELD a , org -> M_TUPL3_GET_FIELD a );
|
||||
|
||||
|
||||
/* Define the SET_WITH method calling the SET method for all params. */
|
||||
#define TUPLEI_DEFINE_SET2(name, ...) \
|
||||
#define M_TUPL3_DEFINE_SET2(name, ...) \
|
||||
static inline void M_C(name, _emplace)(M_C(name,_ct) my \
|
||||
M_MAP(TUPLEI_DEFINE_SET2_PROTO, __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_SET2_PROTO, __VA_ARGS__) \
|
||||
) { \
|
||||
TUPLEI_CONTRACT(my); \
|
||||
M_MAP(TUPLEI_DEFINE_SET2_FUNC , __VA_ARGS__) \
|
||||
M_TUPL3_CONTRACT(my); \
|
||||
M_MAP(M_TUPL3_DEFINE_SET2_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
#define TUPLEI_DEFINE_SET2_PROTO(a) \
|
||||
, TUPLEI_GET_TYPE a const TUPLEI_GET_FIELD a
|
||||
#define M_TUPL3_DEFINE_SET2_PROTO(a) \
|
||||
, M_TUPL3_GET_TYPE a const M_TUPL3_GET_FIELD a
|
||||
|
||||
#define TUPLEI_DEFINE_SET2_FUNC(a) \
|
||||
TUPLEI_CALL_SET(a, my -> TUPLEI_GET_FIELD a , TUPLEI_GET_FIELD a );
|
||||
#define M_TUPL3_DEFINE_SET2_FUNC(a) \
|
||||
M_TUPL3_CALL_SET(a, my -> M_TUPL3_GET_FIELD a , M_TUPL3_GET_FIELD a );
|
||||
|
||||
|
||||
/* Define the CLEAR method calling the CLEAR method for all params. */
|
||||
#define TUPLEI_DEFINE_CLEAR(name, ...) \
|
||||
#define M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(my); \
|
||||
M_MAP(M_TUPL3_DEFINE_CLEAR_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_CLEAR_FUNC(a) \
|
||||
TUPLEI_CALL_CLEAR(a, my -> TUPLEI_GET_FIELD a );
|
||||
#define M_TUPL3_DEFINE_CLEAR_FUNC(a) \
|
||||
M_TUPL3_CALL_CLEAR(a, my -> M_TUPL3_GET_FIELD a );
|
||||
|
||||
|
||||
/* Define the GET_AT_field & CGET_AT methods for all params. */
|
||||
#define TUPLEI_DEFINE_GETTER_FIELD(name, ...) \
|
||||
M_MAP2(TUPLEI_DEFINE_GETTER_FIELD_PROTO, name, __VA_ARGS__)
|
||||
#define M_TUPL3_DEFINE_GETTER_FIELD(name, ...) \
|
||||
M_MAP2(M_TUPL3_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) \
|
||||
#define M_TUPL3_DEFINE_GETTER_FIELD_PROTO(name, a) \
|
||||
static inline M_TUPL3_GET_TYPE a * M_C3(name, _get_at_, M_TUPL3_GET_FIELD a) \
|
||||
(M_C(name,_ct) my) { \
|
||||
TUPLEI_CONTRACT(my); \
|
||||
return &(my->TUPLEI_GET_FIELD a); \
|
||||
M_TUPL3_CONTRACT(my); \
|
||||
return &(my->M_TUPL3_GET_FIELD a); \
|
||||
} \
|
||||
static inline TUPLEI_GET_TYPE a const * M_C3(name, _cget_at_, TUPLEI_GET_FIELD a) \
|
||||
static inline M_TUPL3_GET_TYPE a const * M_C3(name, _cget_at_, M_TUPL3_GET_FIELD a) \
|
||||
(M_C(name,_ct) const my) { \
|
||||
TUPLEI_CONTRACT(my); \
|
||||
return &(my->TUPLEI_GET_FIELD a); \
|
||||
M_TUPL3_CONTRACT(my); \
|
||||
return &(my->M_TUPL3_GET_FIELD a); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the SET_field methods for all params. */
|
||||
#define TUPLEI_DEFINE_SETTER_FIELD(name, ...) \
|
||||
M_MAP2(TUPLEI_DEFINE_SETTER_FIELD_PROTO, name, __VA_ARGS__)
|
||||
#define M_TUPL3_DEFINE_SETTER_FIELD(name, ...) \
|
||||
M_MAP2(M_TUPL3_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 M_TUPL3_DEFINE_SETTER_FIELD_PROTO(name, a) \
|
||||
static inline void M_C3(name, _set_, M_TUPL3_GET_FIELD a) \
|
||||
(M_C(name,_ct) my, M_TUPL3_GET_TYPE a const M_TUPL3_GET_FIELD a) { \
|
||||
M_TUPL3_CONTRACT(my); \
|
||||
M_TUPL3_CALL_SET(a, my ->M_TUPL3_GET_FIELD a, M_TUPL3_GET_FIELD a); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the CMP method by calling CMP methods for all params. */
|
||||
#define TUPLEI_DEFINE_CMP(name, ...) \
|
||||
#define M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(e1); \
|
||||
M_TUPL3_CONTRACT(e2); \
|
||||
M_MAP(M_TUPL3_DEFINE_CMP_FUNC , __VA_ARGS__) \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_CMP_FUNC(a) \
|
||||
i = TUPLEI_CALL_CMP(a, e1 -> TUPLEI_GET_FIELD a , e2 -> TUPLEI_GET_FIELD a ); \
|
||||
#define M_TUPL3_DEFINE_CMP_FUNC(a) \
|
||||
i = M_TUPL3_CALL_CMP(a, e1 -> M_TUPL3_GET_FIELD a , e2 -> M_TUPL3_GET_FIELD a ); \
|
||||
if (i != 0) return i;
|
||||
|
||||
|
||||
@@ -352,150 +352,150 @@ namespace m_lib {
|
||||
In the right order
|
||||
FIXME: _cmp_order is not supported by algorithm yet.
|
||||
*/
|
||||
#define TUPLEI_DEFINE_CMP_ORDER(name, ...) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CONTRACT(e1); \
|
||||
M_TUPL3_CONTRACT(e2); \
|
||||
while (true) { \
|
||||
i=*order++; \
|
||||
switch (i) { \
|
||||
case 0: return 0; \
|
||||
M_MAP2(TUPLEI_DEFINE_CMP_ORDER_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_TUPL3_DEFINE_CMP_ORDER_FUNC , name, __VA_ARGS__) \
|
||||
default: M_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): \
|
||||
r = TUPLEI_CALL_CMP(a, e1 -> TUPLEI_GET_FIELD a , e2 -> TUPLEI_GET_FIELD a ); \
|
||||
#define M_TUPL3_DEFINE_CMP_ORDER_FUNC(name, a) \
|
||||
case M_C4(name, _, M_TUPL3_GET_FIELD a, _value): \
|
||||
case -M_C4(name, _, M_TUPL3_GET_FIELD a, _value): \
|
||||
r = M_TUPL3_CALL_CMP(a, e1 -> M_TUPL3_GET_FIELD a , e2 -> M_TUPL3_GET_FIELD a ); \
|
||||
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, ...) \
|
||||
M_MAP2(TUPLEI_MAP_CMP_FIELD, name, __VA_ARGS__)
|
||||
#define M_TUPL3_DEFINE_CMP_FIELD(name, ...) \
|
||||
M_MAP2(M_TUPL3_MAP_CMP_FIELD, name, __VA_ARGS__)
|
||||
|
||||
#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 M_TUPL3_MAP_CMP_FIELD(name, a) \
|
||||
M_IF_METHOD(CMP, M_TUPL3_GET_OPLIST a)( \
|
||||
M_TUPL3_DEFINE_CMP_FIELD_FUNC(name, M_TUPL3_GET_FIELD a, M_TUPL3_GET_CMP a), \
|
||||
)
|
||||
|
||||
#define TUPLEI_DEFINE_CMP_FIELD_FUNC(name, field, func_cmp) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CONTRACT(e1); \
|
||||
M_TUPL3_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, ...) \
|
||||
#define M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(e1); \
|
||||
M_TUPL3_CONTRACT(e2); \
|
||||
M_MAP(M_TUPL3_DEFINE_EQUAL_FUNC , __VA_ARGS__) \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_EQUAL_FUNC(a) \
|
||||
b = TUPLEI_CALL_EQUAL(a, e1 -> TUPLEI_GET_FIELD a , e2 -> TUPLEI_GET_FIELD a ); \
|
||||
#define M_TUPL3_DEFINE_EQUAL_FUNC(a) \
|
||||
b = M_TUPL3_CALL_EQUAL(a, e1 -> M_TUPL3_GET_FIELD a , e2 -> M_TUPL3_GET_FIELD a ); \
|
||||
if (!b) return false;
|
||||
|
||||
|
||||
/* Define a HASH method by calling the HASH methods for all params */
|
||||
#define TUPLEI_DEFINE_HASH(name, ...) \
|
||||
#define M_TUPL3_DEFINE_HASH(name, ...) \
|
||||
static inline size_t M_C(name, _hash)(M_C(name,_ct) const e1) { \
|
||||
TUPLEI_CONTRACT(e1); \
|
||||
M_TUPL3_CONTRACT(e1); \
|
||||
M_HASH_DECL(hash); \
|
||||
M_MAP(TUPLEI_DEFINE_HASH_FUNC , __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_HASH_FUNC , __VA_ARGS__) \
|
||||
return M_HASH_FINAL (hash); \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_HASH_FUNC(a) \
|
||||
M_HASH_UP(hash, TUPLEI_CALL_HASH(a, e1 -> TUPLEI_GET_FIELD a) );
|
||||
#define M_TUPL3_DEFINE_HASH_FUNC(a) \
|
||||
M_HASH_UP(hash, M_TUPL3_CALL_HASH(a, e1 -> M_TUPL3_GET_FIELD a) );
|
||||
|
||||
|
||||
/* Define a GET_STR method by calling the GET_STR methods for all params */
|
||||
#define TUPLEI_DEFINE_GET_STR(name, ...) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CONTRACT(el); \
|
||||
M_ASSERT (str != NULL); \
|
||||
(append ? string_cat_str : string_set_str) (str, "("); \
|
||||
M_MAP(TUPLEI_DEFINE_GET_STR_FUNC , __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_GET_STR_FUNC , __VA_ARGS__) \
|
||||
string_push_back (str, ')'); \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_GET_STR_FUNC(a) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CALL_GET_STR(a, str, el -> M_TUPL3_GET_FIELD a, true); \
|
||||
|
||||
|
||||
/* Define a OUT_STR method by calling the OUT_STR methods for all params */
|
||||
#define TUPLEI_DEFINE_OUT_STR(name, ...) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CONTRACT(el); \
|
||||
M_ASSERT (f != NULL); \
|
||||
fputc('(', f); \
|
||||
M_MAP(TUPLEI_DEFINE_OUT_STR_FUNC , __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_OUT_STR_FUNC , __VA_ARGS__) \
|
||||
fputc (')', f); \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_OUT_STR_FUNC(a) \
|
||||
#define M_TUPL3_DEFINE_OUT_STR_FUNC(a) \
|
||||
if (comma) fputc (',', f); \
|
||||
comma = true; \
|
||||
TUPLEI_CALL_OUT_STR(a, f, el -> TUPLEI_GET_FIELD a); \
|
||||
M_TUPL3_CALL_OUT_STR(a, f, el -> M_TUPL3_GET_FIELD a); \
|
||||
|
||||
|
||||
/* Define a IN_STR method by calling the IN_STR methods for all params */
|
||||
#define TUPLEI_DEFINE_IN_STR(name, ...) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CONTRACT(el); \
|
||||
M_ASSERT (f != NULL); \
|
||||
int c = fgetc(f); \
|
||||
if (c != '(') return false; \
|
||||
M_MAP(TUPLEI_DEFINE_IN_STR_FUNC , __VA_ARGS__) \
|
||||
M_MAP(M_TUPL3_DEFINE_IN_STR_FUNC , __VA_ARGS__) \
|
||||
c = fgetc(f); \
|
||||
return (c == ')'); \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_IN_STR_FUNC(a) \
|
||||
#define M_TUPL3_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) \
|
||||
if (M_TUPL3_CALL_IN_STR(a, el -> M_TUPL3_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, ...) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CONTRACT(el); \
|
||||
M_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__) \
|
||||
M_MAP(M_TUPL3_DEFINE_PARSE_STR_FUNC , __VA_ARGS__) \
|
||||
c = *str++; \
|
||||
success = (c == ')'); \
|
||||
exit: \
|
||||
@@ -503,58 +503,58 @@ namespace m_lib {
|
||||
return success; \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_PARSE_STR_FUNC(a) \
|
||||
#define M_TUPL3_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) \
|
||||
if (M_TUPL3_CALL_PARSE_STR(a, el -> M_TUPL3_GET_FIELD a, str, &str) == false) \
|
||||
goto exit ; \
|
||||
|
||||
|
||||
/* Return the parameter name as a C string */
|
||||
#define TUPLEI_STRINGIFY_NAME(a) \
|
||||
M_AS_STR(TUPLEI_GET_FIELD a)
|
||||
#define M_TUPL3_STRINGIFY_NAME(a) \
|
||||
M_AS_STR(M_TUPL3_GET_FIELD a)
|
||||
|
||||
|
||||
/* Define a OUT_SERIAL method by calling the OUT_SERIAL methods for all params */
|
||||
#define TUPLEI_DEFINE_OUT_SERIAL(name, ...) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CONTRACT(el); \
|
||||
M_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__) }; \
|
||||
{ M_REDUCE(M_TUPL3_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__) \
|
||||
M_MAP(M_TUPL3_DEFINE_OUT_SERIAL_FUNC , __VA_ARGS__) \
|
||||
M_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) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CALL_OUT_SERIAL(a, f, el -> M_TUPL3_GET_FIELD a); \
|
||||
index++; \
|
||||
|
||||
|
||||
/* Define a IN_SERIAL method by calling the IN_SERIAL methods for all params */
|
||||
#define TUPLEI_DEFINE_IN_SERIAL(name, ...) \
|
||||
#define M_TUPL3_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); \
|
||||
M_TUPL3_CONTRACT(el); \
|
||||
M_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_REDUCE(M_TUPL3_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); \
|
||||
@@ -563,7 +563,7 @@ namespace m_lib {
|
||||
if (ret == M_SERIAL_OK_CONTINUE) { \
|
||||
M_ASSERT (index >= 0 && index < field_max); \
|
||||
switch (1+index) { \
|
||||
M_MAP2(TUPLEI_DEFINE_IN_SERIAL_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_TUPL3_DEFINE_IN_SERIAL_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(0); \
|
||||
} \
|
||||
ret = (ret == M_SERIAL_OK_DONE) ? M_SERIAL_OK_CONTINUE : M_SERIAL_FAIL; \
|
||||
@@ -572,82 +572,82 @@ namespace m_lib {
|
||||
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); \
|
||||
#define M_TUPL3_DEFINE_IN_SERIAL_FUNC(name, a) \
|
||||
case M_C4(name, _, M_TUPL3_GET_FIELD a, _value): \
|
||||
ret = M_TUPL3_CALL_IN_SERIAL(a, el -> M_TUPL3_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 M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(el); \
|
||||
M_MAP(M_TUPL3_DEFINE_INIT_MOVE_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_INIT_MOVE_FUNC(a) \
|
||||
TUPLEI_CALL_INIT_MOVE(a, el -> TUPLEI_GET_FIELD a, org -> TUPLEI_GET_FIELD a);
|
||||
#define M_TUPL3_DEFINE_INIT_MOVE_FUNC(a) \
|
||||
M_TUPL3_CALL_INIT_MOVE(a, el -> M_TUPL3_GET_FIELD a, org -> M_TUPL3_GET_FIELD a);
|
||||
|
||||
|
||||
/* Define a MOVE method by calling the MOVE methods for all params */
|
||||
#define TUPLEI_DEFINE_MOVE(name, ...) \
|
||||
#define M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(el); \
|
||||
M_MAP(M_TUPL3_DEFINE_MOVE_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_MOVE_FUNC(a) \
|
||||
TUPLEI_CALL_MOVE(a, el -> TUPLEI_GET_FIELD a, org -> TUPLEI_GET_FIELD a);
|
||||
#define M_TUPL3_DEFINE_MOVE_FUNC(a) \
|
||||
M_TUPL3_CALL_MOVE(a, el -> M_TUPL3_GET_FIELD a, org -> M_TUPL3_GET_FIELD a);
|
||||
|
||||
|
||||
/* Define a SWAP method by calling the SWAP methods for all params */
|
||||
#define TUPLEI_DEFINE_SWAP(name, ...) \
|
||||
#define M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(el1); \
|
||||
M_TUPL3_CONTRACT(el2); \
|
||||
M_MAP(M_TUPL3_DEFINE_SWAP_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_SWAP_FUNC(a) \
|
||||
TUPLEI_CALL_SWAP(a, el1 -> TUPLEI_GET_FIELD a, el2 -> TUPLEI_GET_FIELD a);
|
||||
#define M_TUPL3_DEFINE_SWAP_FUNC(a) \
|
||||
M_TUPL3_CALL_SWAP(a, el1 -> M_TUPL3_GET_FIELD a, el2 -> M_TUPL3_GET_FIELD a);
|
||||
|
||||
|
||||
/* Define a CLEAN method by calling the CLEAN methods for all params */
|
||||
#define TUPLEI_DEFINE_CLEAN(name, ...) \
|
||||
#define M_TUPL3_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__) \
|
||||
M_TUPL3_CONTRACT(el1); \
|
||||
M_MAP(M_TUPL3_DEFINE_CLEAN_FUNC , __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define TUPLEI_DEFINE_CLEAN_FUNC(a) \
|
||||
TUPLEI_CALL_CLEAN(a, el1 -> TUPLEI_GET_FIELD a);
|
||||
#define M_TUPL3_DEFINE_CLEAN_FUNC(a) \
|
||||
M_TUPL3_CALL_CLEAN(a, el1 -> M_TUPL3_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) \
|
||||
M_APPLY(TUPLEI_TEST_METHOD2_P, method, M_OPFLAT trio)
|
||||
#define M_TUPL3_TEST_METHOD_P(method, trio) \
|
||||
M_APPLY(M_TUPL3_TEST_METHOD2_P, method, M_OPFLAT trio)
|
||||
|
||||
#define TUPLEI_TEST_METHOD2_P(method, f, t, op) \
|
||||
#define M_TUPL3_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, ...) \
|
||||
M_IF(M_REDUCE2(TUPLEI_TEST_METHOD_P, M_AND, method, __VA_ARGS__))
|
||||
#define M_TUPL3_IF_ALL(method, ...) \
|
||||
M_IF(M_REDUCE2(M_TUPL3_TEST_METHOD_P, M_AND, method, __VA_ARGS__))
|
||||
|
||||
// deferred evaluation
|
||||
#define TUPLEI_OPLIST_P1(arg) TUPLEI_OPLIST_P2 arg
|
||||
#define M_TUPL3_OPLIST_P1(arg) M_TUPL3_OPLIST_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#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__)
|
||||
#define M_TUPL3_OPLIST_P2(name, ...) \
|
||||
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(M_TUPL3_OPLIST_P3, M_TUPL3_OPLIST_FAILURE)(name, __VA_ARGS__)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define TUPLEI_OPLIST_FAILURE(name, ...) \
|
||||
((M_LIB_ERROR(ONE_ARGUMENT_OF_TUPLEI_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__)))
|
||||
#define M_TUPL3_OPLIST_FAILURE(name, ...) \
|
||||
((M_LIB_ERROR(ONE_ARGUMENT_OF_M_TUPL3_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__)))
|
||||
|
||||
/* Define the TUPLE oplist */
|
||||
#define TUPLEI_OPLIST_P3(name, ...) \
|
||||
#define M_TUPL3_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_emplace)), \
|
||||
|
||||
+277
-277
@@ -43,7 +43,7 @@
|
||||
VARIANT_DEF2_AS(name, name_t, [(field1, type1, oplist1), (field2, type2, oplist2), ...] ) */
|
||||
#define VARIANT_DEF2_AS(name, name_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
VARIANTI_DEF2_P1( (name, name_t VARIANTI_INJECT_GLOBAL(__VA_ARGS__)) ) \
|
||||
M_VAR1ANT_DEF2_P1( (name, name_t M_VAR1ANT_INJECT_GLOBAL(__VA_ARGS__)) ) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -51,138 +51,138 @@
|
||||
USAGE: VARIANT_OPLIST(name[, oplist of the first type, ...]) */
|
||||
#define VARIANT_OPLIST(...) \
|
||||
M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
(VARIANTI_OPLIST_P1((__VA_ARGS__, M_DEFAULT_OPLIST)), \
|
||||
VARIANTI_OPLIST_P1((__VA_ARGS__ )))
|
||||
(M_VAR1ANT_OPLIST_P1((__VA_ARGS__, M_DEFAULT_OPLIST)), \
|
||||
M_VAR1ANT_OPLIST_P1((__VA_ARGS__ )))
|
||||
|
||||
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
/* Contract of a variant. */
|
||||
#define VARIANTI_CONTRACT(name, my) do { \
|
||||
#define M_VAR1ANT_CONTRACT(name, my) do { \
|
||||
M_ASSERT(my != NULL); \
|
||||
M_ASSERT(my->type >= M_C(name, _EMPTY)); \
|
||||
M_ASSERT(my->type <= (enum M_C(name, _enum)) M_C(name, _MAX_TYPE)); \
|
||||
} while (0)
|
||||
|
||||
/* Inject the oplist within the list of arguments */
|
||||
#define VARIANTI_INJECT_GLOBAL(...) \
|
||||
M_MAP(VARIANTI_INJECT_OPLIST_A, __VA_ARGS__)
|
||||
#define M_VAR1ANT_INJECT_GLOBAL(...) \
|
||||
M_MAP(M_VAR1ANT_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 VARIANTI_INJECT_OPLIST_A( duo_or_trio ) \
|
||||
VARIANTI_INJECT_OPLIST_B duo_or_trio
|
||||
#define M_VAR1ANT_INJECT_OPLIST_A( duo_or_trio ) \
|
||||
M_VAR1ANT_INJECT_OPLIST_B duo_or_trio
|
||||
|
||||
#define VARIANTI_INJECT_OPLIST_B( f, ... ) \
|
||||
#define M_VAR1ANT_INJECT_OPLIST_B( f, ... ) \
|
||||
M_DEFERRED_COMMA \
|
||||
M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) )
|
||||
|
||||
// Deferred evaluation
|
||||
#define VARIANTI_DEF2_P1(...) VARIANTI_DEF2_P2 __VA_ARGS__
|
||||
#define M_VAR1ANT_DEF2_P1(...) M_VAR1ANT_DEF2_P2 __VA_ARGS__
|
||||
|
||||
// Test if all third argument of all arguments is an oplist
|
||||
#define VARIANTI_IF_ALL_OPLIST(...) \
|
||||
M_IF(M_REDUCE(VARIANTI_IS_OPLIST_P, M_AND, __VA_ARGS__))
|
||||
#define M_VAR1ANT_IF_ALL_OPLIST(...) \
|
||||
M_IF(M_REDUCE(M_VAR1ANT_IS_OPLIST_P, M_AND, __VA_ARGS__))
|
||||
|
||||
// Test if the third argument is an oplist
|
||||
#define VARIANTI_IS_OPLIST_P(a) \
|
||||
#define M_VAR1ANT_IS_OPLIST_P(a) \
|
||||
M_OPLIST_P(M_RET_ARG3 a)
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define VARIANTI_DEF2_P2(name, name_t, ...) \
|
||||
VARIANTI_IF_ALL_OPLIST(__VA_ARGS__)(VARIANTI_DEF2_P3, VARIANTI_DEF2_FAILURE)(name, name_t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_DEF2_P2(name, name_t, ...) \
|
||||
M_VAR1ANT_IF_ALL_OPLIST(__VA_ARGS__)(M_VAR1ANT_DEF2_P3, M_VAR1ANT_DEF2_FAILURE)(name, name_t, __VA_ARGS__)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define VARIANTI_DEF2_FAILURE(name, name_t, ...) \
|
||||
#define M_VAR1ANT_DEF2_FAILURE(name, name_t, ...) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(VARIANT_DEF2): at least one of the given argument is not a valid oplist: " #__VA_ARGS__)
|
||||
|
||||
/* Define the variant */
|
||||
#define VARIANTI_DEF2_P3(name, name_t, ...) \
|
||||
VARIANTI_DEFINE_TYPE(name, name_t, __VA_ARGS__) \
|
||||
VARIANTI_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
|
||||
VARIANTI_DEFINE_INIT(name, __VA_ARGS__) \
|
||||
VARIANTI_DEFINE_CLEAR(name, __VA_ARGS__) \
|
||||
VARIANTI_DEFINE_INIT_SET(name, __VA_ARGS__) \
|
||||
VARIANTI_DEFINE_SET(name, __VA_ARGS__) \
|
||||
VARIANTI_DEFINE_TEST_P(name, __VA_ARGS__) \
|
||||
VARIANTI_IF_ALL(INIT, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_INIT_FIELD(name, __VA_ARGS__),) \
|
||||
VARIANTI_DEFINE_INIT_SETTER_FIELD(name, __VA_ARGS__) \
|
||||
VARIANTI_DEFINE_SETTER_FIELD(name, __VA_ARGS__) \
|
||||
VARIANTI_DEFINE_GETTER_FIELD(name, __VA_ARGS__) \
|
||||
VARIANTI_DEFINE_CLEAN_FUNC(name, __VA_ARGS__) \
|
||||
VARIANTI_IF_ALL(HASH, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_HASH(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(EQUAL, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_EQUAL(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(GET_STR, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_GET_STR(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL2(PARSE_STR, INIT, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_PARSE_STR(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(OUT_STR, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_OUT_STR(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL2(IN_STR, INIT, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_IN_STR(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(OUT_SERIAL, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_OUT_SERIAL(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL2(IN_SERIAL, INIT, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_IN_SERIAL(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_INIT_MOVE(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_MOVE(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_MOVER(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(SWAP, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_SWAP(name, __VA_ARGS__),)
|
||||
#define M_VAR1ANT_DEF2_P3(name, name_t, ...) \
|
||||
M_VAR1ANT_DEFINE_TYPE(name, name_t, __VA_ARGS__) \
|
||||
M_VAR1ANT_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_DEFINE_INIT(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_DEFINE_CLEAR(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_DEFINE_INIT_SET(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_DEFINE_SET(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_DEFINE_TEST_P(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_IF_ALL(INIT, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_INIT_FIELD(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_DEFINE_INIT_SETTER_FIELD(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_DEFINE_SETTER_FIELD(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_DEFINE_GETTER_FIELD(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_DEFINE_CLEAN_FUNC(name, __VA_ARGS__) \
|
||||
M_VAR1ANT_IF_ALL(HASH, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_HASH(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL(EQUAL, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_EQUAL(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL(GET_STR, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_GET_STR(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL2(PARSE_STR, INIT, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_PARSE_STR(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL(OUT_STR, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_OUT_STR(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL2(IN_STR, INIT, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_IN_STR(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL(OUT_SERIAL, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_OUT_SERIAL(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL2(IN_SERIAL, INIT, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_IN_SERIAL(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_INIT_MOVE(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_MOVE(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_MOVER(name, __VA_ARGS__),) \
|
||||
M_VAR1ANT_IF_ALL(SWAP, __VA_ARGS__) \
|
||||
(M_VAR1ANT_DEFINE_SWAP(name, __VA_ARGS__),)
|
||||
|
||||
|
||||
/* Get the field name, the type, the oplist or the methods
|
||||
based on the variant (field, type, oplist) */
|
||||
#define VARIANTI_GET_FIELD(f,t,o) f
|
||||
#define VARIANTI_GET_TYPE(f,t,o) t
|
||||
#define VARIANTI_GET_OPLIST(f,t,o) o
|
||||
#define VARIANTI_GET_INIT(f,t,o) M_GET_INIT o
|
||||
#define VARIANTI_GET_INIT_SET(f,t,o) M_GET_INIT_SET o
|
||||
#define VARIANTI_GET_INIT_MOVE(f,t,o) M_GET_INIT_MOVE o
|
||||
#define VARIANTI_GET_MOVE(f,t,o) M_GET_MOVE o
|
||||
#define VARIANTI_GET_SET(f,t,o) M_GET_SET o
|
||||
#define VARIANTI_GET_CLEAR(f,t,o) M_GET_CLEAR o
|
||||
#define VARIANTI_GET_CMP(f,t,o) M_GET_CMP o
|
||||
#define VARIANTI_GET_HASH(f,t,o) M_GET_HASH o
|
||||
#define VARIANTI_GET_EQUAL(f,t,o) M_GET_EQUAL o
|
||||
#define VARIANTI_GET_STR(f,t,o) M_GET_GET_STR o
|
||||
#define VARIANTI_GET_PARSE_STR(f,t,o) M_GET_PARSE_STR o
|
||||
#define VARIANTI_GET_OUT_STR(f,t,o) M_GET_OUT_STR o
|
||||
#define VARIANTI_GET_IN_STR(f,t,o) M_GET_IN_STR o
|
||||
#define VARIANTI_GET_OUT_SERIAL(f,t,o) M_GET_OUT_SERIAL o
|
||||
#define VARIANTI_GET_IN_SERIAL(f,t,o) M_GET_IN_SERIAL o
|
||||
#define VARIANTI_GET_SWAP(f,t,o) M_GET_SWAP o
|
||||
#define M_VAR1ANT_GET_FIELD(f,t,o) f
|
||||
#define M_VAR1ANT_GET_TYPE(f,t,o) t
|
||||
#define M_VAR1ANT_GET_OPLIST(f,t,o) o
|
||||
#define M_VAR1ANT_GET_INIT(f,t,o) M_GET_INIT o
|
||||
#define M_VAR1ANT_GET_INIT_SET(f,t,o) M_GET_INIT_SET o
|
||||
#define M_VAR1ANT_GET_INIT_MOVE(f,t,o) M_GET_INIT_MOVE o
|
||||
#define M_VAR1ANT_GET_MOVE(f,t,o) M_GET_MOVE o
|
||||
#define M_VAR1ANT_GET_SET(f,t,o) M_GET_SET o
|
||||
#define M_VAR1ANT_GET_CLEAR(f,t,o) M_GET_CLEAR o
|
||||
#define M_VAR1ANT_GET_CMP(f,t,o) M_GET_CMP o
|
||||
#define M_VAR1ANT_GET_HASH(f,t,o) M_GET_HASH o
|
||||
#define M_VAR1ANT_GET_EQUAL(f,t,o) M_GET_EQUAL o
|
||||
#define M_VAR1ANT_GET_STR(f,t,o) M_GET_GET_STR o
|
||||
#define M_VAR1ANT_GET_PARSE_STR(f,t,o) M_GET_PARSE_STR o
|
||||
#define M_VAR1ANT_GET_OUT_STR(f,t,o) M_GET_OUT_STR o
|
||||
#define M_VAR1ANT_GET_IN_STR(f,t,o) M_GET_IN_STR o
|
||||
#define M_VAR1ANT_GET_OUT_SERIAL(f,t,o) M_GET_OUT_SERIAL o
|
||||
#define M_VAR1ANT_GET_IN_SERIAL(f,t,o) M_GET_IN_SERIAL o
|
||||
#define M_VAR1ANT_GET_SWAP(f,t,o) M_GET_SWAP o
|
||||
|
||||
/* Call the methods through API */
|
||||
#define VARIANTI_CALL_INIT(t, ...) M_APPLY_API(VARIANTI_GET_INIT t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_INIT_SET(t, ...) M_APPLY_API(VARIANTI_GET_INIT_SET t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_INIT_MOVE(t, ...) M_APPLY_API(VARIANTI_GET_INIT_MOVE t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_MOVE(t, ...) M_APPLY_API(VARIANTI_GET_MOVE t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_SET(t, ...) M_APPLY_API(VARIANTI_GET_SET t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_CLEAR(t, ...) M_APPLY_API(VARIANTI_GET_CLEAR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_CMP(t, ...) M_APPLY_API(VARIANTI_GET_CMP t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_HASH(t, ...) M_APPLY_API(VARIANTI_GET_HASH t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_EQUAL(t, ...) M_APPLY_API(VARIANTI_GET_EQUAL t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_GET_STR(t, ...) M_APPLY_API(VARIANTI_GET_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_PARSE_STR(t, ...) M_APPLY_API(VARIANTI_GET_PARSE_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_OUT_STR(t, ...) M_APPLY_API(VARIANTI_GET_OUT_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_IN_STR(t, ...) M_APPLY_API(VARIANTI_GET_IN_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_OUT_SERIAL(t, ...) M_APPLY_API(VARIANTI_GET_OUT_SERIAL t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_IN_SERIAL(t, ...) M_APPLY_API(VARIANTI_GET_IN_SERIAL t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_SWAP(t, ...) M_APPLY_API(VARIANTI_GET_SWAP t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_INIT(t, ...) M_APPLY_API(M_VAR1ANT_GET_INIT t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_INIT_SET(t, ...) M_APPLY_API(M_VAR1ANT_GET_INIT_SET t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_INIT_MOVE(t, ...) M_APPLY_API(M_VAR1ANT_GET_INIT_MOVE t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_MOVE(t, ...) M_APPLY_API(M_VAR1ANT_GET_MOVE t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_SET(t, ...) M_APPLY_API(M_VAR1ANT_GET_SET t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_CLEAR(t, ...) M_APPLY_API(M_VAR1ANT_GET_CLEAR t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_CMP(t, ...) M_APPLY_API(M_VAR1ANT_GET_CMP t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_HASH(t, ...) M_APPLY_API(M_VAR1ANT_GET_HASH t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_EQUAL(t, ...) M_APPLY_API(M_VAR1ANT_GET_EQUAL t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_GET_STR(t, ...) M_APPLY_API(M_VAR1ANT_GET_STR t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_PARSE_STR(t, ...) M_APPLY_API(M_VAR1ANT_GET_PARSE_STR t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_OUT_STR(t, ...) M_APPLY_API(M_VAR1ANT_GET_OUT_STR t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_IN_STR(t, ...) M_APPLY_API(M_VAR1ANT_GET_IN_STR t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_OUT_SERIAL(t, ...) M_APPLY_API(M_VAR1ANT_GET_OUT_SERIAL t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_IN_SERIAL(t, ...) M_APPLY_API(M_VAR1ANT_GET_IN_SERIAL t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CALL_SWAP(t, ...) M_APPLY_API(M_VAR1ANT_GET_SWAP t, M_VAR1ANT_GET_OPLIST t, __VA_ARGS__)
|
||||
|
||||
/* Define the type */
|
||||
#define VARIANTI_DEFINE_TYPE(name, name_t, ...) \
|
||||
#define M_VAR1ANT_DEFINE_TYPE(name, name_t, ...) \
|
||||
/* Define enum of all types of the variant */ \
|
||||
enum M_C(name, _enum) { M_C(name, _EMPTY) \
|
||||
M_MAP2(VARIANTI_DEFINE_UNION_ELE, name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_UNION_ELE, name, __VA_ARGS__) \
|
||||
}; \
|
||||
/* Define enum equal to the number of types of the variant */ \
|
||||
enum M_C(name, _enum_max) { \
|
||||
@@ -192,7 +192,7 @@
|
||||
typedef struct M_C(name, _s) { \
|
||||
enum M_C(name, _enum) type; \
|
||||
union { \
|
||||
M_MAP(VARIANTI_DEFINE_TYPE_ELE , __VA_ARGS__) \
|
||||
M_MAP(M_VAR1ANT_DEFINE_TYPE_ELE , __VA_ARGS__) \
|
||||
} value; \
|
||||
} name_t[1]; \
|
||||
\
|
||||
@@ -201,55 +201,55 @@
|
||||
/* Define internal type for oplist */ \
|
||||
typedef name_t M_C(name, _ct);
|
||||
|
||||
#define VARIANTI_DEFINE_UNION_ELE(name, a) \
|
||||
, M_C4(name, _, VARIANTI_GET_FIELD a, _value)
|
||||
#define M_VAR1ANT_DEFINE_UNION_ELE(name, a) \
|
||||
, M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value)
|
||||
|
||||
#define VARIANTI_DEFINE_TYPE_ELE(a) \
|
||||
VARIANTI_GET_TYPE a VARIANTI_GET_FIELD a ;
|
||||
#define M_VAR1ANT_DEFINE_TYPE_ELE(a) \
|
||||
M_VAR1ANT_GET_TYPE a M_VAR1ANT_GET_FIELD a ;
|
||||
|
||||
|
||||
/* Control that all given oplists of all parameters are really oplists */
|
||||
#define VARIANTI_CONTROL_ALL_OPLIST(name, ...) \
|
||||
M_MAP2(VARIANTI_CONTROL_OPLIST, name, __VA_ARGS__)
|
||||
#define M_VAR1ANT_CONTROL_ALL_OPLIST(name, ...) \
|
||||
M_MAP2(M_VAR1ANT_CONTROL_OPLIST, name, __VA_ARGS__)
|
||||
|
||||
#define VARIANTI_CONTROL_OPLIST(name, a) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, VARIANTI_GET_FIELD a, \
|
||||
VARIANTI_GET_TYPE a, VARIANTI_GET_OPLIST a)
|
||||
#define M_VAR1ANT_CONTROL_OPLIST(name, a) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, M_VAR1ANT_GET_FIELD a, \
|
||||
M_VAR1ANT_GET_TYPE a, M_VAR1ANT_GET_OPLIST a)
|
||||
|
||||
|
||||
/* Define the INIT function. Init the variant to empty */
|
||||
#define VARIANTI_DEFINE_INIT(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_INIT(name, ...) \
|
||||
static inline void M_C(name, _init)(M_C(name,_ct) my) { \
|
||||
my->type = M_C(name, _EMPTY); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the INIT_SET function. */
|
||||
#define VARIANTI_DEFINE_INIT_SET(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_INIT_SET(name, ...) \
|
||||
static inline void M_C(name, _init_set)(M_C(name,_ct) my , \
|
||||
M_C(name,_ct) const org) { \
|
||||
VARIANTI_CONTRACT(name, org); \
|
||||
M_VAR1ANT_CONTRACT(name, org); \
|
||||
my->type = org->type; \
|
||||
switch (org->type) { \
|
||||
case M_C(name, _EMPTY): break; \
|
||||
M_MAP2(VARIANTI_DEFINE_INIT_SET_FUNC, name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_INIT_SET_FUNC, name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_INIT_SET_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
VARIANTI_CALL_INIT_SET(a, my -> value. VARIANTI_GET_FIELD a , \
|
||||
org -> value.VARIANTI_GET_FIELD a ); \
|
||||
#define M_VAR1ANT_DEFINE_INIT_SET_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
M_VAR1ANT_CALL_INIT_SET(a, my -> value. M_VAR1ANT_GET_FIELD a , \
|
||||
org -> value.M_VAR1ANT_GET_FIELD a ); \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the SET function. */
|
||||
#define VARIANTI_DEFINE_SET(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_SET(name, ...) \
|
||||
static inline void M_C(name, _set)(M_C(name,_ct) my , \
|
||||
M_C(name,_ct) const org) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
VARIANTI_CONTRACT(name, org); \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
M_VAR1ANT_CONTRACT(name, org); \
|
||||
if (my->type != org->type) { \
|
||||
/* Different types: clear previous one and create new */ \
|
||||
M_C(name, _clear)(my); \
|
||||
@@ -258,193 +258,193 @@
|
||||
/* Same type: optimize the set */ \
|
||||
switch (org->type) { \
|
||||
case M_C(name, _EMPTY): break; \
|
||||
M_MAP2(VARIANTI_DEFINE_SET_FUNC, name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_SET_FUNC, name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_SET_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
VARIANTI_CALL_SET(a, my -> value. VARIANTI_GET_FIELD a , \
|
||||
org -> value.VARIANTI_GET_FIELD a ); \
|
||||
#define M_VAR1ANT_DEFINE_SET_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
M_VAR1ANT_CALL_SET(a, my -> value. M_VAR1ANT_GET_FIELD a , \
|
||||
org -> value.M_VAR1ANT_GET_FIELD a ); \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the CLEAR function. */
|
||||
#define VARIANTI_DEFINE_CLEAR(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_CLEAR(name, ...) \
|
||||
static inline void M_C(name, _clear)(M_C(name,_ct) my) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
switch (my->type) { \
|
||||
case M_C(name, _EMPTY): break; \
|
||||
M_MAP2(VARIANTI_DEFINE_CLEAR_FUNC, name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_CLEAR_FUNC, name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
my->type = M_C(name, _EMPTY); \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_CLEAR_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
VARIANTI_CALL_CLEAR(a, my -> value. VARIANTI_GET_FIELD a); \
|
||||
#define M_VAR1ANT_DEFINE_CLEAR_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
M_VAR1ANT_CALL_CLEAR(a, my -> value. M_VAR1ANT_GET_FIELD a); \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the TEST_P function. */
|
||||
#define VARIANTI_DEFINE_TEST_P(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_TEST_P(name, ...) \
|
||||
static inline bool M_C(name, _empty_p)(M_C(name,_ct) const my) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
return my->type == M_C(name, _EMPTY); \
|
||||
} \
|
||||
static inline enum M_C(name, _enum) \
|
||||
M_C(name, _type)(M_C(name,_ct) my) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
return my->type; \
|
||||
} \
|
||||
M_MAP2(VARIANTI_DEFINE_TEST_FUNC, name, __VA_ARGS__)
|
||||
M_MAP2(M_VAR1ANT_DEFINE_TEST_FUNC, name, __VA_ARGS__)
|
||||
|
||||
#define VARIANTI_DEFINE_TEST_FUNC(name, a) \
|
||||
#define M_VAR1ANT_DEFINE_TEST_FUNC(name, a) \
|
||||
static inline bool \
|
||||
M_C4(name, _, VARIANTI_GET_FIELD a, _p)(M_C(name,_ct) const my) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
return my->type == M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
M_C4(name, _, M_VAR1ANT_GET_FIELD a, _p)(M_C(name,_ct) const my) { \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
return my->type == M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the INIT function. */
|
||||
#define VARIANTI_DEFINE_INIT_FIELD(name, ...) \
|
||||
M_MAP2(VARIANTI_DEFINE_INIT_FIELD_FUNC, name, __VA_ARGS__)
|
||||
#define M_VAR1ANT_DEFINE_INIT_FIELD(name, ...) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_INIT_FIELD_FUNC, name, __VA_ARGS__)
|
||||
|
||||
#define VARIANTI_DEFINE_INIT_FIELD_FUNC(name, a) \
|
||||
#define M_VAR1ANT_DEFINE_INIT_FIELD_FUNC(name, a) \
|
||||
static inline void \
|
||||
M_C3(name, _init_, VARIANTI_GET_FIELD a)(M_C(name,_ct) my) { \
|
||||
M_C3(name, _init_, M_VAR1ANT_GET_FIELD a)(M_C(name,_ct) my) { \
|
||||
/* Reinit variable with the given value */ \
|
||||
my->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
VARIANTI_CALL_INIT(a, my -> value. VARIANTI_GET_FIELD a); \
|
||||
my->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
|
||||
M_VAR1ANT_CALL_INIT(a, my -> value. M_VAR1ANT_GET_FIELD a); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the INIT_SET of a given type function. */
|
||||
#define VARIANTI_DEFINE_INIT_SETTER_FIELD(name, ...) \
|
||||
M_MAP2(VARIANTI_DEFINE_INIT_SETTER_FIELD_FUNC, name, __VA_ARGS__)
|
||||
#define M_VAR1ANT_DEFINE_INIT_SETTER_FIELD(name, ...) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_INIT_SETTER_FIELD_FUNC, name, __VA_ARGS__)
|
||||
|
||||
#define VARIANTI_DEFINE_INIT_SETTER_FIELD_FUNC(name, a) \
|
||||
#define M_VAR1ANT_DEFINE_INIT_SETTER_FIELD_FUNC(name, a) \
|
||||
static inline void \
|
||||
M_C3(name, _init_set_, VARIANTI_GET_FIELD a)(M_C(name,_ct) my, \
|
||||
VARIANTI_GET_TYPE a const VARIANTI_GET_FIELD a ) { \
|
||||
my->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
VARIANTI_CALL_INIT_SET(a, my -> value. VARIANTI_GET_FIELD a, \
|
||||
VARIANTI_GET_FIELD a); \
|
||||
M_C3(name, _init_set_, M_VAR1ANT_GET_FIELD a)(M_C(name,_ct) my, \
|
||||
M_VAR1ANT_GET_TYPE a const M_VAR1ANT_GET_FIELD a ) { \
|
||||
my->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
|
||||
M_VAR1ANT_CALL_INIT_SET(a, my -> value. M_VAR1ANT_GET_FIELD a, \
|
||||
M_VAR1ANT_GET_FIELD a); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the SET of a given type function. */
|
||||
#define VARIANTI_DEFINE_SETTER_FIELD(name, ...) \
|
||||
M_MAP2(VARIANTI_DEFINE_SETTER_FIELD_FUNC, name, __VA_ARGS__)
|
||||
#define M_VAR1ANT_DEFINE_SETTER_FIELD(name, ...) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_SETTER_FIELD_FUNC, name, __VA_ARGS__)
|
||||
|
||||
#define VARIANTI_DEFINE_SETTER_FIELD_FUNC(name, a) \
|
||||
#define M_VAR1ANT_DEFINE_SETTER_FIELD_FUNC(name, a) \
|
||||
static inline void \
|
||||
M_C3(name, _set_, VARIANTI_GET_FIELD a)(M_C(name,_ct) my, \
|
||||
VARIANTI_GET_TYPE a const VARIANTI_GET_FIELD a ) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
if (my->type == M_C4(name, _, VARIANTI_GET_FIELD a, _value) ) { \
|
||||
VARIANTI_CALL_SET(a, my -> value. VARIANTI_GET_FIELD a, \
|
||||
VARIANTI_GET_FIELD a); \
|
||||
M_C3(name, _set_, M_VAR1ANT_GET_FIELD a)(M_C(name,_ct) my, \
|
||||
M_VAR1ANT_GET_TYPE a const M_VAR1ANT_GET_FIELD a ) { \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
if (my->type == M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value) ) { \
|
||||
M_VAR1ANT_CALL_SET(a, my -> value. M_VAR1ANT_GET_FIELD a, \
|
||||
M_VAR1ANT_GET_FIELD a); \
|
||||
} else { \
|
||||
M_C(name, _clear)(my); \
|
||||
/* Reinit variable with the given value */ \
|
||||
my->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
VARIANTI_CALL_INIT_SET(a, my -> value. VARIANTI_GET_FIELD a, \
|
||||
VARIANTI_GET_FIELD a); \
|
||||
my->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
|
||||
M_VAR1ANT_CALL_INIT_SET(a, my -> value. M_VAR1ANT_GET_FIELD a, \
|
||||
M_VAR1ANT_GET_FIELD a); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* Define the GET_field of a given type function. */
|
||||
#define VARIANTI_DEFINE_GETTER_FIELD(name, ...) \
|
||||
M_MAP2(VARIANTI_DEFINE_GETTER_FIELD_FUNC, name, __VA_ARGS__)
|
||||
#define M_VAR1ANT_DEFINE_GETTER_FIELD(name, ...) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_GETTER_FIELD_FUNC, name, __VA_ARGS__)
|
||||
|
||||
#define VARIANTI_DEFINE_GETTER_FIELD_FUNC(name, a) \
|
||||
static inline VARIANTI_GET_TYPE a * \
|
||||
M_C3(name, _get_, VARIANTI_GET_FIELD a)(M_C(name,_ct) my) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
if (my->type != M_C4(name, _, VARIANTI_GET_FIELD a, _value) ) { \
|
||||
#define M_VAR1ANT_DEFINE_GETTER_FIELD_FUNC(name, a) \
|
||||
static inline M_VAR1ANT_GET_TYPE a * \
|
||||
M_C3(name, _get_, M_VAR1ANT_GET_FIELD a)(M_C(name,_ct) my) { \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
if (my->type != M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value) ) { \
|
||||
return NULL; \
|
||||
} \
|
||||
return &my -> value . VARIANTI_GET_FIELD a; \
|
||||
return &my -> value . M_VAR1ANT_GET_FIELD a; \
|
||||
} \
|
||||
\
|
||||
static inline VARIANTI_GET_TYPE a const * \
|
||||
M_C3(name, _cget_, VARIANTI_GET_FIELD a)(M_C(name,_ct) const my) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
if (my->type != M_C4(name, _, VARIANTI_GET_FIELD a, _value) ) { \
|
||||
static inline M_VAR1ANT_GET_TYPE a const * \
|
||||
M_C3(name, _cget_, M_VAR1ANT_GET_FIELD a)(M_C(name,_ct) const my) { \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
if (my->type != M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value) ) { \
|
||||
return NULL; \
|
||||
} \
|
||||
return &my -> value . VARIANTI_GET_FIELD a; \
|
||||
return &my -> value . M_VAR1ANT_GET_FIELD a; \
|
||||
}
|
||||
|
||||
|
||||
/* Define the EQUAL_P function. */
|
||||
#define VARIANTI_DEFINE_EQUAL(name, ...) \
|
||||
#define M_VAR1ANT_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; \
|
||||
VARIANTI_CONTRACT(name, e1); \
|
||||
VARIANTI_CONTRACT(name, e2); \
|
||||
M_VAR1ANT_CONTRACT(name, e1); \
|
||||
M_VAR1ANT_CONTRACT(name, e2); \
|
||||
if (e1->type != e2->type) return false; \
|
||||
switch (e1->type) { \
|
||||
case M_C(name, _EMPTY): break; \
|
||||
M_MAP2(VARIANTI_DEFINE_EQUAL_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_EQUAL_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_EQUAL_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
b = VARIANTI_CALL_EQUAL(a, e1 -> value . VARIANTI_GET_FIELD a , \
|
||||
e2 -> value . VARIANTI_GET_FIELD a ); \
|
||||
#define M_VAR1ANT_DEFINE_EQUAL_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
b = M_VAR1ANT_CALL_EQUAL(a, e1 -> value . M_VAR1ANT_GET_FIELD a , \
|
||||
e2 -> value . M_VAR1ANT_GET_FIELD a ); \
|
||||
return b; \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the HASH function. */
|
||||
#define VARIANTI_DEFINE_HASH(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_HASH(name, ...) \
|
||||
static inline size_t M_C(name, _hash)(M_C(name,_ct) const e1) { \
|
||||
VARIANTI_CONTRACT(name, e1); \
|
||||
M_VAR1ANT_CONTRACT(name, e1); \
|
||||
M_HASH_DECL(hash); \
|
||||
M_HASH_UP (hash, (unsigned int) (e1 -> type)); \
|
||||
switch (e1->type) { \
|
||||
case M_C(name, _EMPTY): break; \
|
||||
M_MAP2(VARIANTI_DEFINE_HASH_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_HASH_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
return M_HASH_FINAL (hash); \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_HASH_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
M_HASH_UP(hash, VARIANTI_CALL_HASH(a, e1 -> value . VARIANTI_GET_FIELD a) ); \
|
||||
#define M_VAR1ANT_DEFINE_HASH_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
M_HASH_UP(hash, M_VAR1ANT_CALL_HASH(a, e1 -> value . M_VAR1ANT_GET_FIELD a) ); \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the INIT_MOVE function. */
|
||||
#define VARIANTI_DEFINE_INIT_MOVE(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_INIT_MOVE(name, ...) \
|
||||
static inline void \
|
||||
M_C(name, _init_move)(M_C(name,_ct) el, M_C(name,_ct) org) { \
|
||||
VARIANTI_CONTRACT(name, org); \
|
||||
M_VAR1ANT_CONTRACT(name, org); \
|
||||
el -> type = org -> type; \
|
||||
switch (el->type) { \
|
||||
case M_C(name, _EMPTY): break; \
|
||||
M_MAP2(VARIANTI_DEFINE_INIT_MOVE_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_INIT_MOVE_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
org -> type = M_C(name, _EMPTY); \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_INIT_MOVE_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
VARIANTI_CALL_INIT_MOVE(a, el -> value . VARIANTI_GET_FIELD a, \
|
||||
org -> value . VARIANTI_GET_FIELD a); \
|
||||
#define M_VAR1ANT_DEFINE_INIT_MOVE_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
M_VAR1ANT_CALL_INIT_MOVE(a, el -> value . M_VAR1ANT_GET_FIELD a, \
|
||||
org -> value . M_VAR1ANT_GET_FIELD a); \
|
||||
break;
|
||||
|
||||
|
||||
@@ -452,48 +452,48 @@
|
||||
This is not optimized version.
|
||||
It can be optimized if both types are the same.
|
||||
*/
|
||||
#define VARIANTI_DEFINE_MOVE(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_MOVE(name, ...) \
|
||||
static inline void \
|
||||
M_C(name, _move)(M_C(name,_ct) el, M_C(name,_ct) org) { \
|
||||
VARIANTI_CONTRACT(name, el); \
|
||||
VARIANTI_CONTRACT(name, org); \
|
||||
M_VAR1ANT_CONTRACT(name, el); \
|
||||
M_VAR1ANT_CONTRACT(name, org); \
|
||||
M_C(name, _clear)(el); \
|
||||
M_C(name, _init_move)(el , org); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the MOVE function of a given type */
|
||||
#define VARIANTI_DEFINE_MOVER(name, ...) \
|
||||
M_MAP2(VARIANTI_DEFINE_MOVER_FUNC, name, __VA_ARGS__)
|
||||
#define M_VAR1ANT_DEFINE_MOVER(name, ...) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_MOVER_FUNC, name, __VA_ARGS__)
|
||||
|
||||
#define VARIANTI_DEFINE_MOVER_FUNC(name, a) \
|
||||
#define M_VAR1ANT_DEFINE_MOVER_FUNC(name, a) \
|
||||
static inline void \
|
||||
M_C3(name, _move_, VARIANTI_GET_FIELD a)(M_C(name,_ct) my, \
|
||||
VARIANTI_GET_TYPE a VARIANTI_GET_FIELD a ) { \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
M_C3(name, _move_, M_VAR1ANT_GET_FIELD a)(M_C(name,_ct) my, \
|
||||
M_VAR1ANT_GET_TYPE a M_VAR1ANT_GET_FIELD a ) { \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
M_C(name, _clear)(my); \
|
||||
/* Reinit variable with the given value */ \
|
||||
my->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
VARIANTI_CALL_INIT_MOVE(a, my -> value. VARIANTI_GET_FIELD a, \
|
||||
VARIANTI_GET_FIELD a); \
|
||||
my->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
|
||||
M_VAR1ANT_CALL_INIT_MOVE(a, my -> value. M_VAR1ANT_GET_FIELD a, \
|
||||
M_VAR1ANT_GET_FIELD a); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the SWAP function */
|
||||
#define VARIANTI_DEFINE_SWAP(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_SWAP(name, ...) \
|
||||
static inline void \
|
||||
M_C(name, _swap)(M_C(name,_ct) el1, M_C(name,_ct) el2) { \
|
||||
VARIANTI_CONTRACT(name, el1); \
|
||||
VARIANTI_CONTRACT(name, el2); \
|
||||
M_VAR1ANT_CONTRACT(name, el1); \
|
||||
M_VAR1ANT_CONTRACT(name, el2); \
|
||||
if (el1->type == el2->type) { \
|
||||
switch (el1->type) { \
|
||||
case M_C(name, _EMPTY): break; \
|
||||
M_MAP2(VARIANTI_DEFINE_INIT_SWAP_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_INIT_SWAP_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
} else { \
|
||||
M_C(name,_ct) tmp; \
|
||||
VARIANTI_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
M_VAR1ANT_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
( /* NOTE: Slow implementation */ \
|
||||
M_C(name, _init_move)(tmp, el1); \
|
||||
M_C(name, _init_move)(el1, el2); \
|
||||
@@ -508,43 +508,43 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_INIT_SWAP_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
VARIANTI_CALL_SWAP(a, el1 -> value . VARIANTI_GET_FIELD a, \
|
||||
el2 -> value . VARIANTI_GET_FIELD a); \
|
||||
#define M_VAR1ANT_DEFINE_INIT_SWAP_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
M_VAR1ANT_CALL_SWAP(a, el1 -> value . M_VAR1ANT_GET_FIELD a, \
|
||||
el2 -> value . M_VAR1ANT_GET_FIELD a); \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the GET_STR function */
|
||||
#define VARIANTI_DEFINE_GET_STR(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_GET_STR(name, ...) \
|
||||
static inline void M_C(name, _get_str)(string_t str, \
|
||||
M_C(name,_ct) const el, \
|
||||
bool append) { \
|
||||
VARIANTI_CONTRACT(name, el); \
|
||||
M_VAR1ANT_CONTRACT(name, el); \
|
||||
M_ASSERT (str != NULL); \
|
||||
void (*func)(string_t, const char *); \
|
||||
func = append ? string_cat_str : string_set_str; \
|
||||
switch (el->type) { \
|
||||
case M_C(name, _EMPTY): func(str, "@EMPTY@"); break; \
|
||||
M_MAP2(VARIANTI_DEFINE_GET_STR_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_GET_STR_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
string_push_back (str, '@'); \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_GET_STR_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
func(str, "@" M_AS_STR(VARIANTI_GET_FIELD a) "@"); \
|
||||
VARIANTI_CALL_GET_STR(a, str, el -> value . VARIANTI_GET_FIELD a, true); \
|
||||
#define M_VAR1ANT_DEFINE_GET_STR_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
func(str, "@" M_AS_STR(M_VAR1ANT_GET_FIELD a) "@"); \
|
||||
M_VAR1ANT_CALL_GET_STR(a, str, el -> value . M_VAR1ANT_GET_FIELD a, true); \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the PARSE_STR function */
|
||||
#define VARIANTI_DEFINE_PARSE_STR(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_PARSE_STR(name, ...) \
|
||||
static inline bool M_C(name, _parse_str)(M_C(name,_ct) el, \
|
||||
const char str[], \
|
||||
const char **endp) { \
|
||||
VARIANTI_CONTRACT(name, el); \
|
||||
M_VAR1ANT_CONTRACT(name, el); \
|
||||
M_ASSERT (str != NULL); \
|
||||
bool success = false; \
|
||||
char variantTypeBuf[M_MAX_IDENTIFIER_LENGTH+1]; \
|
||||
@@ -565,7 +565,7 @@
|
||||
if (strcmp(variantTypeBuf, "EMPTY") == 0) { \
|
||||
el->type = M_C(name, _EMPTY); \
|
||||
} \
|
||||
M_MAP2(VARIANTI_DEFINE_PARSE_STR_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_PARSE_STR_FUNC , name, __VA_ARGS__) \
|
||||
else goto exit; \
|
||||
success = (*str++ == '@'); \
|
||||
exit: \
|
||||
@@ -573,41 +573,41 @@
|
||||
return success; \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_PARSE_STR_FUNC(name, a) \
|
||||
else if (strcmp (variantTypeBuf, M_AS_STR(VARIANTI_GET_FIELD a)) == 0) { \
|
||||
el->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
VARIANTI_CALL_INIT(a, el ->value . VARIANTI_GET_FIELD a ); \
|
||||
bool b = VARIANTI_CALL_PARSE_STR(a, el -> value . VARIANTI_GET_FIELD a, str, &str); \
|
||||
#define M_VAR1ANT_DEFINE_PARSE_STR_FUNC(name, a) \
|
||||
else if (strcmp (variantTypeBuf, M_AS_STR(M_VAR1ANT_GET_FIELD a)) == 0) { \
|
||||
el->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
|
||||
M_VAR1ANT_CALL_INIT(a, el ->value . M_VAR1ANT_GET_FIELD a ); \
|
||||
bool b = M_VAR1ANT_CALL_PARSE_STR(a, el -> value . M_VAR1ANT_GET_FIELD a, str, &str); \
|
||||
if (!b) goto exit; \
|
||||
}
|
||||
|
||||
|
||||
/* Define the OUT_STR function */
|
||||
#define VARIANTI_DEFINE_OUT_STR(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_OUT_STR(name, ...) \
|
||||
static inline void M_C(name, _out_str)(FILE *f, \
|
||||
M_C(name,_ct) const el) { \
|
||||
VARIANTI_CONTRACT(name, el); \
|
||||
M_VAR1ANT_CONTRACT(name, el); \
|
||||
M_ASSERT (f != NULL); \
|
||||
switch (el->type) { \
|
||||
case M_C(name, _EMPTY): fprintf(f, "@EMPTY@"); break; \
|
||||
M_MAP2(VARIANTI_DEFINE_OUT_STR_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_OUT_STR_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
fputc ('@', f); \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_OUT_STR_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
fprintf(f, "@" M_AS_STR(VARIANTI_GET_FIELD a) "@"); \
|
||||
VARIANTI_CALL_OUT_STR(a, f, el -> value . VARIANTI_GET_FIELD a); \
|
||||
#define M_VAR1ANT_DEFINE_OUT_STR_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
fprintf(f, "@" M_AS_STR(M_VAR1ANT_GET_FIELD a) "@"); \
|
||||
M_VAR1ANT_CALL_OUT_STR(a, f, el -> value . M_VAR1ANT_GET_FIELD a); \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the IN_STR function */
|
||||
#define VARIANTI_DEFINE_IN_STR(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_IN_STR(name, ...) \
|
||||
static inline bool M_C(name, _in_str)(M_C(name,_ct) el, \
|
||||
FILE *f) { \
|
||||
VARIANTI_CONTRACT(name, el); \
|
||||
M_VAR1ANT_CONTRACT(name, el); \
|
||||
M_ASSERT (f != NULL); \
|
||||
char variantTypeBuf[M_MAX_IDENTIFIER_LENGTH+1]; \
|
||||
M_C(name, _clean)(el); \
|
||||
@@ -627,33 +627,33 @@
|
||||
if (strcmp(variantTypeBuf, "EMPTY") == 0) { \
|
||||
el->type = M_C(name, _EMPTY); \
|
||||
} \
|
||||
M_MAP2(VARIANTI_DEFINE_IN_STR_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_IN_STR_FUNC , name, __VA_ARGS__) \
|
||||
else { b = false; } \
|
||||
return b && (fgetc(f) == '@'); \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_IN_STR_FUNC(name, a) \
|
||||
else if (strcmp (variantTypeBuf, M_AS_STR(VARIANTI_GET_FIELD a)) == 0) { \
|
||||
el->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
VARIANTI_CALL_INIT(a, el ->value . VARIANTI_GET_FIELD a ); \
|
||||
b = VARIANTI_CALL_IN_STR(a, el -> value . VARIANTI_GET_FIELD a, f); \
|
||||
#define M_VAR1ANT_DEFINE_IN_STR_FUNC(name, a) \
|
||||
else if (strcmp (variantTypeBuf, M_AS_STR(M_VAR1ANT_GET_FIELD a)) == 0) { \
|
||||
el->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
|
||||
M_VAR1ANT_CALL_INIT(a, el ->value . M_VAR1ANT_GET_FIELD a ); \
|
||||
b = M_VAR1ANT_CALL_IN_STR(a, el -> value . M_VAR1ANT_GET_FIELD a, f); \
|
||||
}
|
||||
|
||||
|
||||
/* Return the STRING version of a parameter name */
|
||||
#define VARIANTI_STRINGIFY_NAME(a) \
|
||||
M_AS_STR(VARIANTI_GET_FIELD a)
|
||||
#define M_VAR1ANT_STRINGIFY_NAME(a) \
|
||||
M_AS_STR(M_VAR1ANT_GET_FIELD a)
|
||||
|
||||
|
||||
/* Define the OUT_SERIAL function */
|
||||
#define VARIANTI_DEFINE_OUT_SERIAL(name, ...) \
|
||||
#define M_VAR1ANT_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) { \
|
||||
VARIANTI_CONTRACT(name, el); \
|
||||
M_VAR1ANT_CONTRACT(name, el); \
|
||||
const int field_max = M_NARGS(__VA_ARGS__); \
|
||||
static const char *const field_name[] = \
|
||||
{ M_REDUCE(VARIANTI_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
|
||||
{ M_REDUCE(M_VAR1ANT_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_local_t local; \
|
||||
m_serial_return_code_t ret; \
|
||||
@@ -661,30 +661,30 @@
|
||||
case M_C(name, _EMPTY): \
|
||||
return f->m_interface->write_variant_start(local, f, field_name, field_max, -1); \
|
||||
break; \
|
||||
M_MAP2(VARIANTI_DEFINE_OUT_SERIAL_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_OUT_SERIAL_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
ret |= f->m_interface->write_variant_end(local, f); \
|
||||
return ret & M_SERIAL_FAIL; \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_OUT_SERIAL_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
#define M_VAR1ANT_DEFINE_OUT_SERIAL_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
ret = f->m_interface->write_variant_start(local, f, field_name, field_max, \
|
||||
M_C4(name, _, VARIANTI_GET_FIELD a, _value) -1); \
|
||||
VARIANTI_CALL_OUT_SERIAL(a, f, el -> value . VARIANTI_GET_FIELD a); \
|
||||
M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value) -1); \
|
||||
M_VAR1ANT_CALL_OUT_SERIAL(a, f, el -> value . M_VAR1ANT_GET_FIELD a); \
|
||||
break;
|
||||
|
||||
|
||||
/* Define the IN_SERIAL function */
|
||||
#define VARIANTI_DEFINE_IN_SERIAL(name, ...) \
|
||||
#define M_VAR1ANT_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) { \
|
||||
VARIANTI_CONTRACT(name, el); \
|
||||
M_VAR1ANT_CONTRACT(name, el); \
|
||||
const int field_max = M_NARGS(__VA_ARGS__); \
|
||||
static const char *const field_name[] = \
|
||||
{ M_REDUCE(VARIANTI_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
|
||||
{ M_REDUCE(M_VAR1ANT_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
|
||||
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_local_t local; \
|
||||
m_serial_return_code_t ret; \
|
||||
@@ -695,7 +695,7 @@
|
||||
M_ASSERT (id >= 0 && id < field_max); \
|
||||
el->type = (enum M_C(name, _enum))(id+1); \
|
||||
switch (id+1) { \
|
||||
M_MAP2(VARIANTI_DEFINE_IN_SERIAL_FUNC , name, __VA_ARGS__) \
|
||||
M_MAP2(M_VAR1ANT_DEFINE_IN_SERIAL_FUNC , name, __VA_ARGS__) \
|
||||
default: M_ASSERT(false); break; \
|
||||
} \
|
||||
if (ret == M_SERIAL_OK_DONE) \
|
||||
@@ -703,36 +703,36 @@
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define VARIANTI_DEFINE_IN_SERIAL_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
VARIANTI_CALL_INIT(a, el ->value . VARIANTI_GET_FIELD a ); \
|
||||
ret = VARIANTI_CALL_IN_SERIAL(a, el -> value . VARIANTI_GET_FIELD a, f); \
|
||||
#define M_VAR1ANT_DEFINE_IN_SERIAL_FUNC(name, a) \
|
||||
case M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value): \
|
||||
M_VAR1ANT_CALL_INIT(a, el ->value . M_VAR1ANT_GET_FIELD a ); \
|
||||
ret = M_VAR1ANT_CALL_IN_SERIAL(a, el -> value . M_VAR1ANT_GET_FIELD a, f); \
|
||||
break; \
|
||||
|
||||
|
||||
/* Define the CLEAN function */
|
||||
#define VARIANTI_DEFINE_CLEAN_FUNC(name, ...) \
|
||||
#define M_VAR1ANT_DEFINE_CLEAN_FUNC(name, ...) \
|
||||
static inline void M_C(name, _clean)(M_C(name,_ct) my) \
|
||||
{ \
|
||||
VARIANTI_CONTRACT(name, my); \
|
||||
M_VAR1ANT_CONTRACT(name, my); \
|
||||
M_C(name, _clear)(my); \
|
||||
M_C(name, _init)(my); \
|
||||
} \
|
||||
|
||||
|
||||
/* deferred evaluation of the oplist */
|
||||
#define VARIANTI_OPLIST_P1(arg) VARIANTI_OPLIST_P2 arg
|
||||
#define M_VAR1ANT_OPLIST_P1(arg) M_VAR1ANT_OPLIST_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define VARIANTI_OPLIST_P2(name, ...) \
|
||||
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(VARIANTI_OPLIST_P3, VARIANTI_OPLIST_FAILURE)(name, __VA_ARGS__)
|
||||
#define M_VAR1ANT_OPLIST_P2(name, ...) \
|
||||
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(M_VAR1ANT_OPLIST_P3, M_VAR1ANT_OPLIST_FAILURE)(name, __VA_ARGS__)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define VARIANTI_OPLIST_FAILURE(name, ...) \
|
||||
#define M_VAR1ANT_OPLIST_FAILURE(name, ...) \
|
||||
((M_LIB_ERROR(ONE_ARGUMENT_OF_VARIANT_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__)))
|
||||
|
||||
/* Define the oplist */
|
||||
#define VARIANTI_OPLIST_P3(name, ...) \
|
||||
#define M_VAR1ANT_OPLIST_P3(name, ...) \
|
||||
(INIT(M_C(name,_init)), \
|
||||
INIT_SET(M_C(name, _init_set)), \
|
||||
SET(M_C(name,_set)), \
|
||||
@@ -757,18 +757,18 @@
|
||||
)
|
||||
|
||||
/* Macros for testing for method presence */
|
||||
#define VARIANTI_TEST_METHOD_P2(method, f, t, op) \
|
||||
#define M_VAR1ANT_TEST_METHOD_P2(method, f, t, op) \
|
||||
M_TEST_METHOD_P(method, op)
|
||||
#define VARIANTI_TEST_METHOD_P(method, trio) \
|
||||
M_APPLY(VARIANTI_TEST_METHOD_P2, method, M_OPFLAT trio)
|
||||
#define VARIANTI_IF_ALL(method, ...) \
|
||||
M_IF(M_REDUCE2(VARIANTI_TEST_METHOD_P, M_AND, method, __VA_ARGS__))
|
||||
#define M_VAR1ANT_TEST_METHOD_P(method, trio) \
|
||||
M_APPLY(M_VAR1ANT_TEST_METHOD_P2, method, M_OPFLAT trio)
|
||||
#define M_VAR1ANT_IF_ALL(method, ...) \
|
||||
M_IF(M_REDUCE2(M_VAR1ANT_TEST_METHOD_P, M_AND, method, __VA_ARGS__))
|
||||
|
||||
#define VARIANTI_TEST_METHOD2_P2(method1, method2, f, t, op) \
|
||||
#define M_VAR1ANT_TEST_METHOD2_P2(method1, method2, f, t, op) \
|
||||
M_AND(M_TEST_METHOD_P(method1, op), M_TEST_METHOD_P(method2, op))
|
||||
#define VARIANTI_TEST_METHOD2_P(method, trio) \
|
||||
M_APPLY(VARIANTI_TEST_METHOD2_P2, M_PAIR_1 method, M_PAIR_2 method, M_OPFLAT trio)
|
||||
#define VARIANTI_IF_ALL2(method1, method2, ...) \
|
||||
M_IF(M_REDUCE2(VARIANTI_TEST_METHOD2_P, M_AND, (method1, method2), __VA_ARGS__))
|
||||
#define M_VAR1ANT_TEST_METHOD2_P(method, trio) \
|
||||
M_APPLY(M_VAR1ANT_TEST_METHOD2_P2, M_PAIR_1 method, M_PAIR_2 method, M_OPFLAT trio)
|
||||
#define M_VAR1ANT_IF_ALL2(method1, method2, ...) \
|
||||
M_IF(M_REDUCE2(M_VAR1ANT_TEST_METHOD2_P, M_AND, (method1, method2), __VA_ARGS__))
|
||||
|
||||
#endif
|
||||
+77
-77
@@ -113,25 +113,25 @@ typedef struct work_order_s {
|
||||
* * MACRO to complete the not-used fields
|
||||
*/
|
||||
#if M_USE_WORKER_CLANG_BLOCK || M_USE_WORKER_CPP_FUNCTION
|
||||
# define WORKERI_EMPTY_ORDER { NULL, NULL, NULL, NULL }
|
||||
# define WORKERI_EXTRA_ORDER , NULL
|
||||
# define M_WORK3R_EMPTY_ORDER { NULL, NULL, NULL, NULL }
|
||||
# define M_WORK3R_EXTRA_ORDER , NULL
|
||||
#else
|
||||
# define WORKERI_EMPTY_ORDER { NULL, NULL, NULL }
|
||||
# define WORKERI_EXTRA_ORDER
|
||||
# define M_WORK3R_EMPTY_ORDER { NULL, NULL, NULL }
|
||||
# define M_WORK3R_EXTRA_ORDER
|
||||
#endif
|
||||
|
||||
/* As in C++, it uses std::function, M_POD_OPLIST
|
||||
is not sufficient for initialization of the structure.
|
||||
So let's use C++ constructor, destructor and copy constructor */
|
||||
#if M_USE_WORKER_CPP_FUNCTION
|
||||
# define WORKERI_CPP_INIT(x) (new (&(x)) worker_order_ct())
|
||||
# define WORKERI_CPP_INIT_SET(x, y) (new (&(x)) worker_order_ct(y))
|
||||
# define WORKERI_CPP_SET(x, y) ((x) = (y))
|
||||
# define WORKERI_CPP_CLEAR(x) ((&(x))->~worker_order_ct())
|
||||
# define WORKERI_CPP_INIT_MOVE(x,y) (new (&(x)) worker_order_ct(y), ((&(y))->~worker_order_ct()))
|
||||
# define M_WORK3R_CPP_INIT(x) (new (&(x)) worker_order_ct())
|
||||
# define M_WORK3R_CPP_INIT_SET(x, y) (new (&(x)) worker_order_ct(y))
|
||||
# define M_WORK3R_CPP_SET(x, y) ((x) = (y))
|
||||
# define M_WORK3R_CPP_CLEAR(x) ((&(x))->~worker_order_ct())
|
||||
# define M_WORK3R_CPP_INIT_MOVE(x,y) (new (&(x)) worker_order_ct(y), ((&(y))->~worker_order_ct()))
|
||||
# define WORKER_OPLIST \
|
||||
(INIT(WORKERI_CPP_INIT), INIT_SET(WORKERI_CPP_INIT_SET), \
|
||||
SET(WORKERI_CPP_SET), CLEAR(WORKERI_CPP_CLEAR), INIT_MOVE(WORKERI_CPP_INIT_MOVE) )
|
||||
(INIT(M_WORK3R_CPP_INIT), INIT_SET(M_WORK3R_CPP_INIT_SET), \
|
||||
SET(M_WORK3R_CPP_SET), CLEAR(M_WORK3R_CPP_CLEAR), INIT_MOVE(M_WORK3R_CPP_INIT_MOVE) )
|
||||
#else
|
||||
# define WORKER_OPLIST M_POD_OPLIST
|
||||
#endif
|
||||
@@ -200,9 +200,9 @@ workeri_get_cpu_count(void)
|
||||
|
||||
// (INTERNAL) Debug support for workers
|
||||
#if 1
|
||||
#define WORKERI_DEBUG(...) (void) 0
|
||||
#define M_WORK3R_DEBUG(...) (void) 0
|
||||
#else
|
||||
#define WORKERI_DEBUG(...) printf(__VA_ARGS__)
|
||||
#define M_WORK3R_DEBUG(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/* Execute the registered work order **synchronously** */
|
||||
@@ -210,15 +210,15 @@ static inline void
|
||||
workeri_exec(worker_order_ct *w)
|
||||
{
|
||||
M_ASSERT (w!= NULL && w->block != NULL);
|
||||
WORKERI_DEBUG ("Starting thread with data %p\n", w->data);
|
||||
M_WORK3R_DEBUG ("Starting thread with data %p\n", w->data);
|
||||
#if M_USE_WORKER_CLANG_BLOCK
|
||||
WORKERI_DEBUG ("Running %s f=%p b=%p\n", (w->func == NULL) ? "Blocks" : "Function", w->func, w->blockFunc);
|
||||
M_WORK3R_DEBUG ("Running %s f=%p b=%p\n", (w->func == NULL) ? "Blocks" : "Function", w->func, w->blockFunc);
|
||||
if (w->func == NULL)
|
||||
w->blockFunc(w->data);
|
||||
else
|
||||
#endif
|
||||
#if M_USE_WORKER_CPP_FUNCTION
|
||||
WORKERI_DEBUG ("Running %s f=%p b=%p\n", (w->function == NULL) ? "Lambda" : "Function", w->func, w->blockFunc);
|
||||
M_WORK3R_DEBUG ("Running %s f=%p b=%p\n", (w->function == NULL) ? "Lambda" : "Function", w->func, w->blockFunc);
|
||||
if (w->function)
|
||||
w->function(w->data);
|
||||
else
|
||||
@@ -242,7 +242,7 @@ workeri_thread(void *arg)
|
||||
g->resetFunc_g();
|
||||
}
|
||||
// Waiting for data
|
||||
WORKERI_DEBUG ("Waiting for data (queue: %lu / %lu)\n", worker_queue_size(g->queue_g), worker_queue_capacity(g->queue_g));
|
||||
M_WORK3R_DEBUG ("Waiting for data (queue: %lu / %lu)\n", worker_queue_size(g->queue_g), worker_queue_capacity(g->queue_g));
|
||||
worker_queue_pop(&w, g->queue_g);
|
||||
// We received a work order
|
||||
// Note: that the work order is still present in the queue
|
||||
@@ -278,7 +278,7 @@ worker_init(worker_t g, int numWorker, unsigned int extraQueue, void (*resetFunc
|
||||
// Auto compute number of workers if the argument is 0
|
||||
if (numWorker <= 0)
|
||||
numWorker = (1 + (numWorker == -1))*workeri_get_cpu_count()-1;
|
||||
WORKERI_DEBUG ("Starting queue with: %d\n", numWorker + extraQueue);
|
||||
M_WORK3R_DEBUG ("Starting queue with: %d\n", numWorker + extraQueue);
|
||||
// Initialization
|
||||
// numWorker can still be 0 if it is a single core cpu (no worker available)
|
||||
M_ASSERT(numWorker >= 0);
|
||||
@@ -316,7 +316,7 @@ worker_clear(worker_t g)
|
||||
M_ASSERT (worker_queue_empty_p (g->queue_g));
|
||||
// Push the terminate order on the queue
|
||||
for(unsigned int i = 0; i < g->numWorker_g; i++) {
|
||||
worker_order_ct w = WORKERI_EMPTY_ORDER;
|
||||
worker_order_ct w = M_WORK3R_EMPTY_ORDER;
|
||||
// Normaly all worker threads shall be waiting at this
|
||||
// stage, so all push won't block as the queue is empty.
|
||||
// But for robustness, let's wait.
|
||||
@@ -351,14 +351,14 @@ worker_start(worker_sync_t block, worker_t g)
|
||||
static inline void
|
||||
worker_spawn(worker_sync_t block, void (*func)(void *data), void *data)
|
||||
{
|
||||
const worker_order_ct w = { block, data, func WORKERI_EXTRA_ORDER };
|
||||
const worker_order_ct w = { block, data, func M_WORK3R_EXTRA_ORDER };
|
||||
if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
|
||||
&& worker_queue_push (block->worker->queue_g, w) == true) {
|
||||
WORKERI_DEBUG ("Sending data to thread: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
M_WORK3R_DEBUG ("Sending data to thread: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
atomic_fetch_add (&block->num_spawn, 1);
|
||||
return;
|
||||
}
|
||||
WORKERI_DEBUG ("Running data ourself: %p\n", data);
|
||||
M_WORK3R_DEBUG ("Running data ourself: %p\n", data);
|
||||
/* No worker available. Call the function ourself */
|
||||
(*func) (data);
|
||||
}
|
||||
@@ -372,11 +372,11 @@ worker_spawn_block(worker_sync_t block, void (^func)(void *data), void *data)
|
||||
const worker_order_ct w = { block, data, NULL, func };
|
||||
if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
|
||||
&& worker_queue_push (block->worker->queue_g, w) == true) {
|
||||
WORKERI_DEBUG ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
M_WORK3R_DEBUG ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
atomic_fetch_add (&block->num_spawn, 1);
|
||||
return;
|
||||
}
|
||||
WORKERI_DEBUG ("Running data ourself as block: %p\n", data);
|
||||
M_WORK3R_DEBUG ("Running data ourself as block: %p\n", data);
|
||||
/* No worker available. Call the function ourself */
|
||||
func (data);
|
||||
}
|
||||
@@ -391,11 +391,11 @@ worker_spawn_function(worker_sync_t block, std::function<void(void *data)> func,
|
||||
const worker_order_ct w = { block, data, NULL, func };
|
||||
if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
|
||||
&& worker_queue_push (block->worker->queue_g, w) == true) {
|
||||
WORKERI_DEBUG ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
M_WORK3R_DEBUG ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
atomic_fetch_add (&block->num_spawn, 1);
|
||||
return;
|
||||
}
|
||||
WORKERI_DEBUG ("Running data ourself as block: %p\n", data);
|
||||
M_WORK3R_DEBUG ("Running data ourself as block: %p\n", data);
|
||||
/* No worker available. Call the function ourself */
|
||||
func (data);
|
||||
}
|
||||
@@ -415,7 +415,7 @@ worker_sync_p(worker_sync_t block)
|
||||
static inline void
|
||||
worker_sync(worker_sync_t block)
|
||||
{
|
||||
WORKERI_DEBUG ("Waiting for thread terminasion.\n");
|
||||
M_WORK3R_DEBUG ("Waiting for thread terminasion.\n");
|
||||
// Fast case: all workers have finished
|
||||
if (worker_sync_p(block)) return;
|
||||
// Slow case: perform a locked wait to put this thread to waiting state
|
||||
@@ -455,77 +455,77 @@ worker_count(worker_t g)
|
||||
*/
|
||||
#if M_USE_WORKER_CLANG_BLOCK
|
||||
#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)
|
||||
M_WORK3R_DEF_DATA(_input, _output) \
|
||||
M_WORK3R_DEF_SUBBLOCK(_input, _output, _core) \
|
||||
worker_spawn_block ((_block), M_WORK3R_SPAWN_SUBFUNC_NAME, &M_WORK3R_SPAWN_DATA_NAME)
|
||||
#elif M_USE_WORKER_CPP_FUNCTION
|
||||
// TODO: Explicit pass all arguments by reference.
|
||||
#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) \
|
||||
worker_spawn ((_block), WORKER_SPAWN_SUBFUNC_NAME, &WORKER_SPAWN_DATA_NAME)
|
||||
M_WORK3R_DEF_DATA(_input, _output) \
|
||||
M_WORK3R_DEF_SUBFUNC(_input, _output, _core) \
|
||||
worker_spawn ((_block), M_WORK3R_SPAWN_SUBFUNC_NAME, &M_WORK3R_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 M_WORK3R_SPAWN_STRUCT_NAME M_C(worker_data_s_, __LINE__)
|
||||
#define M_WORK3R_SPAWN_DATA_NAME M_C(worker_data_, __LINE__)
|
||||
#define M_WORK3R_SPAWN_SUBFUNC_NAME M_C(worker_subfunc_, __LINE__)
|
||||
#define M_WORK3R_DEF_DATA(_input, _output) \
|
||||
struct M_WORK3R_SPAWN_STRUCT_NAME { \
|
||||
M_WORK3R_DEF_DATA_INPUT _input \
|
||||
M_IF_EMPTY _output ( , M_WORK3R_DEF_DATA_OUTPUT _output) \
|
||||
} M_WORK3R_SPAWN_DATA_NAME = { \
|
||||
M_WORK3R_INIT_DATA_INPUT _input \
|
||||
M_IF_EMPTY _output (, M_WORK3R_INIT_DATA_OUTPUT _output) \
|
||||
};
|
||||
#define WORKER_DEF_SINGLE_INPUT(var) __typeof__(var) var;
|
||||
#define WORKER_DEF_DATA_INPUT(...) \
|
||||
M_MAP(WORKER_DEF_SINGLE_INPUT, __VA_ARGS__)
|
||||
#define WORKER_DEF_SINGLE_OUTPUT(var) \
|
||||
#define M_WORK3R_DEF_SINGLE_INPUT(var) __typeof__(var) var;
|
||||
#define M_WORK3R_DEF_DATA_INPUT(...) \
|
||||
M_MAP(M_WORK3R_DEF_SINGLE_INPUT, __VA_ARGS__)
|
||||
#define M_WORK3R_DEF_SINGLE_OUTPUT(var) \
|
||||
__typeof__(var) *M_C(var, _ptr);
|
||||
#define WORKER_DEF_DATA_OUTPUT(...) \
|
||||
M_MAP(WORKER_DEF_SINGLE_OUTPUT, __VA_ARGS__)
|
||||
#define WORKER_INIT_SINGLE_INPUT(var) \
|
||||
#define M_WORK3R_DEF_DATA_OUTPUT(...) \
|
||||
M_MAP(M_WORK3R_DEF_SINGLE_OUTPUT, __VA_ARGS__)
|
||||
#define M_WORK3R_INIT_SINGLE_INPUT(var) \
|
||||
.var = var,
|
||||
#define WORKER_INIT_DATA_INPUT(...) \
|
||||
M_MAP(WORKER_INIT_SINGLE_INPUT, __VA_ARGS__)
|
||||
#define WORKER_INIT_SINGLE_OUTPUT(var) \
|
||||
#define M_WORK3R_INIT_DATA_INPUT(...) \
|
||||
M_MAP(M_WORK3R_INIT_SINGLE_INPUT, __VA_ARGS__)
|
||||
#define M_WORK3R_INIT_SINGLE_OUTPUT(var) \
|
||||
.M_C(var, _ptr) = &var,
|
||||
#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) \
|
||||
#define M_WORK3R_INIT_DATA_OUTPUT(...) \
|
||||
M_MAP(M_WORK3R_INIT_SINGLE_OUTPUT, __VA_ARGS__)
|
||||
#define M_WORK3R_DEF_SUBFUNC(_input, _output, _core) \
|
||||
__extension__ auto void M_WORK3R_SPAWN_SUBFUNC_NAME(void *) ; \
|
||||
__extension__ void M_WORK3R_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) \
|
||||
struct M_WORK3R_SPAWN_STRUCT_NAME *_s_data = _data ; \
|
||||
M_WORK3R_INIT_LOCAL_INPUT _input \
|
||||
M_IF_EMPTY _output ( , M_WORK3R_INIT_LOCAL_OUTPUT _output) \
|
||||
do { _core } while (0); \
|
||||
M_IF_EMPTY _output ( , WORKER_PROPAGATE_LOCAL_OUTPUT _output) \
|
||||
M_IF_EMPTY _output ( , M_WORK3R_PROPAGATE_LOCAL_OUTPUT _output) \
|
||||
};
|
||||
#define WORKER_DEF_SUBBLOCK(_input, _output, _core) \
|
||||
void (^WORKER_SPAWN_SUBFUNC_NAME) (void *) = ^ void (void * _data) \
|
||||
#define M_WORK3R_DEF_SUBBLOCK(_input, _output, _core) \
|
||||
void (^M_WORK3R_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) \
|
||||
struct M_WORK3R_SPAWN_STRUCT_NAME *_s_data = _data ; \
|
||||
M_WORK3R_INIT_LOCAL_INPUT _input \
|
||||
M_IF_EMPTY _output ( , M_WORK3R_INIT_LOCAL_OUTPUT _output) \
|
||||
do { _core } while (0); \
|
||||
M_IF_EMPTY _output ( , WORKER_PROPAGATE_LOCAL_OUTPUT _output) \
|
||||
M_IF_EMPTY _output ( , M_WORK3R_PROPAGATE_LOCAL_OUTPUT _output) \
|
||||
};
|
||||
#define WORKER_INIT_SINGLE_LOCAL_INPUT(var) \
|
||||
#define M_WORK3R_INIT_SINGLE_LOCAL_INPUT(var) \
|
||||
__typeof__(var) var = _s_data->var;
|
||||
#define WORKER_INIT_LOCAL_INPUT(...) \
|
||||
M_MAP(WORKER_INIT_SINGLE_LOCAL_INPUT, __VA_ARGS__)
|
||||
#define WORKER_INIT_SINGLE_LOCAL_OUTPUT(var) \
|
||||
#define M_WORK3R_INIT_LOCAL_INPUT(...) \
|
||||
M_MAP(M_WORK3R_INIT_SINGLE_LOCAL_INPUT, __VA_ARGS__)
|
||||
#define M_WORK3R_INIT_SINGLE_LOCAL_OUTPUT(var) \
|
||||
__typeof__(var) var;
|
||||
#define WORKER_INIT_LOCAL_OUTPUT(...) \
|
||||
M_MAP(WORKER_INIT_SINGLE_LOCAL_OUTPUT, __VA_ARGS__)
|
||||
#define WORKER_PROPAGATE_SINGLE_OUTPUT(var) \
|
||||
#define M_WORK3R_INIT_LOCAL_OUTPUT(...) \
|
||||
M_MAP(M_WORK3R_INIT_SINGLE_LOCAL_OUTPUT, __VA_ARGS__)
|
||||
#define M_WORK3R_PROPAGATE_SINGLE_OUTPUT(var) \
|
||||
*(_s_data->M_C(var, _ptr)) = var;
|
||||
#define WORKER_PROPAGATE_LOCAL_OUTPUT(...) \
|
||||
M_MAP(WORKER_PROPAGATE_SINGLE_OUTPUT, __VA_ARGS__)
|
||||
#define M_WORK3R_PROPAGATE_LOCAL_OUTPUT(...) \
|
||||
M_MAP(M_WORK3R_PROPAGATE_SINGLE_OUTPUT, __VA_ARGS__)
|
||||
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ static void test_ti1(int n)
|
||||
deque_t d;
|
||||
|
||||
deque_init(d);
|
||||
assert(deque_capacity(d) == DEQUEUI_DEFAULT_SIZE);
|
||||
assert(deque_capacity(d) == M_D3QU3_DEFAULT_SIZE);
|
||||
|
||||
for(int i =0; i < n ;i++) {
|
||||
deque_push_back(d, i);
|
||||
|
||||
Reference in new issue
Block a user