diff --git a/m-i-shared.h b/m-i-shared.h index 22598711..aaf98a1d 100644 --- a/m-i-shared.h +++ b/m-i-shared.h @@ -42,8 +42,9 @@ #define ISHARED_PTR_INTERFACE(name, type) \ atomic_int M_C(name, _cpt) + /* Define the intrusive shared pointer type and its static inline functions. - USAGE: ISHARED_PTR_DEF(name[, oplist]) */ + USAGE: ISHARED_PTR_DEF(name, type, [, oplist]) */ #define ISHARED_PTR_DEF(name, ...) \ ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ @@ -73,7 +74,15 @@ // Deferred evaluatioin #define ISHAREDI_PTR_DEF_P1(arg) ISHAREDI_PTR_DEF_P2 arg +/* Validate the oplist before going further */ #define ISHAREDI_PTR_DEF_P2(name, type, oplist) \ + M_IF_OPLIST(oplist)(ISHAREDI_PTR_DEF_P3, ISHAREDI_PTR_DEF_FAILURE)(name, type, oplist) + +/* Stop processing with a compilation failure */ +#define ISHAREDI_PTR_DEF_FAILURE(name, type, oplist) \ + 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) \ \ typedef type *M_C(name,_t); \ typedef type M_C(name, _type_t); \ diff --git a/m-prioqueue.h b/m-prioqueue.h index 393553e6..794bf7c9 100644 --- a/m-prioqueue.h +++ b/m-prioqueue.h @@ -52,7 +52,6 @@ /* Deferred evaluation for the definition, so that all arguments are evaluated before further expansion */ #define PRIOQUEUEI_OPLIST_P1(arg) PRIOQUEUEI_OPLIST_P2 arg -#define PRIOQUEUEI_DEF_P1(arg) PRIOQUEUEI_DEF_P2 arg /* Define oplist of a priority queue */ #define PRIOQUEUEI_OPLIST_P2(name, oplist) \ @@ -74,6 +73,19 @@ ,GET_SIZE(M_C(name, _size)) \ ) + +/* Deferred evaluation for the definition, + so that all arguments are evaluated before further expansion */ +#define PRIOQUEUEI_DEF_P1(arg) PRIOQUEUEI_DEF_P2 arg + +/* Validate the oplist before going further */ +#define PRIOQUEUEI_DEF_P2(name, type, oplist, prioqueue_t, it_t) \ + M_IF_OPLIST(oplist)(PRIOQUEUEI_DEF_P3, PRIOQUEUEI_DEF_FAILURE)(name, type, oplist, prioqueue_t, it_t) + +/* Stop processing with a compilation failure */ +#define PRIOQUEUEI_DEF_FAILURE(name, type, oplist, prioqueue_t, it_t) \ + M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(PRIOQUEUE_DEF): the given argument is not a valid oplist: " #oplist) + /* Define the priority queue: - name: prefix to use, - type: type of the contained objects, @@ -81,7 +93,7 @@ - prioqueue_t: type of the container, - it_t: iterator of the container */ -#define PRIOQUEUEI_DEF_P2(name, type, oplist, prioqueue_t, it_t) \ +#define PRIOQUEUEI_DEF_P3(name, type, oplist, prioqueue_t, it_t) \ ARRAY_DEF(M_C(name, _array), type, oplist) \ \ typedef type M_C(name, _type_t); \ diff --git a/m-rbtree.h b/m-rbtree.h index 9848646d..ad51fedc 100644 --- a/m-rbtree.h +++ b/m-rbtree.h @@ -36,6 +36,7 @@ (name, __VA_ARGS__ , \ M_C(name, _t), M_C(name, _node_t), M_C(name, _it_t)))) + /* Define the oplist of a rbtree of type. USAGE: RBTREE_OPLIST(name [, oplist_of_the_type]) */ #define RBTREE_OPLIST(...) \ @@ -137,6 +138,14 @@ typedef enum { so that all arguments are evaluated before further expansion */ #define RBTREEI_DEF_P1(arg) RBTREEI_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) + +/* Stop processing with a compilation failure */ +#define RBTREEI_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 - name: prefix to be used - type: type of the elements of the array @@ -145,7 +154,7 @@ typedef enum { - it_t: alias for M_C(name, _it_t) [ iterator of the container ] - node_t: alias for M_C(name, _node_t) [ node ] */ -#define RBTREEI_DEF_P2(name, type, oplist, tree_t, node_t, it_t) \ +#define RBTREEI_DEF_P3(name, type, oplist, tree_t, node_t, it_t) \ \ typedef struct M_C(name, _node_s) { \ struct M_C(name, _node_s) *child[2]; \ @@ -187,9 +196,9 @@ typedef enum { M_CALL_DEL(oplist, ptr); \ } ) \ \ - RBTREEI_DEF_P3(name, type, oplist, tree_t, node_t, it_t) + RBTREEI_DEF_P4(name, type, oplist, tree_t, node_t, it_t) -#define RBTREEI_DEF_P3(name, type, oplist, tree_t, node_t, it_t) \ +#define RBTREEI_DEF_P4(name, type, oplist, tree_t, node_t, it_t) \ \ static inline void \ M_C(name, _init)(tree_t tree) \ diff --git a/m-shared.h b/m-shared.h index a51b2578..b068c2ed 100644 --- a/m-shared.h +++ b/m-shared.h @@ -36,6 +36,7 @@ ((__VA_ARGS__, M_DEFAULT_OPLIST ), \ _OPLIST(__VA_ARGS__ ))) + /* Define shared pointer and its function. USAGE: SHARED_PTR_DEF(name, type, [, oplist]) */ #define SHARED_PTR_DEF(name, ...) \ @@ -43,6 +44,7 @@ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_ATOMIC_OPLIST ), \ (name, __VA_ARGS__ , SHAREDI_ATOMIC_OPLIST))) + /* Define relaxed shared pointer and its function (thread unsafe). USAGE: SHARED_PTR_RELAXED_DEF(name, type, [, oplist]) */ #define SHARED_PTR_RELAXED_DEF(name, ...) \ @@ -50,6 +52,7 @@ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), SHAREDI_INTEGER_OPLIST ), \ (name, __VA_ARGS__ , SHAREDI_INTEGER_OPLIST))) + /* Define shared resource and its function. This is a bounded pool of resource shared by multiple owners. USAGE: SHARED_RESOURCE_DEF(name, type, [, oplist]) */ @@ -62,7 +65,7 @@ /********************************** INTERNAL ************************************/ -// deferred +// deferred evaluation #define SHAREDI_PTR_OPLIST_P1(arg) SHAREDI_PTR_OPLIST_P2 arg #define SHAREDI_PTR_OPLIST_P2(name, oplist) ( \ @@ -79,9 +82,6 @@ ,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \ ) -// deferred -#define SHAREDI_PTR_DEF_P1(arg) SHAREDI_PTR_DEF_P2 arg - // OPLIST to handle a counter of atomic type #define SHAREDI_ATOMIC_OPLIST (TYPE(atomic_int), \ INIT_SET(atomic_init), \ @@ -89,23 +89,38 @@ SUB(atomic_fetch_sub), \ IT_CREF(atomic_load)) -// OPLIST to handle a counter of non-atomic type with its helper functions. +// 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)) + +/* 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; } +/* Contract of a shared pointer */ #define SHAREDI_CONTRACT(shared, cpt_oplist) do { \ assert(shared != NULL); \ assert(*shared == NULL || M_CALL_IT_CREF(cpt_oplist, &(*shared)->cpt) >= 1); \ } while (0) -#define SHAREDI_PTR_DEF_P2(name, type, oplist, cpt_oplist) \ +// deferred evaluation +#define SHAREDI_PTR_DEF_P1(arg) SHAREDI_PTR_DEF_P2 arg + +/* Validate the oplist before going further */ +#define SHAREDI_PTR_DEF_P2(name, type, oplist, cpt_oplist_t) \ + M_IF_OPLIST(oplist)(SHAREDI_PTR_DEF_P3, SHAREDI_PTR_DEF_FAILURE)(name, type, oplist, cpt_oplist_t) + +/* Stop processing with a compilation failure */ +#define SHAREDI_PTR_DEF_FAILURE(name, type, oplist, cpt_oplist) \ + 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) \ \ typedef struct M_C(name, _s){ \ type *data; /* Pointer to the data */ \ @@ -299,7 +314,15 @@ static inline int sharedi_integer_cref(int *p) { return *p; } // deferred #define SHAREDI_RESOURCE_DEF_P1(arg) SHAREDI_RESOURCE_DEF_P2 arg -#define SHAREDI_RESOURCE_DEF_P2(name, type, oplist) \ +/* Validate the oplist before going further */ +#define SHAREDI_RESOURCE_DEF_P2(name, type, oplist) \ + M_IF_OPLIST(oplist)(SHAREDI_RESOURCE_DEF_P3, SHAREDI_RESOURCE_DEF_FAILURE)(name, type, oplist) + +/* Stop processing with a compilation failure */ +#define SHAREDI_RESOURCE_DEF_FAILURE(name, type, oplist) \ + 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) \ \ /* Create an aligned type to avoid false sharing between threads */ \ typedef struct M_C(name, _atype_s) { \ diff --git a/m-snapshot.h b/m-snapshot.h index 091c8fa9..7110e0d1 100644 --- a/m-snapshot.h +++ b/m-snapshot.h @@ -36,6 +36,7 @@ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ (name, __VA_ARGS__ ))) + /* Define a Single Producer Multiple Consummer snapshot and its functions USAGE: SNAPSHOT_SPMC_DEF(name, type[, oplist]) */ #define SNAPSHOT_SPMC_DEF(name, ...) \ @@ -43,6 +44,7 @@ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ (name, __VA_ARGS__ ))) + /* Define a Multiple Producer Multiple Consummer snapshot and its functions USAGE: SNAPSHOT_MPMC_DEF(name, type[, oplist]) */ #define SNAPSHOT_MPMC_DEF(name, ...) \ @@ -50,6 +52,7 @@ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ (name, __VA_ARGS__ ))) + /* Define the oplist of a snapshot (SPSC, SPMC or MPMC). USAGE: SNAPSHOT_OPLIST(name[, oplist]) */ #define SNAPSHOT_OPLIST(...) \ @@ -109,14 +112,22 @@ SNAPSHOTI_SPSC_FLAGS_CONTRACT(f); \ } while (0) -// Defered evaluation of the arguments. -#define SNAPSHOTI_SPSC_DEF_P1(arg) SNAPSHOTI_SPSC_DEF_P2 arg - // 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 SNAPSHOTI_SPSC_DEF_P2(name, type, oplist) \ +// Defered evaluation of the arguments. +#define SNAPSHOTI_SPSC_DEF_P1(arg) SNAPSHOTI_SPSC_DEF_P2 arg + +/* Validate the oplist before going further */ +#define SNAPSHOTI_SPSC_DEF_P2(name, type, oplist) \ + M_IF_OPLIST(oplist)(SNAPSHOTI_SPSC_DEF_P3, SNAPSHOTI_SPSC_DEF_FAILURE)(name, type, oplist) + +/* Stop processing with a compilation failure */ +#define SNAPSHOTI_SPSC_DEF_FAILURE(name, type, oplist) \ + M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_SPSC_DEF): the given argument is not a valid oplist: " #oplist) + +#define SNAPSHOTI_SPSC_DEF_P3(name, type, oplist) \ \ /* Create an aligned type to avoid false sharing between threads */ \ typedef struct M_C(name, _aligned_type_s) { \ @@ -490,7 +501,15 @@ static inline void snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned in // Defered evaluation #define SNAPSHOTI_SPMC_DEF_P1(arg) SNAPSHOTI_SPMC_DEF_P2 arg -#define SNAPSHOTI_SPMC_DEF_P2(name, type, oplist) \ +/* Validate the oplist before going further */ +#define SNAPSHOTI_SPMC_DEF_P2(name, type, oplist) \ + M_IF_OPLIST(oplist)(SNAPSHOTI_SPMC_DEF_P3, SNAPSHOTI_SPMC_DEF_FAILURE)(name, type, oplist) + +/* Stop processing with a compilation failure */ +#define SNAPSHOTI_SPMC_DEF_FAILURE(name, type, oplist) \ + M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_SPMC_DEF): the given argument is not a valid oplist: " #oplist) + +#define SNAPSHOTI_SPMC_DEF_P3(name, type, oplist) \ \ /* Create an aligned type to avoid false sharing between threads */ \ typedef struct M_C(name, _aligned_type_s) { \ @@ -579,7 +598,15 @@ static inline void snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned in // Defered evaluation #define SNAPSHOTI_MPMC_DEF_P1(arg) SNAPSHOTI_MPMC_DEF_P2 arg -#define SNAPSHOTI_MPMC_DEF_P2(name, type, oplist) \ +/* Validate the oplist before going further */ +#define SNAPSHOTI_MPMC_DEF_P2(name, type, oplist) \ + M_IF_OPLIST(oplist)(SNAPSHOTI_MPMC_DEF_P3, SNAPSHOTI_MPMC_DEF_FAILURE)(name, type, oplist) + +/* Stop processing with a compilation failure */ +#define SNAPSHOTI_MPMC_DEF_FAILURE(name, type, oplist) \ + M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_MPMC_DEF): the given argument is not a valid oplist: " #oplist) + +#define SNAPSHOTI_MPMC_DEF_P3(name, type, oplist) \ \ SNAPSHOTI_SPMC_DEF_P1((M_C(name, _mrsw), type, oplist)) \ \