Replace TAB by SPACE

This commit is contained in:
Patrick Pelissier committed 2020-07-25 19:17:25 +02:00
1 parent efef35c1e1
commit 5f9feb833c
10 files changed
+1067 -1061

No files matched your search

+7 -7
View File
@@ -127,7 +127,7 @@ using std::memory_order_seq_cst;
*/ */
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) ) \ #elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) ) \
|| (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__cplusplus) && (__GNUC__*100 + __GNUC_MINOR__) >= 409) \ || (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__cplusplus) && (__GNUC__*100 + __GNUC_MINOR__) >= 409) \
|| (defined(__clang__) && __clang_major__ >= 4) \ || (defined(__clang__) && __clang_major__ >= 4) \
|| (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1800) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1800)
#include <stdatomic.h> #include <stdatomic.h>
@@ -166,12 +166,12 @@ M_BEGIN_PROTECTED_CODE
_lock : the mutex lock. _lock : the mutex lock.
Support up to sizeof (long long) type. Support up to sizeof (long long) type.
*/ */
#define _Atomic(T) \ #define _Atomic(T) \
struct { \ struct { \
T volatile _val; \ T volatile _val; \
T _zero; \ T _zero; \
T _previous; \ T _previous; \
m_mutex_t _lock; \ m_mutex_t _lock; \
} }
/* Define the supported memory order. /* Define the supported memory order.
+251 -248
View File
@@ -63,14 +63,14 @@ typedef enum {
USAGE: BUFFER_OPLIST(name[, oplist of the type]) */ USAGE: BUFFER_OPLIST(name[, oplist of the type]) */
#define BUFFER_OPLIST(...) \ #define BUFFER_OPLIST(...) \
BUFFERI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ BUFFERI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST), \ ((__VA_ARGS__, M_DEFAULT_OPLIST), \
(__VA_ARGS__ ))) (__VA_ARGS__ )))
/* Define a nearly lock-free queue for Many Producer Many Consummer /* Define a nearly lock-free queue for Many Producer Many Consummer
Much faster than queue of BUFFER_DEF in heavy communication scenario Much faster than queue of BUFFER_DEF in heavy communication scenario
Size of created queue can only a power of 2. Size of created queue can only a power of 2.
*/ */
#define QUEUE_MPMC_DEF(name, type, ...) \ #define QUEUE_MPMC_DEF(name, type, ...) \
M_BEGIN_PROTECTED_CODE \ M_BEGIN_PROTECTED_CODE \
QUEUEI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ QUEUEI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, type, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), M_C(name,_t)), \ ((name, type, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), M_C(name,_t)), \
@@ -81,7 +81,7 @@ typedef enum {
Much faster than queue of BUFFER_DEF in heavy communication scenario Much faster than queue of BUFFER_DEF in heavy communication scenario
Size of created queue can only a power of 2. Size of created queue can only a power of 2.
*/ */
#define QUEUE_SPSC_DEF(name, type, ...) \ #define QUEUE_SPSC_DEF(name, type, ...) \
M_BEGIN_PROTECTED_CODE \ M_BEGIN_PROTECTED_CODE \
QUEUEI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ QUEUEI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, type, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), M_C(name,_t)), \ ((name, type, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), M_C(name,_t)), \
@@ -99,13 +99,13 @@ typedef enum {
#define BUFFERI_POLICY_P(policy, val) \ #define BUFFERI_POLICY_P(policy, val) \
(((policy) & (val)) != 0) (((policy) & (val)) != 0)
#define BUFFERI_CONTRACT(buffer, size) do { \ #define BUFFERI_CONTRACT(buffer, size) do { \
assert (buffer != NULL); \ assert (buffer != NULL); \
assert (buffer->data != NULL); \ assert (buffer->data != NULL); \
}while (0) }while (0)
#define BUFFERI_PROTECTED_CONTRACT(buffer, size) do { \ #define BUFFERI_PROTECTED_CONTRACT(buffer, size) do { \
assert (atomic_load(&buffer->number[0]) <= BUFFERI_SIZE(size)); \ assert (atomic_load(&buffer->number[0]) <= BUFFERI_SIZE(size)); \
} while (0) } while (0)
/* Deferred evaluation for the definition, /* Deferred evaluation for the definition,
@@ -122,7 +122,7 @@ typedef enum {
#define BUFFERI_DEF_P3(name, type, m_size, policy, oplist, buffer_t) \ #define BUFFERI_DEF_P3(name, type, m_size, policy, oplist, buffer_t) \
\ \
typedef struct M_C(name, _s) { \ typedef struct M_C(name, _s) { \
m_mutex_t mutexPush; /* MUTEX used for pushing elements */ \ m_mutex_t mutexPush; /* MUTEX used for pushing elements */ \
size_t idx_prod; /* Index of the production threads */ \ size_t idx_prod; /* Index of the production threads */ \
size_t overwrite; /* Number of overwritten values */ \ size_t overwrite; /* Number of overwritten values */ \
@@ -158,9 +158,11 @@ M_C(name, _init)(buffer_t v, size_t size) \
m_mutex_init(v->mutexPop); \ m_mutex_init(v->mutexPop); \
m_cond_init(v->there_is_data); \ m_cond_init(v->there_is_data); \
m_cond_init(v->there_is_room_for_data); \ m_cond_init(v->there_is_room_for_data); \
} else \ } else { \
assert(BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING)); \ assert(BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING)); \
BUFFERI_IF_CTE_SIZE(m_size)( , \ } \
\
BUFFERI_IF_CTE_SIZE(m_size)( /* Statically allocated */ , \
v->data = M_CALL_REALLOC(oplist, type, NULL, BUFFERI_SIZE(m_size)); \ v->data = M_CALL_REALLOC(oplist, type, NULL, BUFFERI_SIZE(m_size)); \
if (v->data == NULL) { \ if (v->data == NULL) { \
M_MEMORY_FULL (BUFFERI_SIZE(m_size)*sizeof(type)); \ M_MEMORY_FULL (BUFFERI_SIZE(m_size)*sizeof(type)); \
@@ -168,12 +170,12 @@ M_C(name, _init)(buffer_t v, size_t size) \
} \ } \
) \ ) \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(size_t i = 0; i < size; i++) { \ for(size_t i = 0; i < size; i++) { \
M_CALL_INIT(oplist, v->data[i]); \ M_CALL_INIT(oplist, v->data[i]); \
} \ } \
} \ } \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
} \ } \
\ \
BUFFERI_IF_CTE_SIZE(m_size)( \ BUFFERI_IF_CTE_SIZE(m_size)( \
static inline void \ static inline void \
@@ -184,13 +186,13 @@ M_C(name, _init)(buffer_t v, size_t size) \
, ) \ , ) \
\ \
static inline void \ static inline void \
M_C(name, _int_clear_obj)(buffer_t v) \ M_C(name, _int_clear_obj)(buffer_t v) \
{ \ { \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \ for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \
M_CALL_CLEAR(oplist, v->data[i]); \ M_CALL_CLEAR(oplist, v->data[i]); \
} \ } \
} else { \ } else { \
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \ size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
while (i != v->idx_prod) { \ while (i != v->idx_prod) { \
@@ -201,17 +203,17 @@ M_C(name, _init)(buffer_t v, size_t size) \
} \ } \
} \ } \
v->idx_prod = v->idx_cons = 0; \ v->idx_prod = v->idx_cons = 0; \
atomic_store_explicit (&v->number[0], 0UL, memory_order_relaxed); \ atomic_store_explicit (&v->number[0], 0UL, memory_order_relaxed); \
if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \ if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
atomic_store_explicit(&v->number[1], 0UL, memory_order_relaxed); \ atomic_store_explicit(&v->number[1], 0UL, memory_order_relaxed); \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _clear)(buffer_t v) \ M_C(name, _clear)(buffer_t v) \
{ \ { \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
M_C(name, _int_clear_obj)(v); \ M_C(name, _int_clear_obj)(v); \
BUFFERI_IF_CTE_SIZE(m_size)( , \ BUFFERI_IF_CTE_SIZE(m_size)( , \
M_CALL_FREE(oplist, v->data); \ M_CALL_FREE(oplist, v->data); \
v->data = NULL; \ v->data = NULL; \
@@ -224,30 +226,30 @@ M_C(name, _init)(buffer_t v, size_t size) \
m_cond_clear(v->there_is_room_for_data); \ m_cond_clear(v->there_is_room_for_data); \
} \ } \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _clean)(buffer_t v) \ M_C(name, _clean)(buffer_t v) \
{ \ { \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
m_mutex_lock(v->mutexPush); \ m_mutex_lock(v->mutexPush); \
m_mutex_lock(v->mutexPop); \ m_mutex_lock(v->mutexPop); \
} \ } \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \ BUFFERI_PROTECTED_CONTRACT(v, m_size); \
if (BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) \ if (BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) \
M_C(name, _int_clear_obj)(v); \ M_C(name, _int_clear_obj)(v); \
v->idx_prod = v->idx_cons = 0; \ v->idx_prod = v->idx_cons = 0; \
atomic_store_explicit (&v->number[0], 0UL, memory_order_relaxed); \ atomic_store_explicit (&v->number[0], 0UL, memory_order_relaxed); \
if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \ if (BUFFERI_POLICY_P(policy, BUFFER_DEFERRED_POP)) \
atomic_store_explicit(&v->number[1], 0UL, memory_order_relaxed); \ atomic_store_explicit(&v->number[1], 0UL, memory_order_relaxed); \
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
m_cond_broadcast(v->there_is_room_for_data); \ m_cond_broadcast(v->there_is_room_for_data); \
m_mutex_unlock(v->mutexPop); \ m_mutex_unlock(v->mutexPop); \
m_mutex_unlock(v->mutexPush); \ m_mutex_unlock(v->mutexPush); \
} \ } \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _init_set)(buffer_t dest, const buffer_t src) \ M_C(name, _init_set)(buffer_t dest, const buffer_t src) \
{ \ { \
@@ -263,11 +265,11 @@ M_C(name, _init)(buffer_t v, size_t size) \
m_mutex_lock(v->mutexPop); \ m_mutex_lock(v->mutexPop); \
} \ } \
\ \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \ BUFFERI_PROTECTED_CONTRACT(v, m_size); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \ for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \
M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \ M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \
} \ } \
} else { \ } else { \
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \ size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
while (i != v->idx_prod) { \ while (i != v->idx_prod) { \
@@ -291,7 +293,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
BUFFERI_CONTRACT(dest, m_size); \ BUFFERI_CONTRACT(dest, m_size); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _set)(buffer_t dest, const buffer_t src) \ M_C(name, _set)(buffer_t dest, const buffer_t src) \
{ \ { \
@@ -319,13 +321,13 @@ M_C(name, _init)(buffer_t v, size_t size) \
} \ } \
} \ } \
\ \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \ BUFFERI_PROTECTED_CONTRACT(v, m_size); \
M_C(name, _int_clear_obj)(dest); \ M_C(name, _int_clear_obj)(dest); \
\ \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \ for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \
M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \ M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \
} \ } \
} else { \ } else { \
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \ size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
while (i != v->idx_prod) { \ while (i != v->idx_prod) { \
@@ -361,11 +363,11 @@ M_C(name, _init)(buffer_t v, size_t size) \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
BUFFERI_CONTRACT(dest, m_size); \ BUFFERI_CONTRACT(dest, m_size); \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _empty_p)(buffer_t v) \ M_C(name, _empty_p)(buffer_t v) \
{ \ { \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
/* If the buffer has been configured with deferred pop \ /* If the buffer has been configured with deferred pop \
we considered the queue as empty when the number of \ we considered the queue as empty when the number of \
deferred pop has reached 0, not the number of items in the \ deferred pop has reached 0, not the number of items in the \
@@ -375,32 +377,32 @@ M_C(name, _init)(buffer_t v, size_t size) \
else \ else \
return atomic_load_explicit (&v->number[0], memory_order_relaxed) == 0; \ return atomic_load_explicit (&v->number[0], memory_order_relaxed) == 0; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _full_p)(buffer_t v) \ M_C(name, _full_p)(buffer_t v) \
{ \ { \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
return atomic_load_explicit (&v->number[0], memory_order_relaxed) \ return atomic_load_explicit (&v->number[0], memory_order_relaxed) \
== BUFFERI_SIZE(m_size); \ == BUFFERI_SIZE(m_size); \
} \ } \
\ \
static inline size_t \ static inline size_t \
M_C(name, _size)(buffer_t v) \ M_C(name, _size)(buffer_t v) \
{ \ { \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
return atomic_load_explicit (&v->number[0], memory_order_relaxed); \ return atomic_load_explicit (&v->number[0], memory_order_relaxed); \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _push_blocking)(buffer_t v, type const data, bool blocking) \ M_C(name, _push_blocking)(buffer_t v, type const data, bool blocking) \
{ \ { \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
\ \
/* BUFFER lock */ \ /* BUFFER lock */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
m_mutex_lock(v->mutexPush); \ m_mutex_lock(v->mutexPush); \
while (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \ while (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
&& M_C(name, _full_p)(v)) { \ && M_C(name, _full_p)(v)) { \
if (!blocking) { \ if (!blocking) { \
m_mutex_unlock(v->mutexPush); \ m_mutex_unlock(v->mutexPush); \
return false; \ return false; \
@@ -408,15 +410,15 @@ M_C(name, _init)(buffer_t v, size_t size) \
m_cond_wait(v->there_is_room_for_data, v->mutexPush); \ m_cond_wait(v->there_is_room_for_data, v->mutexPush); \
} \ } \
} else if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \ } else if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
&& M_C(name, _full_p)(v)) \ && M_C(name, _full_p)(v)) \
return false; \ return false; \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \ BUFFERI_PROTECTED_CONTRACT(v, m_size); \
\ \
size_t previousSize, idx = v->idx_prod; \ size_t previousSize, idx = v->idx_prod; \
/* INDEX computation if we have to overwrite the last element */ \ /* INDEX computation if we have to overwrite the last element */ \
if (M_UNLIKELY (BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \ if (M_UNLIKELY (BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
&& M_C(name, _full_p)(v))) { \ && M_C(name, _full_p)(v))) { \
v->overwrite++; \ v->overwrite++; \
/* Let's overwrite the last element */ \ /* Let's overwrite the last element */ \
/* Compute the index of the last push element */ \ /* Compute the index of the last push element */ \
idx--; \ idx--; \
@@ -424,7 +426,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
idx = idx >= BUFFERI_SIZE(m_size) ? BUFFERI_SIZE(m_size)-1 : idx; \ idx = idx >= BUFFERI_SIZE(m_size) ? BUFFERI_SIZE(m_size)-1 : idx; \
} \ } \
/* Update data in the buffer */ \ /* Update data in the buffer */ \
M_CALL_SET(oplist, v->data[idx], data); \ M_CALL_SET(oplist, v->data[idx], data); \
previousSize = BUFFERI_SIZE(m_size); \ previousSize = BUFFERI_SIZE(m_size); \
\ \
} else { \ } else { \
@@ -449,13 +451,13 @@ M_C(name, _init)(buffer_t v, size_t size) \
thread which has the push lock. As such, it has to be handled \ thread which has the push lock. As such, it has to be handled \
like an atomic variable. */ \ like an atomic variable. */ \
/* Increment number of elements of the buffer */ \ /* Increment number of elements of the buffer */ \
previousSize = atomic_fetch_add (&v->number[0], 1UL); \ previousSize = atomic_fetch_add (&v->number[0], 1UL); \
if (BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \ if (BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
previousSize = atomic_fetch_add (&v->number[1], 1UL); \ previousSize = atomic_fetch_add (&v->number[1], 1UL); \
} \ } \
} \ } \
\ \
/* BUFFER unlock */ \ /* BUFFER unlock */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
m_mutex_unlock(v->mutexPush); \ m_mutex_unlock(v->mutexPush); \
/* If the number of items in the buffer was 0, some consummer \ /* If the number of items in the buffer was 0, some consummer \
@@ -467,35 +469,35 @@ M_C(name, _init)(buffer_t v, size_t size) \
m_mutex_unlock(v->mutexPop); \ m_mutex_unlock(v->mutexPop); \
} \ } \
} \ } \
\ \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
return true; \ return true; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _pop_blocking)(type *data, buffer_t v, bool blocking) \ M_C(name, _pop_blocking)(type *data, buffer_t v, bool blocking) \
{ \ { \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
assert (data != NULL); \ assert (data != NULL); \
\ \
/* BUFFER lock */ \ /* BUFFER lock */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
m_mutex_lock(v->mutexPop); \ m_mutex_lock(v->mutexPop); \
while (M_C(name, _empty_p)(v)) { \ while (M_C(name, _empty_p)(v)) { \
if (!blocking) { \ if (!blocking) { \
m_mutex_unlock(v->mutexPop); \ m_mutex_unlock(v->mutexPop); \
return false; \ return false; \
} \ } \
m_cond_wait(v->there_is_data, v->mutexPop); \ m_cond_wait(v->there_is_data, v->mutexPop); \
} \ } \
} else if (M_C(name, _empty_p)(v)) \ } else if (M_C(name, _empty_p)(v)) \
return false; \ return false; \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \ BUFFERI_PROTECTED_CONTRACT(v, m_size); \
\ \
/* POP data from the buffer and update INDEX */ \ /* POP data from the buffer and update INDEX */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_STACK)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_STACK)) { \
/* FIFO queue */ \ /* FIFO queue */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, *data, v->data[v->idx_cons]); \ M_CALL_SET(oplist, *data, v->data[v->idx_cons]); \
} else { \ } else { \
M_DO_INIT_MOVE (oplist, *data, v->data[v->idx_cons]); \ M_DO_INIT_MOVE (oplist, *data, v->data[v->idx_cons]); \
@@ -518,12 +520,12 @@ M_C(name, _init)(buffer_t v, size_t size) \
/* Decrement number of elements in the buffer */ \ /* Decrement number of elements in the buffer */ \
size_t previousSize; \ size_t previousSize; \
if (!BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
previousSize = atomic_fetch_sub (&v->number[0], 1UL); \ previousSize = atomic_fetch_sub (&v->number[0], 1UL); \
} else { \ } else { \
atomic_fetch_sub (&v->number[1], 1UL); \ atomic_fetch_sub (&v->number[1], 1UL); \
} \ } \
\ \
/* BUFFER unlock */ \ /* BUFFER unlock */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
m_mutex_unlock(v->mutexPop); \ m_mutex_unlock(v->mutexPop); \
/* If the number of items in the buffer was the max, some producer \ /* If the number of items in the buffer was the max, some producer \
@@ -536,31 +538,31 @@ M_C(name, _init)(buffer_t v, size_t size) \
m_mutex_unlock(v->mutexPush); \ m_mutex_unlock(v->mutexPush); \
} \ } \
} \ } \
\ \
BUFFERI_CONTRACT(v,m_size); \ BUFFERI_CONTRACT(v,m_size); \
return true; \ return true; \
} \ } \
\ \
\ \
static inline bool \ static inline bool \
M_C(name, _push)(buffer_t v, type const data) \ M_C(name, _push)(buffer_t v, type const data) \
{ \ { \
return M_C(name, _push_blocking)(v, data, \ return M_C(name, _push_blocking)(v, data, \
!BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING_PUSH)); \ !BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING_PUSH)); \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _pop)(type *data, buffer_t v) \ M_C(name, _pop)(type *data, buffer_t v) \
{ \ { \
return M_C(name, _pop_blocking)(data, v, \ return M_C(name, _pop_blocking)(data, v, \
!BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING_POP)); \ !BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING_POP)); \
} \ } \
\ \
static inline size_t \ static inline size_t \
M_C(name, _overwrite)(const buffer_t v) \ M_C(name, _overwrite)(const buffer_t v) \
{ \ { \
return v->overwrite; \ return v->overwrite; \
} \ } \
\ \
static inline size_t \ static inline size_t \
M_C(name, _capacity)(const buffer_t v) \ M_C(name, _capacity)(const buffer_t v) \
@@ -574,7 +576,7 @@ M_C(name, _init)(buffer_t v, size_t size) \
{ \ { \
/* Decrement the effective number of elements in the buffer */ \ /* Decrement the effective number of elements in the buffer */ \
if (BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \ if (BUFFERI_POLICY_P((policy), BUFFER_DEFERRED_POP)) { \
size_t previousSize = atomic_fetch_sub (&v->number[0], 1UL); \ size_t previousSize = atomic_fetch_sub (&v->number[0], 1UL); \
if (previousSize == BUFFERI_SIZE(m_size)) { \ if (previousSize == BUFFERI_SIZE(m_size)) { \
m_mutex_lock(v->mutexPush); \ m_mutex_lock(v->mutexPush); \
m_cond_broadcast(v->there_is_room_for_data); \ m_cond_broadcast(v->there_is_room_for_data); \
@@ -600,11 +602,11 @@ M_C(name, _init)(buffer_t v, size_t size) \
#define QUEUEI_MPMC_DEF_P1(arg) QUEUEI_MPMC_DEF_P2 arg #define QUEUEI_MPMC_DEF_P1(arg) QUEUEI_MPMC_DEF_P2 arg
/* Validate the value oplist before going further */ /* Validate the value oplist before going further */
#define QUEUEI_MPMC_DEF_P2(name, type, policy, oplist, buffer_t) \ #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) M_IF_OPLIST(oplist)(QUEUEI_MPMC_DEF_P3, QUEUEI_MPMC_DEF_FAILURE)(name, type, policy, oplist, buffer_t)
/* Stop processing with a compilation failure */ /* Stop processing with a compilation failure */
#define QUEUEI_MPMC_DEF_FAILURE(name, type, policy, oplist, buffer_t) \ #define QUEUEI_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)) 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 #ifdef NDEBUG
@@ -621,54 +623,55 @@ M_C(name, _init)(buffer_t v, size_t size) \
} while (0) } while (0)
#endif #endif
#define QUEUEI_MPMC_DEF_P3(name, type, policy, oplist, buffer_t) \ #define QUEUEI_MPMC_DEF_P3(name, type, policy, oplist, buffer_t) \
\ \
/* The sequence number of an element will be equal to either \ /* The sequence number of an element will be equal to either \
- 2* the index of the production which creates it, \ - 2* the index of the production which creates it, \
- 1 + 2* the index of the consumption which consummes it \ - 1 + 2* the index of the consumption which consummes it \
In case of wrapping, as there is no order comparison but only \ In case of wrapping, as there is no order comparison but only \
equal comparison, there is no special issue. \ equal comparison, there is no special issue. \
Each element is put in a separate cache line to avoid false \ Each element is put in a separate cache line to avoid false \
sharing. \ sharing. \
*/ \ */ \
typedef struct M_C(name, _el_s) { \ typedef struct M_C(name, _el_s) { \
atomic_uint seq; /* Can only increase until wrapping */ \ atomic_uint seq; /* Can only increase until wrapping */ \
type x; \ type x; \
M_CACHELINE_ALIGN(align, atomic_uint, type); \ M_CACHELINE_ALIGN(align, atomic_uint, type); \
} M_C(name, _el_t); \ } M_C(name, _el_t); \
\ \
/* If there is only one producer and one consummer, then they won't \ /* If there is only one producer and one consummer, then they won't \
typically use the same cache line, increasing performance. */ \ typically use the same cache line, increasing performance. */ \
typedef struct M_C(name, _s) { \ typedef struct M_C(name, _s) { \
atomic_uint ProdIdx; /* Can only increase until wrapping */ \ atomic_uint ProdIdx; /* Can only increase until wrapping */ \
M_CACHELINE_ALIGN(align1, atomic_uint); \ M_CACHELINE_ALIGN(align1, atomic_uint); \
atomic_uint ConsoIdx; /* Can only increase until wrapping */ \ atomic_uint ConsoIdx; /* Can only increase until wrapping */ \
M_CACHELINE_ALIGN(align2, atomic_uint); \ M_CACHELINE_ALIGN(align2, atomic_uint); \
M_C(name, _el_t) *Tab; \ M_C(name, _el_t) *Tab; \
unsigned int size; \ unsigned int size; \
} buffer_t[1]; \ } buffer_t[1]; \
\ \
static inline bool \ static inline bool \
M_C(name, _push)(buffer_t table, type const x) \ M_C(name, _push)(buffer_t table, type const x) \
{ \ { \
QUEUEI_MPMC_CONTRACT(table); \ QUEUEI_MPMC_CONTRACT(table); \
unsigned int idx = atomic_load_explicit(&table->ProdIdx, \ unsigned int idx = atomic_load_explicit(&table->ProdIdx, \
memory_order_relaxed); \ memory_order_relaxed); \
const unsigned int i = idx & (table->size -1); \ const unsigned int i = idx & (table->size -1); \
const unsigned int seq = atomic_load_explicit(&table->Tab[i].seq, \ const unsigned int seq = atomic_load_explicit(&table->Tab[i].seq, \
memory_order_acquire); \ memory_order_acquire); \
if (M_UNLIKELY (2*(idx - table->size) + 1 != seq)) { \ if (M_UNLIKELY (2*(idx - table->size) + 1 != seq)) { \
/* Buffer full (or unlikely preemption). Can not push */ \ /* Buffer full (or unlikely preemption). Can not push */ \
return false; \ return false; \
} \ } \
if (M_UNLIKELY (!atomic_compare_exchange_strong_explicit(&table->ProdIdx, \ if (M_UNLIKELY (!atomic_compare_exchange_strong_explicit(&table->ProdIdx, \
&idx, idx+1, memory_order_relaxed, memory_order_relaxed))) { \ &idx, idx+1, memory_order_relaxed, memory_order_relaxed))) { \
/* Thread has been preempted by another one. */ \ /* Thread has been preempted by another one. */ \
return false; \ return false; \
} \ } \
/* If it is interrupted here, it may block pop method (not push) */ \ /* If it is interrupted here, it may block pop method (not push) */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, table->Tab[i].x, x); \ M_CALL_SET(oplist, table->Tab[i].x, x); \
} else { \ } else { \
M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \ M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \
} \ } \
@@ -676,27 +679,27 @@ M_C(name, _init)(buffer_t v, size_t size) \
atomic_store_explicit(&table->Tab[i].seq, 2*idx, memory_order_release); \ atomic_store_explicit(&table->Tab[i].seq, 2*idx, memory_order_release); \
QUEUEI_MPMC_CONTRACT(table); \ QUEUEI_MPMC_CONTRACT(table); \
return true; \ return true; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _pop)(type *ptr, buffer_t table) \ M_C(name, _pop)(type *ptr, buffer_t table) \
{ \ { \
QUEUEI_MPMC_CONTRACT(table); \ QUEUEI_MPMC_CONTRACT(table); \
assert (ptr != NULL); \ assert (ptr != NULL); \
unsigned int iC = atomic_load_explicit(&table->ConsoIdx, \ unsigned int iC = atomic_load_explicit(&table->ConsoIdx, \
memory_order_relaxed); \ memory_order_relaxed); \
const unsigned int i = (iC & (table->size -1)); \ const unsigned int i = (iC & (table->size -1)); \
const unsigned int seq = atomic_load_explicit(&table->Tab[i].seq, \ const unsigned int seq = atomic_load_explicit(&table->Tab[i].seq, \
memory_order_acquire); \ memory_order_acquire); \
if (seq != 2 * iC) { \ if (seq != 2 * iC) { \
/* Nothing in buffer to consumme (or unlikely preemption) */ \ /* Nothing in buffer to consumme (or unlikely preemption) */ \
return false; \ return false; \
} \ } \
if (M_UNLIKELY (!atomic_compare_exchange_strong_explicit(&table->ConsoIdx, \ if (M_UNLIKELY (!atomic_compare_exchange_strong_explicit(&table->ConsoIdx, \
&iC, iC+1, memory_order_relaxed, memory_order_relaxed))) { \ &iC, iC+1, memory_order_relaxed, memory_order_relaxed))) { \
/* Thread has been preempted by another one */ \ /* Thread has been preempted by another one */ \
return false; \ return false; \
} \ } \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, *ptr, table->Tab[i].x); \ M_CALL_SET(oplist, *ptr, table->Tab[i].x); \
} else { \ } else { \
@@ -705,40 +708,40 @@ M_C(name, _init)(buffer_t v, size_t size) \
atomic_store_explicit(&table->Tab[i].seq, 2*iC + 1, memory_order_release); \ atomic_store_explicit(&table->Tab[i].seq, 2*iC + 1, memory_order_release); \
QUEUEI_MPMC_CONTRACT(table); \ QUEUEI_MPMC_CONTRACT(table); \
return true; \ return true; \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _init)(buffer_t buffer, size_t size) \ M_C(name, _init)(buffer_t buffer, size_t size) \
{ \ { \
assert (buffer != NULL); \ assert (buffer != NULL); \
assert( M_POWEROF2_P(size)); \ assert( M_POWEROF2_P(size)); \
assert (0 < size && size <= UINT_MAX); \ assert (0 < size && size <= UINT_MAX); \
assert(((policy) & (BUFFER_STACK|BUFFER_THREAD_UNSAFE|BUFFER_PUSH_OVERWRITE)) == 0); \ assert(((policy) & (BUFFER_STACK|BUFFER_THREAD_UNSAFE|BUFFER_PUSH_OVERWRITE)) == 0); \
atomic_init(&buffer->ProdIdx, (unsigned int) size); \ atomic_init(&buffer->ProdIdx, (unsigned int) size); \
atomic_init(&buffer->ConsoIdx, (unsigned int) size); \ atomic_init(&buffer->ConsoIdx, (unsigned int) size); \
buffer->size = (unsigned int) size; \ buffer->size = (unsigned int) size; \
buffer->Tab = M_CALL_REALLOC(oplist, M_C(name, _el_t), NULL, size); \ buffer->Tab = M_CALL_REALLOC(oplist, M_C(name, _el_t), NULL, size); \
if (buffer->Tab == NULL) { \ if (buffer->Tab == NULL) { \
M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \ M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \
return; \ return; \
} \ } \
for(unsigned int j = 0; j < (unsigned int) size; j++) { \ for(unsigned int j = 0; j < (unsigned int) size; j++) { \
atomic_init(&buffer->Tab[j].seq, 2*j+1U); \ atomic_init(&buffer->Tab[j].seq, 2*j+1U); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_INIT(oplist, buffer->Tab[j].x); \ M_CALL_INIT(oplist, buffer->Tab[j].x); \
} \ } \
} \ } \
QUEUEI_MPMC_CONTRACT(buffer); \ QUEUEI_MPMC_CONTRACT(buffer); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _clear)(buffer_t buffer) \ M_C(name, _clear)(buffer_t buffer) \
{ \ { \
QUEUEI_MPMC_CONTRACT(buffer); \ QUEUEI_MPMC_CONTRACT(buffer); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(unsigned int j = 0; j < buffer->size; j++) { \ for(unsigned int j = 0; j < buffer->size; j++) { \
M_CALL_CLEAR(oplist, buffer->Tab[j].x); \ M_CALL_CLEAR(oplist, buffer->Tab[j].x); \
} \ } \
} else { \ } else { \
unsigned int iP = atomic_load_explicit(&buffer->ProdIdx, memory_order_relaxed); \ unsigned int iP = atomic_load_explicit(&buffer->ProdIdx, memory_order_relaxed); \
unsigned int i = iP & (buffer->size -1); \ unsigned int i = iP & (buffer->size -1); \
@@ -751,19 +754,19 @@ M_C(name, _init)(buffer_t v, size_t size) \
j = 0; \ j = 0; \
} \ } \
} \ } \
M_CALL_FREE(oplist, buffer->Tab); \ M_CALL_FREE(oplist, buffer->Tab); \
buffer->Tab = NULL; /* safer */ \ buffer->Tab = NULL; /* safer */ \
} \ } \
\ \
static inline size_t \ static inline size_t \
M_C(name, _size)(buffer_t table) \ M_C(name, _size)(buffer_t table) \
{ \ { \
QUEUEI_MPMC_CONTRACT(table); \ QUEUEI_MPMC_CONTRACT(table); \
const unsigned int iC = atomic_load_explicit(&table->ConsoIdx, memory_order_relaxed); \ const unsigned int iC = atomic_load_explicit(&table->ConsoIdx, memory_order_relaxed); \
const unsigned int iP = atomic_load_explicit(&table->ProdIdx, memory_order_acquire); \ 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 \ /* We return an approximation as we can't read both iC & iP atomically \
As we read producer index after consummer index, \ As we read producer index after consummer index, \
and they are atomic variables without reordering \ and they are atomic variables without reordering \
producer index is always greater or equal than consumer index \ producer index is always greater or equal than consumer index \
(or on overflow occurs, in which case as we compute with modulo \ (or on overflow occurs, in which case as we compute with modulo \
arithmetic, the right result is computed). \ arithmetic, the right result is computed). \
@@ -771,27 +774,27 @@ M_C(name, _init)(buffer_t v, size_t size) \
if the function is interrupted a long time between reading iC & \ if the function is interrupted a long time between reading iC & \
iP. the function is not protected against it. \ iP. the function is not protected against it. \
*/ \ */ \
return iP-iC; \ return iP-iC; \
} \ } \
\ \
static inline size_t \ static inline size_t \
M_C(name, _capacity)(buffer_t v) \ M_C(name, _capacity)(buffer_t v) \
{ \ { \
QUEUEI_MPMC_CONTRACT(v); \ QUEUEI_MPMC_CONTRACT(v); \
return v->size; \ return v->size; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _empty_p)(buffer_t v) \ M_C(name, _empty_p)(buffer_t v) \
{ \ { \
return M_C(name, _size) (v) == 0; \ return M_C(name, _size) (v) == 0; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _full_p)(buffer_t v) \ M_C(name, _full_p)(buffer_t v) \
{ \ { \
return M_C(name, _size)(v) >= v->size; \ return M_C(name, _size)(v) >= v->size; \
} \ } \
@@ -810,11 +813,11 @@ M_C(name, _init)(buffer_t v, size_t size) \
#define QUEUEI_SPSC_DEF_P1(arg) QUEUEI_SPSC_DEF_P2 arg #define QUEUEI_SPSC_DEF_P1(arg) QUEUEI_SPSC_DEF_P2 arg
/* Validate the value oplist before going further */ /* Validate the value oplist before going further */
#define QUEUEI_SPSC_DEF_P2(name, type, policy, oplist, buffer_t) \ #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) M_IF_OPLIST(oplist)(QUEUEI_SPSC_DEF_P3, QUEUEI_SPSC_DEF_FAILURE)(name, type, policy, oplist, buffer_t)
/* Stop processing with a compilation failure */ /* Stop processing with a compilation failure */
#define QUEUEI_SPSC_DEF_FAILURE(name, type, policy, oplist, buffer_t) \ #define QUEUEI_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)) 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 #ifdef NDEBUG
@@ -833,10 +836,10 @@ M_C(name, _init)(buffer_t v, size_t size) \
#define QUEUEI_SPSC_DEF_P3(name, type, policy, oplist, buffer_t) \ #define QUEUEI_SPSC_DEF_P3(name, type, policy, oplist, buffer_t) \
\ \
typedef struct M_C(name, _el_s) { \ typedef struct M_C(name, _el_s) { \
type x; \ type x; \
} M_C(name, _el_t); \ } M_C(name, _el_t); \
\ \
typedef struct M_C(name, _s) { \ typedef struct M_C(name, _s) { \
atomic_uint consoIdx; /* Can only increase until overflow */ \ atomic_uint consoIdx; /* Can only increase until overflow */ \
unsigned int size; \ unsigned int size; \
@@ -845,9 +848,9 @@ M_C(name, _init)(buffer_t v, size_t size) \
atomic_uint prodIdx; /* Can only increase until overflow */ \ atomic_uint prodIdx; /* Can only increase until overflow */ \
} buffer_t[1]; \ } buffer_t[1]; \
\ \
static inline bool \ static inline bool \
M_C(name, _push)(buffer_t table, type const x) \ M_C(name, _push)(buffer_t table, type const x) \
{ \ { \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \ unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_relaxed); \ memory_order_relaxed); \
@@ -857,18 +860,18 @@ M_C(name, _init)(buffer_t v, size_t size) \
return false; \ return false; \
unsigned int i = w & (table->size -1); \ unsigned int i = w & (table->size -1); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, table->Tab[i].x, x); \ M_CALL_SET(oplist, table->Tab[i].x, x); \
} else { \ } else { \
M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \ M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \
} \ } \
atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \ atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
return true; \ return true; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _push_move)(buffer_t table, type x) \ M_C(name, _push_move)(buffer_t table, type x) \
{ \ { \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \ unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_relaxed); \ memory_order_relaxed); \
@@ -878,24 +881,24 @@ M_C(name, _init)(buffer_t v, size_t size) \
return false; \ return false; \
unsigned int i = w & (table->size -1); \ unsigned int i = w & (table->size -1); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_DO_MOVE(oplist, table->Tab[i].x, x); \ M_DO_MOVE(oplist, table->Tab[i].x, x); \
} else { \ } else { \
M_DO_INIT_MOVE(oplist, table->Tab[i].x, x); \ M_DO_INIT_MOVE(oplist, table->Tab[i].x, x); \
} \ } \
atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \ atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
return true; \ return true; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _pop)(type *ptr, buffer_t table) \ M_C(name, _pop)(type *ptr, buffer_t table) \
{ \ { \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
assert (ptr != NULL); \ assert (ptr != NULL); \
unsigned int w = atomic_load_explicit(&table->prodIdx, \ unsigned int w = atomic_load_explicit(&table->prodIdx, \
memory_order_relaxed); \ memory_order_relaxed); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \ unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_acquire); \ memory_order_acquire); \
if (w-r == 0) \ if (w-r == 0) \
return false; \ return false; \
unsigned int i = r & (table->size -1); \ unsigned int i = r & (table->size -1); \
@@ -904,14 +907,14 @@ M_C(name, _init)(buffer_t v, size_t size) \
} else { \ } else { \
M_DO_INIT_MOVE (oplist, *ptr, table->Tab[i].x); \ M_DO_INIT_MOVE (oplist, *ptr, table->Tab[i].x); \
} \ } \
atomic_store_explicit(&table->consoIdx, r+1, memory_order_release); \ atomic_store_explicit(&table->consoIdx, r+1, memory_order_release); \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
return true; \ return true; \
} \ } \
\ \
static inline unsigned \ static inline unsigned \
M_C(name, _push_bulk)(buffer_t table, unsigned n, type const x[]) \ M_C(name, _push_bulk)(buffer_t table, unsigned n, type const x[]) \
{ \ { \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
assert (x != NULL); \ assert (x != NULL); \
assert (n <= table->size); \ assert (n <= table->size); \
@@ -935,16 +938,16 @@ M_C(name, _init)(buffer_t v, size_t size) \
return max; \ return max; \
} \ } \
\ \
static inline unsigned \ static inline unsigned \
M_C(name, _pop_bulk)(unsigned int n, type ptr[], buffer_t table) \ M_C(name, _pop_bulk)(unsigned int n, type ptr[], buffer_t table) \
{ \ { \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
assert (ptr != NULL); \ assert (ptr != NULL); \
assert (n <= table->size); \ assert (n <= table->size); \
unsigned int w = atomic_load_explicit(&table->prodIdx, \ unsigned int w = atomic_load_explicit(&table->prodIdx, \
memory_order_relaxed); \ memory_order_relaxed); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \ unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_acquire); \ memory_order_acquire); \
if (w-r == 0) \ if (w-r == 0) \
return 0; \ return 0; \
unsigned int max = M_MIN(w-r, n); \ unsigned int max = M_MIN(w-r, n); \
@@ -961,9 +964,9 @@ M_C(name, _init)(buffer_t v, size_t size) \
return max; \ return max; \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _push_force)(buffer_t table, type const x) \ M_C(name, _push_force)(buffer_t table, type const x) \
{ \ { \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \ unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_relaxed); \ memory_order_relaxed); \
@@ -976,11 +979,11 @@ M_C(name, _init)(buffer_t v, size_t size) \
} \ } \
unsigned int i = w & (table->size -1); \ unsigned int i = w & (table->size -1); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, table->Tab[i].x, x); \ M_CALL_SET(oplist, table->Tab[i].x, x); \
} else { \ } else { \
M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \ M_CALL_INIT_SET(oplist, table->Tab[i].x, x); \
} \ } \
atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \ atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
} \ } \
\ \
@@ -989,12 +992,12 @@ M_C(name, _init)(buffer_t v, size_t size) \
{ \ { \
QUEUEI_SPSC_CONTRACT(table); \ QUEUEI_SPSC_CONTRACT(table); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \ unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_relaxed); \ memory_order_relaxed); \
unsigned int w = atomic_load_explicit(&table->prodIdx, \ unsigned int w = atomic_load_explicit(&table->prodIdx, \
memory_order_acquire); \ memory_order_acquire); \
/* We return an approximation as we can't read both r & w atomically \ /* We return an approximation as we can't read both r & w atomically \
As we read producer index after consummer index, \ As we read producer index after consummer index, \
and they are atomic variables without reordering \ and they are atomic variables without reordering \
producer index is always greater or equal than consumer index \ producer index is always greater or equal than consumer index \
(or on overflow occurs, in which case as we compute with modulo \ (or on overflow occurs, in which case as we compute with modulo \
arithmetic, the right result is computed). \ arithmetic, the right result is computed). \
@@ -1006,54 +1009,54 @@ M_C(name, _init)(buffer_t v, size_t size) \
} \ } \
\ \
static inline size_t \ static inline size_t \
M_C(name, _capacity)(buffer_t v) \ M_C(name, _capacity)(buffer_t v) \
{ \ { \
return v->size; \ return v->size; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _empty_p)(buffer_t v) \ M_C(name, _empty_p)(buffer_t v) \
{ \ { \
return M_C(name, _size) (v) == 0; \ return M_C(name, _size) (v) == 0; \
} \ } \
\
static inline bool \
M_C(name, _full_p)(buffer_t v) \
{ \
return M_C(name, _size)(v) >= v->size; \
} \
\ \
static inline void \ static inline bool \
M_C(name, _init)(buffer_t buffer, size_t size) \ M_C(name, _full_p)(buffer_t v) \
{ \ { \
assert (buffer != NULL); \ return M_C(name, _size)(v) >= v->size; \
assert( M_POWEROF2_P(size)); \ } \
\
static inline void \
M_C(name, _init)(buffer_t buffer, size_t size) \
{ \
assert (buffer != NULL); \
assert( M_POWEROF2_P(size)); \
assert (0 < size && size <= UINT_MAX); \ assert (0 < size && size <= UINT_MAX); \
assert(((policy) & (BUFFER_STACK|BUFFER_THREAD_UNSAFE|BUFFER_PUSH_OVERWRITE)) == 0); \ assert(((policy) & (BUFFER_STACK|BUFFER_THREAD_UNSAFE|BUFFER_PUSH_OVERWRITE)) == 0); \
atomic_init(&buffer->prodIdx, (unsigned int) size); \ atomic_init(&buffer->prodIdx, (unsigned int) size); \
atomic_init(&buffer->consoIdx, (unsigned int) size); \ atomic_init(&buffer->consoIdx, (unsigned int) size); \
buffer->size = (unsigned int) size; \ buffer->size = (unsigned int) size; \
buffer->Tab = M_CALL_REALLOC(oplist, M_C(name, _el_t), NULL, size); \ buffer->Tab = M_CALL_REALLOC(oplist, M_C(name, _el_t), NULL, size); \
if (buffer->Tab == NULL) { \ if (buffer->Tab == NULL) { \
M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \ M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \
return; \ return; \
} \ } \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(unsigned int j = 0; j < (unsigned int) size; j++) { \ for(unsigned int j = 0; j < (unsigned int) size; j++) { \
M_CALL_INIT(oplist, buffer->Tab[j].x); \ M_CALL_INIT(oplist, buffer->Tab[j].x); \
} \ } \
} \ } \
QUEUEI_SPSC_CONTRACT(buffer); \ QUEUEI_SPSC_CONTRACT(buffer); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _clear)(buffer_t buffer) \ M_C(name, _clear)(buffer_t buffer) \
{ \ { \
QUEUEI_SPSC_CONTRACT(buffer); \ QUEUEI_SPSC_CONTRACT(buffer); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(unsigned int j = 0; j < buffer->size; j++) { \ for(unsigned int j = 0; j < buffer->size; j++) { \
M_CALL_CLEAR(oplist, buffer->Tab[j].x); \ M_CALL_CLEAR(oplist, buffer->Tab[j].x); \
} \ } \
} else { \ } else { \
unsigned int iP = atomic_load_explicit(&buffer->prodIdx, memory_order_relaxed); \ unsigned int iP = atomic_load_explicit(&buffer->prodIdx, memory_order_relaxed); \
unsigned int i = iP & (buffer->size -1); \ unsigned int i = iP & (buffer->size -1); \
@@ -1066,33 +1069,33 @@ M_C(name, _init)(buffer_t v, size_t size) \
j = 0; \ j = 0; \
} \ } \
} \ } \
M_CALL_FREE(oplist, buffer->Tab); \ M_CALL_FREE(oplist, buffer->Tab); \
buffer->Tab = NULL; /* safer */ \ buffer->Tab = NULL; /* safer */ \
} \ } \
\ \
/* Deferred evaluation for the definition, /* Deferred evaluation for the definition,
so that all arguments are evaluated before further expansion */ so that all arguments are evaluated before further expansion */
#define BUFFERI_OPLIST_P1(arg) BUFFERI_OPLIST_P2 arg #define BUFFERI_OPLIST_P1(arg) BUFFERI_OPLIST_P2 arg
/* Validation of the given oplist */ /* Validation of the given oplist */
#define BUFFERI_OPLIST_P2(name, oplist) \ #define BUFFERI_OPLIST_P2(name, oplist) \
M_IF_OPLIST(oplist)(BUFFERI_OPLIST_P3, BUFFERI_OPLIST_FAILURE)(name, oplist) M_IF_OPLIST(oplist)(BUFFERI_OPLIST_P3, BUFFERI_OPLIST_FAILURE)(name, oplist)
/* Prepare a clean compilation failure */ /* Prepare a clean compilation failure */
#define BUFFERI_OPLIST_FAILURE(name, oplist) \ #define BUFFERI_OPLIST_FAILURE(name, oplist) \
((M_LIB_ERROR(ARGUMENT_OF_BUFFER_OPLIST_IS_NOT_AN_OPLIST, name, oplist))) ((M_LIB_ERROR(ARGUMENT_OF_BUFFER_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
/* OPLIST defininition of a buffer */ /* OPLIST defininition of a buffer */
#define BUFFERI_OPLIST_P3(name, oplist) \ #define BUFFERI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _int_init)) \ (INIT(M_C(name, _int_init)) \
,INIT_SET(M_C(name, _init_set)) \ ,INIT_SET(M_C(name, _init_set)) \
,SET(M_C(name, _set)) \ ,SET(M_C(name, _set)) \
,CLEAR(M_C(name, _clear)) \ ,CLEAR(M_C(name, _clear)) \
,TYPE(M_C(name,_t)) \ ,TYPE(M_C(name,_t)) \
,SUBTYPE(M_C(name, _type_t)) \ ,SUBTYPE(M_C(name, _type_t)) \
,CLEAN(M_C(name,_clean)) \ ,CLEAN(M_C(name,_clean)) \
,PUSH(M_C(name,_push)) \ ,PUSH(M_C(name,_push)) \
,POP(M_C(name,_pop)) \ ,POP(M_C(name,_pop)) \
,OPLIST(oplist) \ ,OPLIST(oplist) \
,TEST_EMPTY(M_C(name, _empty_p)), \ ,TEST_EMPTY(M_C(name, _empty_p)), \
+2 -2
View File
@@ -225,7 +225,7 @@ M_BEGIN_PROTECTED_CODE
memory_order_relaxed)) { \ memory_order_relaxed)) { \
break; \ break; \
} \ } \
/* Failure: perform a random exponential backoff */ \ /* Failure: perform a random exponential backoff */ \
m_core_backoff_wait(bkoff); \ m_core_backoff_wait(bkoff); \
} \ } \
} \ } \
@@ -243,7 +243,7 @@ M_BEGIN_PROTECTED_CODE
/* Dequeue a node if the node is old enough */ \ /* Dequeue a node if the node is old enough */ \
static inline M_C(name, _lf_node_t) * \ static inline M_C(name, _lf_node_t) * \
M_C(name, _lflist_pop_if)(M_C(name, _lflist_t) list, \ M_C(name, _lflist_pop_if)(M_C(name, _lflist_t) list, \
m_gc_ticket_t age, m_core_backoff_t bkoff) \ m_gc_ticket_t age, m_core_backoff_t bkoff) \
{ \ { \
M_C(name, _lf_node_t) *head; \ M_C(name, _lf_node_t) *head; \
M_C(name, _lf_node_t) *tail; \ M_C(name, _lf_node_t) *tail; \
+17 -17
View File
@@ -1351,7 +1351,7 @@ M_BEGIN_PROTECTED_CODE
#define M_IF_NARGS_EQ2(...) M_IF(M_EQUAL(M_NARGS(__VA_ARGS__), 2)) #define M_IF_NARGS_EQ2(...) M_IF(M_EQUAL(M_NARGS(__VA_ARGS__), 2))
/* If NDEBUG macro is defined /* If NDEBUG macro is defined
M_IF_DEBUG(code if NDEBUG is not defined) M_IF_DEBUG(code if NDEBUG is not defined)
Note: not 100% robust */ Note: not 100% robust */
#define M_TEST_NDEBUG_P() M_C3(M_, NDEBUG, _TEST) #define M_TEST_NDEBUG_P() M_C3(M_, NDEBUG, _TEST)
#define M_NDEBUG_TEST 0 #define M_NDEBUG_TEST 0
@@ -1374,7 +1374,7 @@ M_BEGIN_PROTECTED_CODE
#define f(...) M_APPLY(f, M_IF_DEFAULT1(0, __VA_ARGS__)) #define f(...) M_APPLY(f, M_IF_DEFAULT1(0, __VA_ARGS__))
This need to be called within a M_APPLY macro. This need to be called within a M_APPLY macro.
*/ */
#define M_IF_DEFAULT1(value, ...) \ #define M_IF_DEFAULT1(value, ...) \
__VA_ARGS__ M_IF_NARGS_EQ1(__VA_ARGS__)(M_DEFERRED_COMMA value, ) __VA_ARGS__ M_IF_NARGS_EQ1(__VA_ARGS__)(M_DEFERRED_COMMA value, )
/* Helper macro to redefine a function with a default values: /* Helper macro to redefine a function with a default values:
@@ -2484,7 +2484,7 @@ m_core_hash (const void *str, size_t length)
#define M_MEMCMP2_DEFAULT(a,b) (M_CHECK_SAME(a, b), memcmp(&(a), &(b), sizeof (a))) #define M_MEMCMP2_DEFAULT(a,b) (M_CHECK_SAME(a, b), memcmp(&(a), &(b), sizeof (a)))
#define M_SWAP_DEFAULT(el1, el2) do { \ #define M_SWAP_DEFAULT(el1, el2) do { \
char _tmp[sizeof (el1)]; \ char _tmp[sizeof (el1)]; \
M_CHECK_SAME(el1, el2); \ M_CHECK_SAME(el1, el2); \
memcpy(&_tmp, &(el1), sizeof (el1)); \ memcpy(&_tmp, &(el1), sizeof (el1)); \
memcpy(&(el1), &(el2), sizeof (el1)); \ memcpy(&(el1), &(el2), sizeof (el1)); \
memcpy(&(el2), &_tmp, sizeof (el1)); \ memcpy(&(el2), &_tmp, sizeof (el1)); \
@@ -2737,12 +2737,12 @@ m_core_parse2_enum (const char str[], const char **endptr)
/* Perform a preprocessing M_IF if both methods exist in the oplist. /* Perform a preprocessing M_IF if both methods exist in the oplist.
Example: M_IF_METHOD2(HASH, CMP, oplist) (define function with HASH & CMP method, ) */ Example: M_IF_METHOD2(HASH, CMP, oplist) (define function with HASH & CMP method, ) */
#define M_IF_METHOD2(method1, method2, oplist) \ #define M_IF_METHOD2(method1, method2, oplist) \
M_IF(M_AND(M_TEST_METHOD_P(method1, oplist), M_TEST_METHOD_P(method2, oplist))) M_IF(M_AND(M_TEST_METHOD_P(method1, oplist), M_TEST_METHOD_P(method2, oplist)))
/* Perform a preprocessing M_IF if at least one method exists in the oplist. /* Perform a preprocessing M_IF if at least one method exists in the oplist.
Example: M_IF_AT_LEAST_METHOD(HASH, CMP, oplist) (define function with HASH or CMP method, ) */ Example: M_IF_AT_LEAST_METHOD(HASH, CMP, oplist) (define function with HASH or CMP method, ) */
#define M_IF_AT_LEAST_METHOD(method1, method2, oplist) \ #define M_IF_AT_LEAST_METHOD(method1, method2, oplist) \
M_IF(M_OR(M_TEST_METHOD_P(method1, oplist), M_TEST_METHOD_P(method2, oplist))) M_IF(M_OR(M_TEST_METHOD_P(method1, oplist), M_TEST_METHOD_P(method2, oplist)))
/* Perform a preprocessing M_IF if both methods exists in both oplist. /* Perform a preprocessing M_IF if both methods exists in both oplist.
@@ -2753,7 +2753,7 @@ m_core_parse2_enum (const char str[], const char **endptr)
/* Perform a preprocessing M_IF if the method exists for all oplist. /* Perform a preprocessing M_IF if the method exists for all oplist.
Example: M_IF_METHOD_ALL(HASH, oplist1, oplist2) (define function with HASH method, ) */ Example: M_IF_METHOD_ALL(HASH, oplist1, oplist2) (define function with HASH method, ) */
#define M_IF_METHOD_ALL(method, ...) \ #define M_IF_METHOD_ALL(method, ...) \
M_IF(M_REDUCE2(M_TEST_METHOD_P, M_AND, method, __VA_ARGS__)) M_IF(M_REDUCE2(M_TEST_METHOD_P, M_AND, method, __VA_ARGS__))
/* Perform a preprocessing M_IF if both methods exist for all oplist. /* Perform a preprocessing M_IF if both methods exist for all oplist.
@@ -2770,18 +2770,18 @@ m_core_parse2_enum (const char str[], const char **endptr)
/* Perform an INIT_MOVE if present, or emulate it using INIT_SET/CLEAR */ /* Perform an INIT_MOVE if present, or emulate it using INIT_SET/CLEAR */
#define M_DO_INIT_MOVE(oplist, dest, src) do { \ #define M_DO_INIT_MOVE(oplist, dest, src) do { \
M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_INIT_MOVE(oplist, (dest), (src)), \ M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_INIT_MOVE(oplist, (dest), (src)), \
M_CALL_INIT_SET(oplist, (dest), (src)) ; \ M_CALL_INIT_SET(oplist, (dest), (src)) ; \
M_CALL_CLEAR(oplist, (src) )); \ M_CALL_CLEAR(oplist, (src) )); \
} while (0) } while (0)
/* Perform a MOVE if present, or emulate it using CLEAR/INIT_MOVE /* Perform a MOVE if present, or emulate it using CLEAR/INIT_MOVE
if possible, or with SET/CLEAR otherwise */ if possible, or with SET/CLEAR otherwise */
#define M_DO_MOVE(oplist, dest, src) do { \ #define M_DO_MOVE(oplist, dest, src) do { \
M_IF_METHOD(MOVE, oplist) (M_CALL_MOVE(oplist, (dest), (src)), \ M_IF_METHOD(MOVE, oplist) (M_CALL_MOVE(oplist, (dest), (src)), \
M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_CLEAR(oplist, (dest)); \ M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_CLEAR(oplist, (dest)); \
M_CALL_INIT_MOVE(oplist, (dest), (src)), \ M_CALL_INIT_MOVE(oplist, (dest), (src)), \
M_CALL_SET(oplist, (dest), (src)); \ M_CALL_SET(oplist, (dest), (src)); \
M_CALL_CLEAR(oplist, (src)) \ M_CALL_CLEAR(oplist, (src)) \
)); \ )); \
} while (0) } while (0)
@@ -2800,13 +2800,13 @@ m_core_parse2_enum (const char str[], const char **endptr)
otherwise it returns the argument. otherwise it returns the argument.
Global oplist is limited to typedef types. Global oplist is limited to typedef types.
*/ */
#define M_GLOBAL_OPLIST(a) \ #define M_GLOBAL_OPLIST(a) \
M_IF( M_OPLIST_P(a))(M_GLOBALI_ID, M_GLOBALI_OPLIST_ELSE)(a) M_IF( M_OPLIST_P(a))(M_GLOBALI_ID, M_GLOBALI_OPLIST_ELSE)(a)
#define M_GLOBALI_ID(a) a #define M_GLOBALI_ID(a) a
#define M_GLOBALI_OPLIST_ELSE(a) M_GLOBALI_OPLIST_ELSE2(a, M_C(M_OPL_, a)()) #define M_GLOBALI_OPLIST_ELSE(a) M_GLOBALI_OPLIST_ELSE2(a, M_C(M_OPL_, a)())
#define M_GLOBALI_OPLIST_ELSE2(a, op) M_IF( M_OPLIST_P (op))(op, a) #define M_GLOBALI_OPLIST_ELSE2(a, op) M_IF( M_OPLIST_P (op))(op, a)
#define M_GLOBAL_TYPE(a) \ #define M_GLOBAL_TYPE(a) \
M_IF( M_OPLIST_P(a))(M_GLOBALI_TYPE_GET, M_GLOBALI_ID)(a) M_IF( M_OPLIST_P(a))(M_GLOBALI_TYPE_GET, M_GLOBALI_ID)(a)
#define M_GLOBALI_TYPE_GET(a) M_GET_TYPE a #define M_GLOBALI_TYPE_GET(a) M_GET_TYPE a
@@ -3086,13 +3086,13 @@ m_core_parse2_enum (const char str[], const char **endptr)
an expression. an expression.
*/ */
#if defined(__cplusplus) #if defined(__cplusplus)
# define M_STATIC_ASSERT(cond, error, msg) \ # define M_STATIC_ASSERT(cond, error, msg) \
([] { static_assert(cond, #error ": " msg); } ()) ([] { static_assert(cond, #error ": " msg); } ())
#elif defined(__GNUC__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #elif defined(__GNUC__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
# define M_STATIC_ASSERT(cond, error, msg) \ # define M_STATIC_ASSERT(cond, error, msg) \
M_ATTR_EXTENSION ({ static_assert(cond, #error ": " msg); }) M_ATTR_EXTENSION ({ static_assert(cond, #error ": " msg); })
#else #else
# define M_STATIC_ASSERT(cond, error, msg) \ # define M_STATIC_ASSERT(cond, error, msg) \
((void) sizeof(struct { int error : !!(cond);})) ((void) sizeof(struct { int error : !!(cond);}))
#endif #endif
+491 -488
View File
File diff suppressed because it is too large. Load diff
+17 -17
View File
@@ -89,22 +89,22 @@
*/ */
/* Specialization of the OPLIST in function if there is at least one member or not */ /* Specialization of the OPLIST in function if there is at least one member or not */
#define FUNCOBJI_INS_NO_ATTR_OPLIST(name) \ #define FUNCOBJI_INS_NO_ATTR_OPLIST(name) \
(NAME(name), TYPE(M_C(name, _t)), \ (NAME(name), TYPE(M_C(name, _t)), \
CLEAR(M_C(name, _clear)), \ CLEAR(M_C(name, _clear)), \
INIT(M_C(name,_init)) \ INIT(M_C(name,_init)) \
) )
/* Validate the oplist before going further */ /* Validate the oplist before going further */
#define FUNCOBJI_INS_ATTR_OPLIST_P1(name, ...) \ #define FUNCOBJI_INS_ATTR_OPLIST_P1(name, ...) \
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(FUNCOBJI_INS_ATTR_OPLIST_P3, FUNCOBJI_INS_ATTR_OPLIST_FAILURE)(name, __VA_ARGS__) M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(FUNCOBJI_INS_ATTR_OPLIST_P3, FUNCOBJI_INS_ATTR_OPLIST_FAILURE)(name, __VA_ARGS__)
/* Prepare a clean compilation failure */ /* Prepare a clean compilation failure */
#define FUNCOBJI_INS_ATTR_OPLIST_FAILURE(name, ...) \ #define FUNCOBJI_INS_ATTR_OPLIST_FAILURE(name, ...) \
((M_LIB_ERROR(ONE_ARGUMENT_OF_FUNC_OBJ_INS_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__))) ((M_LIB_ERROR(ONE_ARGUMENT_OF_FUNC_OBJ_INS_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__)))
/* Define at least the oplist */ /* Define at least the oplist */
#define FUNCOBJI_INS_ATTR_OPLIST_P3(name, ...) \ #define FUNCOBJI_INS_ATTR_OPLIST_P3(name, ...) \
(NAME(name), TYPE(M_C(name, _t)), \ (NAME(name), TYPE(M_C(name, _t)), \
INIT_WITH(M_C(name, _init_with)), \ INIT_WITH(M_C(name, _init_with)), \
CLEAR(M_C(name, _clear)), \ CLEAR(M_C(name, _clear)), \
@@ -216,21 +216,21 @@
FUNCOBJI_INS_ATTR_DEF_P2(name, base_name, param_list, callback_core, FUNCOBJI_INJECT_GLOBAL(__VA_ARGS__) ) FUNCOBJI_INS_ATTR_DEF_P2(name, base_name, param_list, callback_core, FUNCOBJI_INJECT_GLOBAL(__VA_ARGS__) )
/* Inject the oplist within the list of arguments */ /* Inject the oplist within the list of arguments */
#define FUNCOBJI_INJECT_GLOBAL(...) \ #define FUNCOBJI_INJECT_GLOBAL(...) \
M_MAP_C(FUNCOBJI_INJECT_OPLIST_A, __VA_ARGS__) M_MAP_C(FUNCOBJI_INJECT_OPLIST_A, __VA_ARGS__)
/* Transform (x, type) into (x, type, oplist) if there is global registered oplist /* 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 (x, type, M_DEFAULT_OPLIST) if there is no global one,
or keep (x, type, oplist) if oplist was already present */ or keep (x, type, oplist) if oplist was already present */
#define FUNCOBJI_INJECT_OPLIST_A( duo_or_trio ) \ #define FUNCOBJI_INJECT_OPLIST_A( duo_or_trio ) \
FUNCOBJI_INJECT_OPLIST_B duo_or_trio FUNCOBJI_INJECT_OPLIST_B duo_or_trio
#define FUNCOBJI_INJECT_OPLIST_B( f, ... ) \ #define FUNCOBJI_INJECT_OPLIST_B( f, ... ) \
M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) ) 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 // Test if all third argument of all arguments is an oplist
#define FUNCOBJI_IF_ALL_OPLIST(...) \ #define FUNCOBJI_IF_ALL_OPLIST(...) \
M_IF(M_REDUCE(FUNCOBJI_IS_OPLIST_P, M_AND, __VA_ARGS__)) M_IF(M_REDUCE(FUNCOBJI_IS_OPLIST_P, M_AND, __VA_ARGS__))
// Test if the third argument is an oplist // Test if the third argument is an oplist
#define FUNCOBJI_IS_OPLIST_P(a) \ #define FUNCOBJI_IS_OPLIST_P(a) \
M_OPLIST_P(M_RET_ARG3 a) M_OPLIST_P(M_RET_ARG3 a)
/* Validate the oplist before going further */ /* Validate the oplist before going further */
@@ -297,24 +297,24 @@
/* Define a numbered type of a parameter of the callback*/ /* Define a numbered type of a parameter of the callback*/
#define FUNCOBJI_BASE_TYPE(name, num, type) \ #define FUNCOBJI_BASE_TYPE(name, num, type) \
typedef type M_C4(name, _param_, num, _t); typedef type M_C4(name, _param_, num, _t);
/* Define a list of the type of arguments for a function definition */ /* Define a list of the type of arguments for a function definition */
#define FUNCOBJI_BASE_ARGLIST(name, num, type) \ #define FUNCOBJI_BASE_ARGLIST(name, num, type) \
M_DEFERRED_COMMA type M_C(param_, num) M_DEFERRED_COMMA type M_C(param_, num)
/* Define a list of arguments for a function call */ /* Define a list of arguments for a function call */
#define FUNCOBJI_BASE_ARGCALL(name, num, type) \ #define FUNCOBJI_BASE_ARGCALL(name, num, type) \
M_DEFERRED_COMMA M_C(param_, num) M_DEFERRED_COMMA M_C(param_, num)
/* Helper macros */ /* Helper macros */
/* arg = (name, type [, oplist]) */ /* arg = (name, type [, oplist]) */
#define FUNCOBJI_INS_ATTR_STRUCT(arg) \ #define FUNCOBJI_INS_ATTR_STRUCT(arg) \
M_RET_ARG2 arg M_RET_ARG1 arg; M_RET_ARG2 arg M_RET_ARG1 arg;
#define FUNCOBJI_INS_ATTR_LIST(arg) \ #define FUNCOBJI_INS_ATTR_LIST(arg) \
M_DEFERRED_COMMA M_RET_ARG2 arg const M_RET_ARG1 arg M_DEFERRED_COMMA M_RET_ARG2 arg const M_RET_ARG1 arg
#define FUNCOBJI_INS_ATTR_INIT(arg) \ #define FUNCOBJI_INS_ATTR_INIT(arg) \
@@ -327,12 +327,12 @@
M_CALL_CLEAR(M_RET_ARG3 arg, obj -> M_RET_ARG1 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 the list of arguments of the instance of the callback */
#define FUNCOBJI_INS_ARGLIST(name, num, param) \ #define FUNCOBJI_INS_ARGLIST(name, num, param) \
M_DEFERRED_COMMA M_C4(name, _param_, num, _t) param M_DEFERRED_COMMA M_C4(name, _param_, num, _t) param
/* Macros for testing for a method presence in all the attributes */ /* Macros for testing for a method presence in all the attributes */
#define FUNCOBJI_TEST_METHOD2_P(method, op) \ #define FUNCOBJI_TEST_METHOD2_P(method, op) \
M_TEST_METHOD_P(method, op) M_TEST_METHOD_P(method, op)
#define FUNCOBJI_TEST_METHOD1_P(method, arg) \ #define FUNCOBJI_TEST_METHOD1_P(method, arg) \
M_APPLY(FUNCOBJI_TEST_METHOD2_P, method, M_RET_ARG3 arg) M_APPLY(FUNCOBJI_TEST_METHOD2_P, method, M_RET_ARG3 arg)
@@ -340,7 +340,7 @@
M_IF(M_REDUCE2(FUNCOBJI_TEST_METHOD1_P, M_AND, method, __VA_ARGS__)) M_IF(M_REDUCE2(FUNCOBJI_TEST_METHOD1_P, M_AND, method, __VA_ARGS__))
/* Macro for checking compatible type and oplist for all the attributes */ /* Macro for checking compatible type and oplist for all the attributes */
#define FUNCOBJI_CONTROL_ALL_OPLIST(name, ...) \ #define FUNCOBJI_CONTROL_ALL_OPLIST(name, ...) \
M_MAP2(FUNCOBJI_CONTROL_OPLIST, name, __VA_ARGS__) M_MAP2(FUNCOBJI_CONTROL_OPLIST, name, __VA_ARGS__)
#define FUNCOBJI_CONTROL_OPLIST(name, a) \ #define FUNCOBJI_CONTROL_OPLIST(name, a) \
M_CHECK_COMPATIBLE_OPLIST(name, M_RET_ARG1 a, M_RET_ARG2 a, M_RET_ARG3 a) M_CHECK_COMPATIBLE_OPLIST(name, M_RET_ARG1 a, M_RET_ARG2 a, M_RET_ARG3 a)
+200 -200
View File
@@ -38,7 +38,7 @@
... ...
} tmp_str_t; } tmp_str_t;
*/ */
#define ILIST_INTERFACE(name, type) \ #define ILIST_INTERFACE(name, type) \
struct ilist_head_s name struct ilist_head_s name
/* Define a doubly-linked intrusive list of a given type. /* Define a doubly-linked intrusive list of a given type.
@@ -57,7 +57,7 @@
ILIST_OPLIST(name [, oplist_of_the_type]) */ ILIST_OPLIST(name [, oplist_of_the_type]) */
#define ILIST_OPLIST(...) \ #define ILIST_OPLIST(...) \
ILISTI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ ILISTI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST), \ ((__VA_ARGS__, M_DEFAULT_OPLIST), \
(__VA_ARGS__ ))) (__VA_ARGS__ )))
@@ -73,37 +73,37 @@ typedef struct ilist_head_s {
#define ILISTI_OPLIST_P1(arg) ILISTI_OPLIST_P2 arg #define ILISTI_OPLIST_P1(arg) ILISTI_OPLIST_P2 arg
/* Validation of the given oplist */ /* Validation of the given oplist */
#define ILISTI_OPLIST_P2(name, oplist) \ #define ILISTI_OPLIST_P2(name, oplist) \
M_IF_OPLIST(oplist)(ILISTI_OPLIST_P3, ILISTI_OPLIST_FAILURE)(name, oplist) M_IF_OPLIST(oplist)(ILISTI_OPLIST_P3, ILISTI_OPLIST_FAILURE)(name, oplist)
/* Prepare a clean compilation failure */ /* Prepare a clean compilation failure */
#define ILISTI_OPLIST_FAILURE(name, oplist) \ #define ILISTI_OPLIST_FAILURE(name, oplist) \
((M_LIB_ERROR(ARGUMENT_OF_ILIST_OPLIST_IS_NOT_AN_OPLIST, name, oplist))) ((M_LIB_ERROR(ARGUMENT_OF_ILIST_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
/* Define the oplist of an ilist of type */ /* Define the oplist of an ilist of type */
#define ILISTI_OPLIST_P3(name, oplist) \ #define ILISTI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _init)), \ (INIT(M_C(name, _init)), \
CLEAR(M_C(name, _clear)), \ CLEAR(M_C(name, _clear)), \
INIT_MOVE(M_C(name, _init_move)), \ INIT_MOVE(M_C(name, _init_move)), \
MOVE(M_C(name, _move)), \ MOVE(M_C(name, _move)), \
TYPE(M_C(name,_t)), \ TYPE(M_C(name,_t)), \
CLEAN(M_C(name,_clean)), \ CLEAN(M_C(name,_clean)), \
SUBTYPE(M_C(name,_type_t)), \ SUBTYPE(M_C(name,_type_t)), \
TEST_EMPTY(M_C(name,_empty_p)), \ TEST_EMPTY(M_C(name,_empty_p)), \
IT_TYPE(M_C(name,_it_t)), \ IT_TYPE(M_C(name,_it_t)), \
IT_FIRST(M_C(name,_it)), \ IT_FIRST(M_C(name,_it)), \
IT_SET(M_C(name,_it_set)), \ IT_SET(M_C(name,_it_set)), \
IT_LAST(M_C(name,_it_last)), \ IT_LAST(M_C(name,_it_last)), \
IT_END(M_C(name,_it_end)), \ IT_END(M_C(name,_it_end)), \
IT_END_P(M_C(name,_end_p)), \ IT_END_P(M_C(name,_end_p)), \
IT_LAST_P(M_C(name,_last_p)), \ IT_LAST_P(M_C(name,_last_p)), \
IT_EQUAL_P(M_C(name,_it_equal_p)), \ IT_EQUAL_P(M_C(name,_it_equal_p)), \
IT_NEXT(M_C(name,_next)), \ IT_NEXT(M_C(name,_next)), \
IT_PREVIOUS(M_C(name,_previous)), \ IT_PREVIOUS(M_C(name,_previous)), \
IT_REF(M_C(name,_ref)), \ IT_REF(M_C(name,_ref)), \
IT_CREF(M_C(name,_cref)), \ IT_CREF(M_C(name,_cref)), \
IT_REMOVE(M_C(name,_remove)), \ IT_REMOVE(M_C(name,_remove)), \
M_IF_METHOD(NEW, oplist)(IT_INSERT(M_C(name,_insert)),), \ M_IF_METHOD(NEW, oplist)(IT_INSERT(M_C(name,_insert)),), \
OPLIST(oplist), \ OPLIST(oplist), \
SPLICE_BACK(M_C(name,_splice_back)) \ SPLICE_BACK(M_C(name,_splice_back)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \ ,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
@@ -111,7 +111,7 @@ typedef struct ilist_head_s {
) )
/* Contract respected by all intrusive lists */ /* Contract respected by all intrusive lists */
#define ILISTI_CONTRACT(name, list) do { \ #define ILISTI_CONTRACT(name, list) do { \
assert(list != NULL); \ assert(list != NULL); \
assert(list->name.prev != NULL); \ assert(list->name.prev != NULL); \
assert(list->name.next != NULL); \ assert(list->name.next != NULL); \
@@ -131,11 +131,11 @@ typedef struct ilist_head_s {
#define ILISTI_DEF_P1(arg) ILISTI_DEF_P2 arg #define ILISTI_DEF_P1(arg) ILISTI_DEF_P2 arg
/* Validate the oplist before going further */ /* Validate the oplist before going further */
#define ILISTI_DEF_P2(name, type, oplist, list_t, it_t) \ #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) M_IF_OPLIST(oplist)(ILISTI_DEF_P3, ILISTI_DEF_FAILURE)(name, type, oplist, list_t, it_t)
/* Stop processing with a compilation failure */ /* Stop processing with a compilation failure */
#define ILISTI_DEF_FAILURE(name, type, oplist, list_t, it_t) \ #define ILISTI_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) 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. /* Definition of the type and function for an intrusive doubly-linked list.
@@ -147,65 +147,65 @@ typedef struct ilist_head_s {
it_t: iterator of the intrusive list (name##_it_t) it_t: iterator of the intrusive list (name##_it_t)
*/ */
#define ILISTI_DEF_P3(name, type, oplist, list_t, it_t) \ #define ILISTI_DEF_P3(name, type, oplist, list_t, it_t) \
\ \
typedef struct M_C(name, _s) { \ typedef struct M_C(name, _s) { \
struct ilist_head_s name; \ struct ilist_head_s name; \
} list_t[1]; \ } list_t[1]; \
typedef struct M_C(name, _s) *M_C(name, _ptr); \ typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \ typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
\ \
typedef type M_C(name, _type_t); \ typedef type M_C(name, _type_t); \
\ \
typedef struct M_C(name, _it_s) { \ typedef struct M_C(name, _it_s) { \
struct ilist_head_s *head; \ struct ilist_head_s *head; \
struct ilist_head_s *previous; \ struct ilist_head_s *previous; \
struct ilist_head_s *current; \ struct ilist_head_s *current; \
struct ilist_head_s *next; \ struct ilist_head_s *next; \
} it_t[1]; \ } it_t[1]; \
\ \
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \ M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\ \
static inline void M_C(name, _init)(list_t list) \ static inline void M_C(name, _init)(list_t list) \
{ \ { \
assert (list != NULL); \ assert (list != NULL); \
list->name.next = &list->name; \ list->name.next = &list->name; \
list->name.prev = &list->name; \ list->name.prev = &list->name; \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
} \ } \
\ \
static inline void M_C(name, _clean)(list_t list) \ static inline void M_C(name, _clean)(list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
for(struct ilist_head_s *it = list->name.next, *next ; \ for(struct ilist_head_s *it = list->name.next, *next ; \
it != &list->name; it = next) { \ it != &list->name; it = next) { \
/* Cannot check node contract as previous node may be deleted */ \ /* Cannot check node contract as previous node may be deleted */ \
type *obj = M_TYPE_FROM_FIELD(type, it, \ type *obj = M_TYPE_FROM_FIELD(type, it, \
struct ilist_head_s, name); \ struct ilist_head_s, name); \
/* Read next now before the object is destroyed */ \ /* Read next now before the object is destroyed */ \
next = it->next; \ next = it->next; \
assert (next != NULL); \ assert (next != NULL); \
M_CALL_CLEAR(oplist, *obj); \ M_CALL_CLEAR(oplist, *obj); \
/* Delete also the object if a DELETE operand is registered */ \ /* Delete also the object if a DELETE operand is registered */ \
M_IF_METHOD(DEL, oplist)(M_CALL_DEL(oplist, obj), (void) 0); \ M_IF_METHOD(DEL, oplist)(M_CALL_DEL(oplist, obj), (void) 0); \
} \ } \
/* Nothing remains in the list anymore */ \ /* Nothing remains in the list anymore */ \
list->name.next = &list->name; \ list->name.next = &list->name; \
list->name.prev = &list->name; \ list->name.prev = &list->name; \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
} \ } \
\ \
static inline void M_C(name, _clear)(list_t list) \ static inline void M_C(name, _clear)(list_t list) \
{ \ { \
M_C(name, _clean)(list); \ M_C(name, _clean)(list); \
} \ } \
\ \
static inline bool M_C(name, _empty_p)(const list_t list) \ static inline bool M_C(name, _empty_p)(const list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
return list->name.next == &list->name; \ return list->name.next == &list->name; \
} \ } \
\ \
\ \
static inline void M_C(name, _init_move)(list_t list, list_t ref) \ static inline void M_C(name, _init_move)(list_t list, list_t ref) \
{ \ { \
ILISTI_CONTRACT(name, ref); \ ILISTI_CONTRACT(name, ref); \
@@ -219,18 +219,18 @@ typedef struct ilist_head_s {
} \ } \
ref->name.next = NULL; \ ref->name.next = NULL; \
ref->name.prev = NULL; \ ref->name.prev = NULL; \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
} \ } \
\ \
static inline void M_C(name, _move)(list_t list, list_t ref) \ static inline void M_C(name, _move)(list_t list, list_t ref) \
{ \ { \
M_C(name, _clear)(list); \ M_C(name, _clear)(list); \
M_C(name, _init_move)(list, ref); \ M_C(name, _init_move)(list, ref); \
} \ } \
\ \
static inline size_t M_C(name, _size)(const list_t list) \ static inline size_t M_C(name, _size)(const list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
size_t s = 0; \ size_t s = 0; \
for(const struct ilist_head_s *it = list->name.next ; \ for(const struct ilist_head_s *it = list->name.next ; \
it != &list->name; it = it->next) { \ it != &list->name; it = it->next) { \
@@ -240,28 +240,28 @@ typedef struct ilist_head_s {
return s; \ return s; \
} \ } \
\ \
static inline void M_C(name, _push_back)(list_t list, type *obj) \ static inline void M_C(name, _push_back)(list_t list, type *obj) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \ assert (obj != NULL); \
struct ilist_head_s *prev = list->name.prev; \ struct ilist_head_s *prev = list->name.prev; \
list->name.prev = &obj->name; \ list->name.prev = &obj->name; \
obj->name.prev = prev; \ obj->name.prev = prev; \
obj->name.next = &list->name; \ obj->name.next = &list->name; \
prev->next = &obj->name; \ prev->next = &obj->name; \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
} \ } \
\ \
static inline void M_C(name, _push_front)(list_t list, type *obj) \ static inline void M_C(name, _push_front)(list_t list, type *obj) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \ assert (obj != NULL); \
struct ilist_head_s *next = list->name.next; \ struct ilist_head_s *next = list->name.next; \
list->name.next = &obj->name; \ list->name.next = &obj->name; \
obj->name.next = next; \ obj->name.next = next; \
obj->name.prev = &list->name; \ obj->name.prev = &list->name; \
next->prev = &obj->name; \ next->prev = &obj->name; \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
} \ } \
\ \
static inline void M_C(name, _push_after)(type *obj_pos, type *obj) \ static inline void M_C(name, _push_after)(type *obj_pos, type *obj) \
@@ -274,14 +274,14 @@ typedef struct ilist_head_s {
next->prev = &obj->name; \ next->prev = &obj->name; \
} \ } \
\ \
static inline void M_C(name, _init_field)(type *obj) \ static inline void M_C(name, _init_field)(type *obj) \
{ \ { \
assert (obj != NULL); \ assert (obj != NULL); \
obj->name.next = NULL; \ obj->name.next = NULL; \
obj->name.prev = NULL; \ obj->name.prev = NULL; \
} \ } \
\ \
static inline void M_C(name, _unlink)(type *obj) \ static inline void M_C(name, _unlink)(type *obj) \
{ \ { \
assert (obj != NULL); \ assert (obj != NULL); \
struct ilist_head_s *next = obj->name.next; \ struct ilist_head_s *next = obj->name.next; \
@@ -294,50 +294,50 @@ typedef struct ilist_head_s {
} \ } \
\ \
static inline type * \ static inline type * \
M_C(name, _back)(const list_t list) \ M_C(name, _back)(const list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert(!M_C(name, _empty_p)(list)); \ assert(!M_C(name, _empty_p)(list)); \
return M_TYPE_FROM_FIELD(type, list->name.prev, \ return M_TYPE_FROM_FIELD(type, list->name.prev, \
struct ilist_head_s, name); \ struct ilist_head_s, name); \
} \ } \
\ \
static inline type * \ static inline type * \
M_C(name, _front)(const list_t list) \ M_C(name, _front)(const list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert(!M_C(name, _empty_p)(list)); \ assert(!M_C(name, _empty_p)(list)); \
return M_TYPE_FROM_FIELD(type, list->name.next, \ return M_TYPE_FROM_FIELD(type, list->name.next, \
struct ilist_head_s, name); \ struct ilist_head_s, name); \
} \ } \
\ \
static inline type * \ static inline type * \
M_C(name, _next_obj)(const list_t list, type const *obj) \ M_C(name, _next_obj)(const list_t list, type const *obj) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \ assert (obj != NULL); \
ILISTI_NODE_CONTRACT(&obj->name); \ ILISTI_NODE_CONTRACT(&obj->name); \
return obj->name.next == &list->name ? NULL : \ return obj->name.next == &list->name ? NULL : \
M_TYPE_FROM_FIELD(type, obj->name.next, \ M_TYPE_FROM_FIELD(type, obj->name.next, \
struct ilist_head_s, name); \ struct ilist_head_s, name); \
} \ } \
\ \
static inline type * \ static inline type * \
M_C(name, _previous_obj)(const list_t list, type const *obj) \ M_C(name, _previous_obj)(const list_t list, type const *obj) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \ assert (obj != NULL); \
ILISTI_NODE_CONTRACT(&obj->name); \ ILISTI_NODE_CONTRACT(&obj->name); \
return obj->name.prev == &list->name ? NULL : \ return obj->name.prev == &list->name ? NULL : \
M_TYPE_FROM_FIELD(type, obj->name.prev, \ M_TYPE_FROM_FIELD(type, obj->name.prev, \
struct ilist_head_s, name); \ struct ilist_head_s, name); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _it)(it_t it, const list_t list) \ M_C(name, _it)(it_t it, const list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert (it != NULL); \ assert (it != NULL); \
it->head = list->name.next->prev; \ it->head = list->name.next->prev; \
it->current = list->name.next; \ it->current = list->name.next; \
it->next = list->name.next->next; \ it->next = list->name.next->next; \
@@ -355,19 +355,19 @@ typedef struct ilist_head_s {
it->previous = cit->previous; \ it->previous = cit->previous; \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _it_last)(it_t it, list_t const list) \ M_C(name, _it_last)(it_t it, list_t const list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert (it != NULL); \ assert (it != NULL); \
it->head = list->name.next->prev; \ it->head = list->name.next->prev; \
it->current = list->name.prev; \ it->current = list->name.prev; \
it->next = it->head; \ it->next = it->head; \
it->previous = list->name.prev->prev; \ it->previous = list->name.prev->prev; \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _it_end)(it_t it, list_t const list) \ M_C(name, _it_end)(it_t it, list_t const list) \
{ \ { \
@@ -378,23 +378,23 @@ typedef struct ilist_head_s {
it->previous = list->name.prev; \ it->previous = list->name.prev; \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _end_p)(const it_t it) \ M_C(name, _end_p)(const it_t it) \
{ \ { \
assert (it != NULL); \ assert (it != NULL); \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
return it->current == it->head; \ return it->current == it->head; \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _last_p)(const it_t it) \ M_C(name, _last_p)(const it_t it) \
{ \ { \
assert (it != NULL); \ assert (it != NULL); \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
return it->next == it->head || it->current == it->head; \ return it->next == it->head || it->current == it->head; \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _next)(it_t it) \ M_C(name, _next)(it_t it) \
{ \ { \
@@ -424,7 +424,7 @@ typedef struct ilist_head_s {
assert (it->next != NULL && it->previous != NULL); \ assert (it->next != NULL && it->previous != NULL); \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
} \ } \
\ \
static inline bool \ static inline bool \
M_C(name, _it_equal_p)(const it_t it1, const it_t it2 ) \ M_C(name, _it_equal_p)(const it_t it1, const it_t it2 ) \
{ \ { \
@@ -432,130 +432,130 @@ typedef struct ilist_head_s {
/* No need to check for next & previous */ \ /* No need to check for next & previous */ \
return it1->head == it2->head && it1->current == it2->current; \ return it1->head == it2->head && it1->current == it2->current; \
} \ } \
\ \
static inline type * \ static inline type * \
M_C(name, _ref)(const it_t it) \ M_C(name, _ref)(const it_t it) \
{ \ { \
assert (it != NULL && it->current != NULL); \ assert (it != NULL && it->current != NULL); \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
/* check if 'it' was not deleted */ \ /* check if 'it' was not deleted */ \
assert (it->current->next == it->next); \ assert (it->current->next == it->next); \
assert (it->current->prev == it->previous); \ assert (it->current->prev == it->previous); \
assert (!M_C(name, _end_p)(it)); \ assert (!M_C(name, _end_p)(it)); \
return M_TYPE_FROM_FIELD(type, it->current, \ return M_TYPE_FROM_FIELD(type, it->current, \
struct ilist_head_s, name); \ struct ilist_head_s, name); \
} \ } \
\ \
static inline type const * \ static inline type const * \
M_C(name, _cref)(const it_t it) \ M_C(name, _cref)(const it_t it) \
{ \ { \
type *ptr = M_C(name, _ref)(it); \ type *ptr = M_C(name, _ref)(it); \
return M_CONST_CAST(type, ptr); \ return M_CONST_CAST(type, ptr); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _remove)(list_t list, it_t it) \ M_C(name, _remove)(list_t list, it_t it) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
(void)list; /* list param is not used */ \ (void)list; /* list param is not used */ \
type *obj = M_TYPE_FROM_FIELD(type, it->current, \ type *obj = M_TYPE_FROM_FIELD(type, it->current, \
struct ilist_head_s, name); \ struct ilist_head_s, name); \
M_C(name, _unlink)(obj); \ M_C(name, _unlink)(obj); \
M_CALL_CLEAR(oplist, obj); \ M_CALL_CLEAR(oplist, obj); \
M_IF_METHOD(DEL, oplist)(M_CALL_DEL(oplist, obj), (void) 0); \ M_IF_METHOD(DEL, oplist)(M_CALL_DEL(oplist, obj), (void) 0); \
M_C(name, _next)(it); \ M_C(name, _next)(it); \
} \ } \
\ \
M_IF_METHOD(NEW, oplist)( \ M_IF_METHOD(NEW, oplist)( \
static inline void \ static inline void \
M_C(name, _insert)(list_t list, it_t it, type x) \ M_C(name, _insert)(list_t list, it_t it, type x) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
type *p = M_CALL_NEW(oplist, type); \ type *p = M_CALL_NEW(oplist, type); \
if (M_UNLIKELY (p == NULL)) { \ if (M_UNLIKELY (p == NULL)) { \
M_MEMORY_FULL (sizeof (type)); \ M_MEMORY_FULL (sizeof (type)); \
return ; \ return ; \
} \ } \
M_CALL_INIT_SET(oplist, *p, x); \ M_CALL_INIT_SET(oplist, *p, x); \
type *obj = M_C(name, _ref)(it); \ type *obj = M_C(name, _ref)(it); \
M_C(name, _push_after)(obj, p); \ M_C(name, _push_after)(obj, p); \
it->current = p; \ it->current = p; \
(void) list; \ (void) list; \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
} \ } \
, /* NEW not defined */) \ , /* NEW not defined */) \
\ \
static inline type * \ static inline type * \
M_C(name, _pop_back)(list_t list) \ M_C(name, _pop_back)(list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert (!M_C(name, _empty_p)(list)); \ assert (!M_C(name, _empty_p)(list)); \
type *obj = M_C(name, _back)(list); \ type *obj = M_C(name, _back)(list); \
list->name.prev = list->name.prev->prev; \ list->name.prev = list->name.prev->prev; \
list->name.prev->next = &list->name; \ list->name.prev->next = &list->name; \
return obj; \ return obj; \
} \ } \
\ \
static inline type * \ static inline type * \
M_C(name, _pop_front)(list_t list) \ M_C(name, _pop_front)(list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
assert (!M_C(name, _empty_p)(list)); \ assert (!M_C(name, _empty_p)(list)); \
type *obj = M_C(name, _front)(list); \ type *obj = M_C(name, _front)(list); \
list->name.next = list->name.next->next; \ list->name.next = list->name.next->next; \
list->name.next->prev = &list->name; \ list->name.next->prev = &list->name; \
return obj; \ return obj; \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _splice)(list_t list1, list_t list2) \ M_C(name, _splice)(list_t list1, list_t list2) \
{ \ { \
ILISTI_CONTRACT(name, list1); \ ILISTI_CONTRACT(name, list1); \
ILISTI_CONTRACT(name, list2); \ ILISTI_CONTRACT(name, list2); \
struct ilist_head_s *midle1 = list1->name.prev; \ struct ilist_head_s *midle1 = list1->name.prev; \
struct ilist_head_s *midle2 = list2->name.next; \ struct ilist_head_s *midle2 = list2->name.next; \
midle1->next = midle2; \ midle1->next = midle2; \
midle2->prev = midle1; \ midle2->prev = midle1; \
list1->name.prev = list2->name.prev; \ list1->name.prev = list2->name.prev; \
list2->name.prev->next = &list1->name; \ list2->name.prev->next = &list1->name; \
list2->name.next = &list2->name; \ list2->name.next = &list2->name; \
list2->name.prev = &list2->name; \ list2->name.prev = &list2->name; \
ILISTI_CONTRACT(name, list1); \ ILISTI_CONTRACT(name, list1); \
ILISTI_CONTRACT(name, list2); \ ILISTI_CONTRACT(name, list2); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _splice_back)(list_t nv, list_t ov, it_t it) \ M_C(name, _splice_back)(list_t nv, list_t ov, it_t it) \
{ \ { \
ILISTI_CONTRACT(name, nv); \ ILISTI_CONTRACT(name, nv); \
ILISTI_CONTRACT(name, ov); \ ILISTI_CONTRACT(name, ov); \
ILISTI_NODE_CONTRACT(it->current); \ ILISTI_NODE_CONTRACT(it->current); \
assert (it != NULL); \ assert (it != NULL); \
(void) ov; \ (void) ov; \
type *obj = M_C(name, _ref)(it); \ type *obj = M_C(name, _ref)(it); \
M_C(name, _unlink)(obj); \ M_C(name, _unlink)(obj); \
M_C(name, _push_back)(nv, obj); \ M_C(name, _push_back)(nv, obj); \
M_C(name, _next)(it); \ M_C(name, _next)(it); \
ILISTI_CONTRACT(name, nv); \ ILISTI_CONTRACT(name, nv); \
ILISTI_CONTRACT(name, ov); \ ILISTI_CONTRACT(name, ov); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _splice_at)(list_t nlist, it_t npos, \ M_C(name, _splice_at)(list_t nlist, it_t npos, \
list_t olist, it_t opos) \ list_t olist, it_t opos) \
{ \ { \
ILISTI_CONTRACT(name, nlist); \ ILISTI_CONTRACT(name, nlist); \
ILISTI_CONTRACT(name, olist); \ ILISTI_CONTRACT(name, olist); \
assert (npos != NULL && opos != NULL); \ assert (npos != NULL && opos != NULL); \
assert (!M_C(name, _end_p)(opos)); \ assert (!M_C(name, _end_p)(opos)); \
/* npos may be end */ \ /* npos may be end */ \
(void) olist, (void) nlist; \ (void) olist, (void) nlist; \
type *obj = M_C(name, _ref)(opos); \ type *obj = M_C(name, _ref)(opos); \
struct ilist_head_s *ref = npos->current; \ struct ilist_head_s *ref = npos->current; \
/* Remove object */ \ /* Remove object */ \
M_C(name, _unlink)(obj); \ M_C(name, _unlink)(obj); \
/* Push 'obj' after 'ref' */ \ /* Push 'obj' after 'ref' */ \
struct ilist_head_s *next = ref->next; \ struct ilist_head_s *next = ref->next; \
ref->next = &obj->name; \ ref->next = &obj->name; \
@@ -568,15 +568,15 @@ typedef struct ilist_head_s {
npos->previous = ref; \ npos->previous = ref; \
npos->current = &obj->name; \ npos->current = &obj->name; \
npos->next = next; \ npos->next = next; \
ILISTI_CONTRACT(name, nlist); \ ILISTI_CONTRACT(name, nlist); \
ILISTI_CONTRACT(name, olist); \ ILISTI_CONTRACT(name, olist); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _swap)(list_t d, list_t e) \ M_C(name, _swap)(list_t d, list_t e) \
{ \ { \
ILISTI_CONTRACT(name, d); \ ILISTI_CONTRACT(name, d); \
ILISTI_CONTRACT(name, e); \ ILISTI_CONTRACT(name, e); \
struct ilist_head_s *d_item = d->name.next; \ struct ilist_head_s *d_item = d->name.next; \
struct ilist_head_s *e_item = e->name.next; \ struct ilist_head_s *e_item = e->name.next; \
d->name.next = e_item == &e->name ? &d->name : e_item; \ d->name.next = e_item == &e->name ? &d->name : e_item; \
@@ -589,13 +589,13 @@ typedef struct ilist_head_s {
d->name.prev->next = &d->name; \ d->name.prev->next = &d->name; \
e->name.next->prev = &e->name; \ e->name.next->prev = &e->name; \
e->name.prev->next = &e->name; \ e->name.prev->next = &e->name; \
ILISTI_CONTRACT(name, d); \ ILISTI_CONTRACT(name, d); \
ILISTI_CONTRACT(name, e); \ ILISTI_CONTRACT(name, e); \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _reverse)(list_t list) \ M_C(name, _reverse)(list_t list) \
{ \ { \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
struct ilist_head_s *next, *it; \ struct ilist_head_s *next, *it; \
for(it = list->name.next ; it != &list->name; it = next) { \ for(it = list->name.next ; it != &list->name; it = next) { \
@@ -607,7 +607,7 @@ typedef struct ilist_head_s {
it->next = it->prev; \ it->next = it->prev; \
it->prev = next; \ it->prev = next; \
ILISTI_CONTRACT(name, list); \ ILISTI_CONTRACT(name, list); \
} \ } \
\ \
LISTI_ITBASE_DEF(name, type, oplist, list_t, it_t) LISTI_ITBASE_DEF(name, type, oplist, list_t, it_t)
+50 -50
View File
@@ -42,7 +42,7 @@ M_BEGIN_PROTECTED_CODE
name: name of the intrusive shared pointer. name: name of the intrusive shared pointer.
type: name of the type of the structure (aka. struct test_s) - not used currently. type: name of the type of the structure (aka. struct test_s) - not used currently.
NOTE: There can be only one interface of this kind in a type! */ NOTE: There can be only one interface of this kind in a type! */
#define ISHARED_PTR_INTERFACE(name, type) \ #define ISHARED_PTR_INTERFACE(name, type) \
atomic_int M_C(name, _cpt) atomic_int M_C(name, _cpt)
@@ -52,7 +52,7 @@ M_BEGIN_PROTECTED_CODE
M_BEGIN_PROTECTED_CODE \ M_BEGIN_PROTECTED_CODE \
ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \
(name, __VA_ARGS__ ))) \ (name, __VA_ARGS__ ))) \
M_END_PROTECTED_CODE M_END_PROTECTED_CODE
@@ -62,23 +62,23 @@ M_BEGIN_PROTECTED_CODE
#define ISHAREDI_PTR_OPLIST_P1(arg) ISHAREDI_PTR_OPLIST_P2 arg #define ISHAREDI_PTR_OPLIST_P1(arg) ISHAREDI_PTR_OPLIST_P2 arg
/* Validation of the given oplist */ /* Validation of the given oplist */
#define ISHAREDI_PTR_OPLIST_P2(name, oplist) \ #define ISHAREDI_PTR_OPLIST_P2(name, oplist) \
M_IF_OPLIST(oplist)(ISHAREDI_PTR_OPLIST_P3, ISHAREDI_PTR_OPLIST_FAILURE)(name, oplist) M_IF_OPLIST(oplist)(ISHAREDI_PTR_OPLIST_P3, ISHAREDI_PTR_OPLIST_FAILURE)(name, oplist)
/* Prepare a clean compilation failure */ /* Prepare a clean compilation failure */
#define ISHAREDI_PTR_OPLIST_FAILURE(name, oplist) \ #define ISHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
((M_LIB_ERROR(ARGUMENT_OF_ISHARED_PTR_OPLIST_IS_NOT_AN_OPLIST, name, oplist))) ((M_LIB_ERROR(ARGUMENT_OF_ISHARED_PTR_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
// Define the oplist // Define the oplist
#define ISHAREDI_PTR_OPLIST_P3(name, oplist) ( \ #define ISHAREDI_PTR_OPLIST_P3(name, oplist) ( \
INIT(M_INIT_DEFAULT), \ INIT(M_INIT_DEFAULT), \
INIT_SET(API_4(M_C(name, _init_set))), \ INIT_SET(API_4(M_C(name, _init_set))), \
SET(M_C(name, _set) M_IPTR), \ SET(M_C(name, _set) M_IPTR), \
CLEAR(M_C(name, _clear)), \ CLEAR(M_C(name, _clear)), \
CLEAN(M_C(name, _clean) M_IPTR), \ CLEAN(M_C(name, _clean) M_IPTR), \
TYPE(M_C(name, _t)), \ TYPE(M_C(name, _t)), \
OPLIST(oplist), \ OPLIST(oplist), \
SUBTYPE(M_C(name, _type_t)) \ SUBTYPE(M_C(name, _type_t)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \ ,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \ ,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \ ,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
@@ -92,47 +92,47 @@ M_BEGIN_PROTECTED_CODE
M_IF_OPLIST(oplist)(ISHAREDI_PTR_DEF_P3, ISHAREDI_PTR_DEF_FAILURE)(name, type, oplist) M_IF_OPLIST(oplist)(ISHAREDI_PTR_DEF_P3, ISHAREDI_PTR_DEF_FAILURE)(name, type, oplist)
/* Stop processing with a compilation failure */ /* Stop processing with a compilation failure */
#define ISHAREDI_PTR_DEF_FAILURE(name, type, oplist) \ #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) 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) \ #define ISHAREDI_PTR_DEF_P3(name, type, oplist) \
\ \
typedef type *M_C(name,_t); \ typedef type *M_C(name,_t); \
typedef type M_C(name, _type_t); \ typedef type M_C(name, _type_t); \
\ \
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \ M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\ \
static inline M_C(name,_t) \ static inline M_C(name,_t) \
M_C(name, _init)(type *ptr) \ M_C(name, _init)(type *ptr) \
{ \ { \
if (M_LIKELY (ptr != NULL)) \ if (M_LIKELY (ptr != NULL)) \
atomic_init(&ptr->M_C(name, _cpt), 1); \ atomic_init(&ptr->M_C(name, _cpt), 1); \
return ptr; \ return ptr; \
} \ } \
\ \
static inline M_C(name,_t) \ static inline M_C(name,_t) \
M_C(name, _init_set)(M_C(name,_t) shared) \ M_C(name, _init_set)(M_C(name,_t) shared) \
{ \ { \
if (M_LIKELY (shared != NULL)) { \ if (M_LIKELY (shared != NULL)) { \
int n = atomic_fetch_add(&(shared->M_C(name, _cpt)), 1); \ int n = atomic_fetch_add(&(shared->M_C(name, _cpt)), 1); \
(void) n; \ (void) n; \
} \ } \
return shared; \ return shared; \
} \ } \
\ \
static inline void M_ATTR_DEPRECATED \ static inline void M_ATTR_DEPRECATED \
M_C(name, _init_set2)(M_C(name,_t) *ptr, M_C(name,_t) shared) \ M_C(name, _init_set2)(M_C(name,_t) *ptr, M_C(name,_t) shared) \
{ \ { \
assert (ptr != NULL); \ assert (ptr != NULL); \
*ptr = M_C(name, _init_set)(shared); \ *ptr = M_C(name, _init_set)(shared); \
} \ } \
\ \
M_IF_DISABLED_METHOD(NEW, oplist) \ M_IF_DISABLED_METHOD(NEW, oplist) \
( /* Nothing to do */, M_IF_METHOD(INIT, oplist) \ ( /* Nothing to do */, M_IF_METHOD(INIT, oplist) \
( \ ( \
static inline M_C(name,_t) \ static inline M_C(name,_t) \
M_C(name, _init_new)(void) \ M_C(name, _init_new)(void) \
{ \ { \
type *ptr = M_CALL_NEW(oplist, type); \ type *ptr = M_CALL_NEW(oplist, type); \
if (ptr == NULL) { \ if (ptr == NULL) { \
M_MEMORY_FULL(sizeof(type)); \ M_MEMORY_FULL(sizeof(type)); \
@@ -141,45 +141,45 @@ M_BEGIN_PROTECTED_CODE
M_CALL_INIT(oplist, *ptr); \ M_CALL_INIT(oplist, *ptr); \
atomic_init (&ptr->M_C(name, _cpt), 1); \ atomic_init (&ptr->M_C(name, _cpt), 1); \
return ptr; \ return ptr; \
} \ } \
, /* End of INIT */) \ , /* End of INIT */) \
/* End of NEW */) \ /* End of NEW */) \
\ \
static inline void \ static inline void \
M_C(name, _clear)(M_C(name,_t) shared) \ M_C(name, _clear)(M_C(name,_t) shared) \
{ \ { \
if (shared != NULL) { \ if (shared != NULL) { \
if (atomic_fetch_sub(&(shared->M_C(name, _cpt)), 1) == 1) { \ if (atomic_fetch_sub(&(shared->M_C(name, _cpt)), 1) == 1) { \
M_CALL_CLEAR(oplist, *shared); \ M_CALL_CLEAR(oplist, *shared); \
M_IF_DISABLED_METHOD(DEL, oplist)(, M_CALL_DEL(oplist, shared);) \ M_IF_DISABLED_METHOD(DEL, oplist)(, M_CALL_DEL(oplist, shared);) \
} \ } \
} \ } \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _clear_ptr)(M_C(name,_t) *shared) \ M_C(name, _clear_ptr)(M_C(name,_t) *shared) \
{ \ { \
assert(shared != NULL); \ assert(shared != NULL); \
M_C(name, _clear)(*shared); \ M_C(name, _clear)(*shared); \
*shared = NULL; \ *shared = NULL; \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _clean)(M_C(name,_t) *shared) \ M_C(name, _clean)(M_C(name,_t) *shared) \
{ \ { \
M_C(name, _clear)(*shared); \ M_C(name, _clear)(*shared); \
*shared = NULL; \ *shared = NULL; \
} \ } \
\ \
static inline void \ static inline void \
M_C(name, _set)(M_C(name,_t) *ptr, M_C(name,_t)shared) \ M_C(name, _set)(M_C(name,_t) *ptr, M_C(name,_t)shared) \
{ \ { \
assert (ptr != NULL); \ assert (ptr != NULL); \
if (M_LIKELY (*ptr != shared)) { \ if (M_LIKELY (*ptr != shared)) { \
M_C(name, _clear)(*ptr); \ M_C(name, _clear)(*ptr); \
*ptr = M_C(name, _init_set)(shared); \ *ptr = M_C(name, _init_set)(shared); \
} \ } \
} \ } \
\ \
M_END_PROTECTED_CODE M_END_PROTECTED_CODE
+1 -1
View File
@@ -1118,7 +1118,7 @@ typedef enum {
size_t estimated_size = 0; \ size_t estimated_size = 0; \
type key; \ type key; \
M_C(name,_clean)(t1); \ M_C(name,_clean)(t1); \
ret = f->m_interface->read_array_start(local, f, &estimated_size); \ ret = f->m_interface->read_array_start(local, f, &estimated_size); \
if (M_UNLIKELY (ret != M_SERIAL_OK_CONTINUE)) return ret; \ if (M_UNLIKELY (ret != M_SERIAL_OK_CONTINUE)) return ret; \
M_CALL_INIT(oplist, key); \ M_CALL_INIT(oplist, key); \
do { \ do { \
+31 -31
View File
@@ -578,7 +578,7 @@ string_search_char (const string_t v, char c, size_t start)
STRINGI_CONTRACT (v); STRINGI_CONTRACT (v);
assert (start <= string_size(v)); assert (start <= string_size(v));
const char *p = M_ASSIGN_CAST(const char*, const char *p = M_ASSIGN_CAST(const char*,
strchr(string_get_cstr(v)+start, c)); strchr(string_get_cstr(v)+start, c));
return p == NULL ? STRING_FAILURE : (size_t) (p-string_get_cstr(v)); return p == NULL ? STRING_FAILURE : (size_t) (p-string_get_cstr(v));
} }
@@ -596,7 +596,7 @@ string_search_rchar (const string_t v, char c, size_t start)
// by scanning backward from the bottom of the string (which is // by scanning backward from the bottom of the string (which is
// possible since we know the size) // possible since we know the size)
const char *p = M_ASSIGN_CAST(const char*, const char *p = M_ASSIGN_CAST(const char*,
strrchr(string_get_cstr(v)+start, c)); strrchr(string_get_cstr(v)+start, c));
return p == NULL ? STRING_FAILURE : (size_t) (p-string_get_cstr(v)); return p == NULL ? STRING_FAILURE : (size_t) (p-string_get_cstr(v));
} }
@@ -610,7 +610,7 @@ string_search_str (const string_t v, const char str[], size_t start)
assert (start <= string_size(v)); assert (start <= string_size(v));
M_ASSUME (str != NULL); M_ASSUME (str != NULL);
const char *p = M_ASSIGN_CAST(const char*, const char *p = M_ASSIGN_CAST(const char*,
strstr(string_get_cstr(v)+start, str)); strstr(string_get_cstr(v)+start, str));
return p == NULL ? STRING_FAILURE : (size_t) (p-string_get_cstr(v)); return p == NULL ? STRING_FAILURE : (size_t) (p-string_get_cstr(v));
} }
@@ -636,7 +636,7 @@ string_search_pbrk(const string_t v1, const char first_of[], size_t start)
assert (start <= string_size(v1)); assert (start <= string_size(v1));
M_ASSUME (first_of != NULL); M_ASSUME (first_of != NULL);
const char *p = M_ASSIGN_CAST(const char*, const char *p = M_ASSIGN_CAST(const char*,
strpbrk(string_get_cstr(v1)+start, first_of)); strpbrk(string_get_cstr(v1)+start, first_of));
return p == NULL ? STRING_FAILURE : (size_t) (p-string_get_cstr(v1)); return p == NULL ? STRING_FAILURE : (size_t) (p-string_get_cstr(v1));
} }
@@ -1652,14 +1652,14 @@ namespace m_string {
EXT_ALGO(STRING_SPLIT), \ EXT_ALGO(STRING_SPLIT), \
OOR_EQUAL(string_oor_equal_p), OOR_SET(string_oor_set) \ OOR_EQUAL(string_oor_equal_p), OOR_SET(string_oor_set) \
,SUBTYPE(string_unicode_t) \ ,SUBTYPE(string_unicode_t) \
,IT_TYPE(string_it_t) \ ,IT_TYPE(string_it_t) \
,IT_FIRST(string_it) \ ,IT_FIRST(string_it) \
,IT_END(string_it_end) \ ,IT_END(string_it_end) \
,IT_SET(string_it_set) \ ,IT_SET(string_it_set) \
,IT_END_P(string_end_p) \ ,IT_END_P(string_end_p) \
,IT_EQUAL_P(string_it_equal_p) \ ,IT_EQUAL_P(string_it_equal_p) \
,IT_NEXT(string_next) \ ,IT_NEXT(string_next) \
,IT_CREF(string_cref) \ ,IT_CREF(string_cref) \
) )
/* Register the OPLIST as a global one */ /* Register the OPLIST as a global one */
@@ -1669,31 +1669,31 @@ namespace m_string {
/* Macro encapsulation to give a default value of 0 for start offset */ /* Macro encapsulation to give a default value of 0 for start offset */
/* Search for a character in a string (string, character[, start=0]) */ /* Search for a character in a string (string, character[, start=0]) */
#define string_search_char(v, ...) \ #define string_search_char(v, ...) \
M_APPLY(string_search_char, v, M_IF_DEFAULT1(0, __VA_ARGS__)) M_APPLY(string_search_char, v, M_IF_DEFAULT1(0, __VA_ARGS__))
/* Reverse Search for a character in a string (string, character[, start=0]) */ /* Reverse Search for a character in a string (string, character[, start=0]) */
#define string_search_rchar(v, ...) \ #define string_search_rchar(v, ...) \
M_APPLY(string_search_rchar, v, M_IF_DEFAULT1(0, __VA_ARGS__)) M_APPLY(string_search_rchar, v, M_IF_DEFAULT1(0, __VA_ARGS__))
/* Search for a C string in a string (string, c_string[, start=0]) */ /* Search for a C string in a string (string, c_string[, start=0]) */
#define string_search_str(v, ...) \ #define string_search_str(v, ...) \
M_APPLY(string_search_str, v, M_IF_DEFAULT1(0, __VA_ARGS__)) M_APPLY(string_search_str, v, M_IF_DEFAULT1(0, __VA_ARGS__))
/* Search for a string in a string (string, string[, start=0]) */ /* Search for a string in a string (string, string[, start=0]) */
#define string_search(v, ...) \ #define string_search(v, ...) \
M_APPLY(string_search, v, M_IF_DEFAULT1(0, __VA_ARGS__)) M_APPLY(string_search, v, M_IF_DEFAULT1(0, __VA_ARGS__))
/* PBRK for a string in a string (string, string[, start=0]) */ /* PBRK for a string in a string (string, string[, start=0]) */
#define string_search_pbrk(v, ...) \ #define string_search_pbrk(v, ...) \
M_APPLY(string_search_pbrk, v, M_IF_DEFAULT1(0, __VA_ARGS__)) M_APPLY(string_search_pbrk, v, M_IF_DEFAULT1(0, __VA_ARGS__))
/* Replace a C string to another C string in a string (string, c_src_string, c_dst_string, [, start=0]) */ /* Replace a C string to another C string in a string (string, c_src_string, c_dst_string, [, start=0]) */
#define string_replace_str(v, s1, ...) \ #define string_replace_str(v, s1, ...) \
M_APPLY(string_replace_str, v, s1, M_IF_DEFAULT1(0, __VA_ARGS__)) M_APPLY(string_replace_str, v, s1, M_IF_DEFAULT1(0, __VA_ARGS__))
/* Replace a string to another string in a string (string, src_string, dst_string, [, start=0]) */ /* Replace a string to another string in a string (string, src_string, dst_string, [, start=0]) */
#define string_replace(v, s1, ...) \ #define string_replace(v, s1, ...) \
M_APPLY(string_replace, v, s1, M_IF_DEFAULT1(0, __VA_ARGS__)) M_APPLY(string_replace, v, s1, M_IF_DEFAULT1(0, __VA_ARGS__))
/* Strim a string from the given set of characters (default is " \n\r\t") */ /* Strim a string from the given set of characters (default is " \n\r\t") */
@@ -1706,17 +1706,17 @@ namespace m_string {
/* Select either the string function or the str function depending on /* Select either the string function or the str function depending on
the b operade to the function. the b operade to the function.
func1 is the string function / func2 is the str function. */ func1 is the string function / func2 is the str function. */
# define STRINGI_SELECT2(func1,func2,a,b) \ # define STRINGI_SELECT2(func1,func2,a,b) \
_Generic((b)+0, \ _Generic((b)+0, \
char*: func2, \ char*: func2, \
const char *: func2, \ const char *: func2, \
default : func1 \ default : func1 \
)(a,b) )(a,b)
# define STRINGI_SELECT3(func1,func2,a,b,c) \ # define STRINGI_SELECT3(func1,func2,a,b,c) \
_Generic((b)+0, \ _Generic((b)+0, \
char*: func2, \ char*: func2, \
const char *: func2, \ const char *: func2, \
default : func1 \ default : func1 \
)(a,b,c) )(a,b,c)
/* Init & Set the string a to the string (or C string) b (constructor) */ /* Init & Set the string a to the string (or C string) b (constructor) */
@@ -1739,9 +1739,9 @@ namespace m_string {
#undef string_search #undef string_search
/* Search for a string in a string (or C string) (string, string[, start=0]) */ /* Search for a string in a string (or C string) (string, string[, start=0]) */
#define string_search(v, ...) \ #define string_search(v, ...) \
M_APPLY(STRINGI_SELECT3, string_search, string_search_str, \ M_APPLY(STRINGI_SELECT3, string_search, string_search_str, \
v, M_IF_DEFAULT1(0, __VA_ARGS__)) v, M_IF_DEFAULT1(0, __VA_ARGS__))
/* Internal Macro: Provide GET_STR method to default type */ /* Internal Macro: Provide GET_STR method to default type */
#undef M_GET_STR_METHOD_FOR_DEFAULT_TYPE #undef M_GET_STR_METHOD_FOR_DEFAULT_TYPE
@@ -2131,7 +2131,7 @@ namespace m_string {
} }
}; };
} }
#define BOUNDED_STRING_CTE(name, string) \ #define BOUNDED_STRING_CTE(name, string) \
((const struct M_C(name, _s) *)(m_string::m_bounded_string<sizeof (M_C(name, _t))>(string).s)) ((const struct M_C(name, _s) *)(m_string::m_bounded_string<sizeof (M_C(name, _t))>(string).s))
#endif #endif