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__) ) \
|| (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__cplusplus) && (__GNUC__*100 + __GNUC_MINOR__) >= 409) \
|| (defined(__clang__) && __clang_major__ >= 4) \
|| (defined(__clang__) && __clang_major__ >= 4) \
|| (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1800)
#include <stdatomic.h>
@@ -166,12 +166,12 @@ M_BEGIN_PROTECTED_CODE
_lock : the mutex lock.
Support up to sizeof (long long) type.
*/
#define _Atomic(T) \
struct { \
T volatile _val; \
T _zero; \
T _previous; \
m_mutex_t _lock; \
#define _Atomic(T) \
struct { \
T volatile _val; \
T _zero; \
T _previous; \
m_mutex_t _lock; \
}
/* Define the supported memory order.
+251 -248
View File
@@ -63,14 +63,14 @@ typedef enum {
USAGE: BUFFER_OPLIST(name[, oplist of the type]) */
#define BUFFER_OPLIST(...) \
BUFFERI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST), \
((__VA_ARGS__, M_DEFAULT_OPLIST), \
(__VA_ARGS__ )))
/* Define a nearly lock-free queue for Many Producer Many Consummer
Much faster than queue of BUFFER_DEF in heavy communication scenario
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 \
QUEUEI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((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
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 \
QUEUEI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((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) \
(((policy) & (val)) != 0)
#define BUFFERI_CONTRACT(buffer, size) do { \
assert (buffer != NULL); \
assert (buffer->data != NULL); \
#define BUFFERI_CONTRACT(buffer, size) do { \
assert (buffer != NULL); \
assert (buffer->data != NULL); \
}while (0)
#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)
/* Deferred evaluation for the definition,
@@ -122,7 +122,7 @@ typedef enum {
#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 */ \
size_t idx_prod; /* Index of the production threads */ \
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_cond_init(v->there_is_data); \
m_cond_init(v->there_is_room_for_data); \
} else \
} else { \
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)); \
if (v->data == NULL) { \
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)) { \
for(size_t i = 0; i < size; i++) { \
for(size_t i = 0; i < size; i++) { \
M_CALL_INIT(oplist, v->data[i]); \
} \
} \
} \
BUFFERI_CONTRACT(v,m_size); \
} \
BUFFERI_CONTRACT(v,m_size); \
} \
\
BUFFERI_IF_CTE_SIZE(m_size)( \
static inline void \
@@ -184,13 +186,13 @@ M_C(name, _init)(buffer_t v, size_t size) \
, ) \
\
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)) { \
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]); \
} \
} \
} else { \
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
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; \
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)) \
atomic_store_explicit(&v->number[1], 0UL, memory_order_relaxed); \
BUFFERI_CONTRACT(v,m_size); \
atomic_store_explicit(&v->number[1], 0UL, memory_order_relaxed); \
BUFFERI_CONTRACT(v,m_size); \
} \
\
\
static inline void \
M_C(name, _clear)(buffer_t v) \
M_C(name, _clear)(buffer_t v) \
{ \
BUFFERI_CONTRACT(v,m_size); \
M_C(name, _int_clear_obj)(v); \
BUFFERI_CONTRACT(v,m_size); \
M_C(name, _int_clear_obj)(v); \
BUFFERI_IF_CTE_SIZE(m_size)( , \
M_CALL_FREE(oplist, v->data); \
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); \
} \
} \
\
\
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)) { \
m_mutex_lock(v->mutexPush); \
m_mutex_lock(v->mutexPop); \
} \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
if (BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) \
M_C(name, _int_clear_obj)(v); \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
if (BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) \
M_C(name, _int_clear_obj)(v); \
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)) \
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)) { \
m_cond_broadcast(v->there_is_room_for_data); \
m_mutex_unlock(v->mutexPop); \
m_mutex_unlock(v->mutexPush); \
} \
BUFFERI_CONTRACT(v,m_size); \
BUFFERI_CONTRACT(v,m_size); \
} \
\
\
static inline void \
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); \
} \
\
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \
for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \
M_CALL_INIT_SET(oplist, dest->data[i], v->data[i]); \
} \
} \
} else { \
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
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(dest, m_size); \
} \
\
\
static inline void \
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); \
M_C(name, _int_clear_obj)(dest); \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
M_C(name, _int_clear_obj)(dest); \
\
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]); \
} \
} \
} else { \
size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \
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(dest, m_size); \
} \
\
\
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 \
we considered the queue as empty when the number of \
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 \
return atomic_load_explicit (&v->number[0], memory_order_relaxed) == 0; \
} \
\
\
static inline bool \
M_C(name, _full_p)(buffer_t v) \
{ \
BUFFERI_CONTRACT(v,m_size); \
return atomic_load_explicit (&v->number[0], memory_order_relaxed) \
== BUFFERI_SIZE(m_size); \
BUFFERI_CONTRACT(v,m_size); \
return atomic_load_explicit (&v->number[0], memory_order_relaxed) \
== BUFFERI_SIZE(m_size); \
} \
\
static inline size_t \
\
static inline size_t \
M_C(name, _size)(buffer_t v) \
{ \
BUFFERI_CONTRACT(v,m_size); \
return atomic_load_explicit (&v->number[0], memory_order_relaxed); \
BUFFERI_CONTRACT(v,m_size); \
return atomic_load_explicit (&v->number[0], memory_order_relaxed); \
} \
\
\
static inline bool \
M_C(name, _push_blocking)(buffer_t v, type const data, bool blocking) \
{ \
BUFFERI_CONTRACT(v,m_size); \
\
/* BUFFER lock */ \
BUFFERI_CONTRACT(v,m_size); \
\
/* BUFFER lock */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
m_mutex_lock(v->mutexPush); \
while (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
&& M_C(name, _full_p)(v)) { \
&& M_C(name, _full_p)(v)) { \
if (!blocking) { \
m_mutex_unlock(v->mutexPush); \
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); \
} \
} else if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
&& M_C(name, _full_p)(v)) \
&& M_C(name, _full_p)(v)) \
return false; \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
\
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
\
size_t previousSize, idx = v->idx_prod; \
/* INDEX computation if we have to overwrite the last element */ \
if (M_UNLIKELY (BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
&& M_C(name, _full_p)(v))) { \
v->overwrite++; \
/* INDEX computation if we have to overwrite the last element */ \
if (M_UNLIKELY (BUFFERI_POLICY_P((policy), BUFFER_PUSH_OVERWRITE) \
&& M_C(name, _full_p)(v))) { \
v->overwrite++; \
/* Let's overwrite the last element */ \
/* Compute the index of the last push element */ \
idx--; \
@@ -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; \
} \
/* 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); \
\
} 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 \
like an atomic variable. */ \
/* 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)) { \
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)) { \
m_mutex_unlock(v->mutexPush); \
/* 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); \
} \
} \
\
BUFFERI_CONTRACT(v,m_size); \
\
BUFFERI_CONTRACT(v,m_size); \
return true; \
} \
\
static inline bool \
M_C(name, _pop_blocking)(type *data, buffer_t v, bool blocking) \
{ \
BUFFERI_CONTRACT(v,m_size); \
assert (data != NULL); \
\
/* BUFFER lock */ \
BUFFERI_CONTRACT(v,m_size); \
assert (data != NULL); \
\
/* BUFFER lock */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_THREAD_UNSAFE)) { \
m_mutex_lock(v->mutexPop); \
while (M_C(name, _empty_p)(v)) { \
while (M_C(name, _empty_p)(v)) { \
if (!blocking) { \
m_mutex_unlock(v->mutexPop); \
return false; \
} \
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; \
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
\
BUFFERI_PROTECTED_CONTRACT(v, m_size); \
\
/* POP data from the buffer and update INDEX */ \
if (!BUFFERI_POLICY_P((policy), BUFFER_STACK)) { \
/* 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]); \
} else { \
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 */ \
size_t previousSize; \
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 { \
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)) { \
m_mutex_unlock(v->mutexPop); \
/* 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); \
} \
} \
\
BUFFERI_CONTRACT(v,m_size); \
\
BUFFERI_CONTRACT(v,m_size); \
return true; \
} \
\
\
\
\
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, \
!BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING_PUSH)); \
} \
\
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, \
!BUFFERI_POLICY_P((policy), BUFFER_UNBLOCKING_POP)); \
} \
\
static inline size_t \
M_C(name, _overwrite)(const buffer_t v) \
static inline size_t \
M_C(name, _overwrite)(const buffer_t v) \
{ \
return v->overwrite; \
} \
return v->overwrite; \
} \
\
static inline size_t \
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 */ \
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)) { \
m_mutex_lock(v->mutexPush); \
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
/* 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)
/* 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))
#ifdef NDEBUG
@@ -621,54 +623,55 @@ M_C(name, _init)(buffer_t v, size_t size) \
} while (0)
#endif
#define QUEUEI_MPMC_DEF_P3(name, type, policy, oplist, buffer_t) \
\
/* The sequence number of an element will be equal to either \
- 2* the index of the production which creates it, \
- 1 + 2* the index of the consumption which consummes it \
\
/* The sequence number of an element will be equal to either \
- 2* the index of the production which creates it, \
- 1 + 2* the index of the consumption which consummes it \
In case of wrapping, as there is no order comparison but only \
equal comparison, there is no special issue. \
Each element is put in a separate cache line to avoid false \
sharing. \
*/ \
typedef struct M_C(name, _el_s) { \
atomic_uint seq; /* Can only increase until wrapping */ \
type x; \
*/ \
typedef struct M_C(name, _el_s) { \
atomic_uint seq; /* Can only increase until wrapping */ \
type x; \
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 \
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 */ \
M_CACHELINE_ALIGN(align1, atomic_uint); \
atomic_uint ConsoIdx; /* Can only increase until wrapping */ \
M_CACHELINE_ALIGN(align2, atomic_uint); \
M_C(name, _el_t) *Tab; \
unsigned int size; \
} buffer_t[1]; \
\
static inline bool \
unsigned int size; \
} buffer_t[1]; \
\
static inline bool \
M_C(name, _push)(buffer_t table, type const x) \
{ \
{ \
QUEUEI_MPMC_CONTRACT(table); \
unsigned int idx = atomic_load_explicit(&table->ProdIdx, \
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, \
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 */ \
return false; \
} \
return false; \
} \
if (M_UNLIKELY (!atomic_compare_exchange_strong_explicit(&table->ProdIdx, \
&idx, idx+1, memory_order_relaxed, memory_order_relaxed))) { \
/* Thread has been preempted by another one. */ \
return false; \
} \
&idx, idx+1, memory_order_relaxed, memory_order_relaxed))) { \
/* Thread has been preempted by another one. */ \
return false; \
} \
/* If it is interrupted here, it may block pop method (not push) */ \
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 { \
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); \
QUEUEI_MPMC_CONTRACT(table); \
return true; \
} \
\
static inline bool \
M_C(name, _pop)(type *ptr, buffer_t table) \
{ \
} \
\
static inline bool \
M_C(name, _pop)(type *ptr, buffer_t table) \
{ \
QUEUEI_MPMC_CONTRACT(table); \
assert (ptr != NULL); \
unsigned int iC = atomic_load_explicit(&table->ConsoIdx, \
memory_order_relaxed); \
const unsigned int i = (iC & (table->size -1)); \
memory_order_relaxed); \
const unsigned int i = (iC & (table->size -1)); \
const unsigned int seq = atomic_load_explicit(&table->Tab[i].seq, \
memory_order_acquire); \
if (seq != 2 * iC) { \
if (seq != 2 * iC) { \
/* Nothing in buffer to consumme (or unlikely preemption) */ \
return false; \
} \
return false; \
} \
if (M_UNLIKELY (!atomic_compare_exchange_strong_explicit(&table->ConsoIdx, \
&iC, iC+1, memory_order_relaxed, memory_order_relaxed))) { \
/* Thread has been preempted by another one */ \
return false; \
} \
&iC, iC+1, memory_order_relaxed, memory_order_relaxed))) { \
/* Thread has been preempted by another one */ \
return false; \
} \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, *ptr, table->Tab[i].x); \
} 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); \
QUEUEI_MPMC_CONTRACT(table); \
return true; \
} \
\
static inline void \
M_C(name, _init)(buffer_t buffer, size_t size) \
{ \
assert (buffer != NULL); \
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(((policy) & (BUFFER_STACK|BUFFER_THREAD_UNSAFE|BUFFER_PUSH_OVERWRITE)) == 0); \
atomic_init(&buffer->ProdIdx, (unsigned int) size); \
atomic_init(&buffer->ConsoIdx, (unsigned int) size); \
buffer->size = (unsigned int) size; \
buffer->Tab = M_CALL_REALLOC(oplist, M_C(name, _el_t), NULL, size); \
if (buffer->Tab == NULL) { \
M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \
return; \
} \
if (buffer->Tab == NULL) { \
M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \
return; \
} \
for(unsigned int j = 0; j < (unsigned int) size; j++) { \
atomic_init(&buffer->Tab[j].seq, 2*j+1U); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_INIT(oplist, buffer->Tab[j].x); \
M_CALL_INIT(oplist, buffer->Tab[j].x); \
} \
} \
} \
QUEUEI_MPMC_CONTRACT(buffer); \
} \
\
static inline void \
M_C(name, _clear)(buffer_t buffer) \
{ \
} \
\
static inline void \
M_C(name, _clear)(buffer_t buffer) \
{ \
QUEUEI_MPMC_CONTRACT(buffer); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(unsigned int j = 0; j < buffer->size; j++) { \
M_CALL_CLEAR(oplist, buffer->Tab[j].x); \
} \
} \
} else { \
unsigned int iP = atomic_load_explicit(&buffer->ProdIdx, memory_order_relaxed); \
unsigned int i = iP & (buffer->size -1); \
@@ -751,19 +754,19 @@ M_C(name, _init)(buffer_t v, size_t size) \
j = 0; \
} \
} \
M_CALL_FREE(oplist, buffer->Tab); \
M_CALL_FREE(oplist, buffer->Tab); \
buffer->Tab = NULL; /* safer */ \
} \
\
static inline size_t \
} \
\
static inline size_t \
M_C(name, _size)(buffer_t table) \
{ \
{ \
QUEUEI_MPMC_CONTRACT(table); \
const unsigned int iC = atomic_load_explicit(&table->ConsoIdx, memory_order_relaxed); \
const unsigned int iP = atomic_load_explicit(&table->ProdIdx, memory_order_acquire); \
/* We return an approximation as we can't read both iC & iP atomically \
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 \
(or on overflow occurs, in which case as we compute with modulo \
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 & \
iP. the function is not protected against it. \
*/ \
return iP-iC; \
} \
return iP-iC; \
} \
\
static inline size_t \
M_C(name, _capacity)(buffer_t v) \
M_C(name, _capacity)(buffer_t v) \
{ \
QUEUEI_MPMC_CONTRACT(v); \
return v->size; \
} \
\
static inline bool \
M_C(name, _empty_p)(buffer_t v) \
{ \
return M_C(name, _size) (v) == 0; \
} \
\
static inline bool \
M_C(name, _full_p)(buffer_t v) \
{ \
static inline bool \
M_C(name, _empty_p)(buffer_t v) \
{ \
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; \
} \
} \
@@ -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
/* 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)
/* 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))
#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) \
\
typedef struct M_C(name, _el_s) { \
type x; \
} M_C(name, _el_t); \
\
typedef struct M_C(name, _el_s) { \
type x; \
} M_C(name, _el_t); \
\
typedef struct M_C(name, _s) { \
atomic_uint consoIdx; /* Can only increase until overflow */ \
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 */ \
} buffer_t[1]; \
\
static inline bool \
static inline bool \
M_C(name, _push)(buffer_t table, type const x) \
{ \
{ \
QUEUEI_SPSC_CONTRACT(table); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_relaxed); \
@@ -857,18 +860,18 @@ M_C(name, _init)(buffer_t v, size_t size) \
return false; \
unsigned int i = w & (table->size -1); \
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 { \
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); \
return true; \
} \
\
static inline bool \
static inline bool \
M_C(name, _push_move)(buffer_t table, type x) \
{ \
{ \
QUEUEI_SPSC_CONTRACT(table); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_relaxed); \
@@ -878,24 +881,24 @@ M_C(name, _init)(buffer_t v, size_t size) \
return false; \
unsigned int i = w & (table->size -1); \
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 { \
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); \
return true; \
} \
\
static inline bool \
static inline bool \
M_C(name, _pop)(type *ptr, buffer_t table) \
{ \
{ \
QUEUEI_SPSC_CONTRACT(table); \
assert (ptr != NULL); \
unsigned int w = atomic_load_explicit(&table->prodIdx, \
memory_order_relaxed); \
memory_order_relaxed); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_acquire); \
memory_order_acquire); \
if (w-r == 0) \
return false; \
unsigned int i = r & (table->size -1); \
@@ -904,14 +907,14 @@ M_C(name, _init)(buffer_t v, size_t size) \
} else { \
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); \
return true; \
} \
\
static inline unsigned \
static inline unsigned \
M_C(name, _push_bulk)(buffer_t table, unsigned n, type const x[]) \
{ \
{ \
QUEUEI_SPSC_CONTRACT(table); \
assert (x != NULL); \
assert (n <= table->size); \
@@ -935,16 +938,16 @@ M_C(name, _init)(buffer_t v, size_t size) \
return max; \
} \
\
static inline unsigned \
static inline unsigned \
M_C(name, _pop_bulk)(unsigned int n, type ptr[], buffer_t table) \
{ \
{ \
QUEUEI_SPSC_CONTRACT(table); \
assert (ptr != NULL); \
assert (n <= table->size); \
unsigned int w = atomic_load_explicit(&table->prodIdx, \
memory_order_relaxed); \
memory_order_relaxed); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_acquire); \
memory_order_acquire); \
if (w-r == 0) \
return 0; \
unsigned int max = M_MIN(w-r, n); \
@@ -961,9 +964,9 @@ M_C(name, _init)(buffer_t v, size_t size) \
return max; \
} \
\
static inline void \
static inline void \
M_C(name, _push_force)(buffer_t table, type const x) \
{ \
{ \
QUEUEI_SPSC_CONTRACT(table); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_relaxed); \
@@ -976,11 +979,11 @@ M_C(name, _init)(buffer_t v, size_t size) \
} \
unsigned int i = w & (table->size -1); \
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 { \
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); \
} \
\
@@ -989,12 +992,12 @@ M_C(name, _init)(buffer_t v, size_t size) \
{ \
QUEUEI_SPSC_CONTRACT(table); \
unsigned int r = atomic_load_explicit(&table->consoIdx, \
memory_order_relaxed); \
memory_order_relaxed); \
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 \
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 \
(or on overflow occurs, in which case as we compute with modulo \
arithmetic, the right result is computed). \
@@ -1006,54 +1009,54 @@ M_C(name, _init)(buffer_t v, size_t size) \
} \
\
static inline size_t \
M_C(name, _capacity)(buffer_t v) \
M_C(name, _capacity)(buffer_t v) \
{ \
return v->size; \
} \
\
static inline bool \
M_C(name, _empty_p)(buffer_t v) \
{ \
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 bool \
M_C(name, _empty_p)(buffer_t v) \
{ \
return M_C(name, _size) (v) == 0; \
} \
\
static inline void \
M_C(name, _init)(buffer_t buffer, size_t size) \
{ \
assert (buffer != NULL); \
assert( M_POWEROF2_P(size)); \
static inline bool \
M_C(name, _full_p)(buffer_t v) \
{ \
return M_C(name, _size)(v) >= v->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(((policy) & (BUFFER_STACK|BUFFER_THREAD_UNSAFE|BUFFER_PUSH_OVERWRITE)) == 0); \
atomic_init(&buffer->prodIdx, (unsigned int) size); \
atomic_init(&buffer->consoIdx, (unsigned int) size); \
buffer->size = (unsigned int) size; \
buffer->Tab = M_CALL_REALLOC(oplist, M_C(name, _el_t), NULL, size); \
if (buffer->Tab == NULL) { \
M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \
return; \
} \
if (buffer->Tab == NULL) { \
M_MEMORY_FULL (size*sizeof(M_C(name, _el_t) )); \
return; \
} \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(unsigned int j = 0; j < (unsigned int) size; j++) { \
M_CALL_INIT(oplist, buffer->Tab[j].x); \
M_CALL_INIT(oplist, buffer->Tab[j].x); \
} \
} \
} \
QUEUEI_SPSC_CONTRACT(buffer); \
} \
\
static inline void \
M_C(name, _clear)(buffer_t buffer) \
{ \
} \
\
static inline void \
M_C(name, _clear)(buffer_t buffer) \
{ \
QUEUEI_SPSC_CONTRACT(buffer); \
if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \
for(unsigned int j = 0; j < buffer->size; j++) { \
M_CALL_CLEAR(oplist, buffer->Tab[j].x); \
} \
} \
} else { \
unsigned int iP = atomic_load_explicit(&buffer->prodIdx, memory_order_relaxed); \
unsigned int i = iP & (buffer->size -1); \
@@ -1066,33 +1069,33 @@ M_C(name, _init)(buffer_t v, size_t size) \
j = 0; \
} \
} \
M_CALL_FREE(oplist, buffer->Tab); \
M_CALL_FREE(oplist, buffer->Tab); \
buffer->Tab = NULL; /* safer */ \
} \
\
} \
\
/* Deferred evaluation for the definition,
so that all arguments are evaluated before further expansion */
#define BUFFERI_OPLIST_P1(arg) BUFFERI_OPLIST_P2 arg
/* 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)
/* 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)))
/* OPLIST defininition of a buffer */
#define BUFFERI_OPLIST_P3(name, oplist) \
#define BUFFERI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _int_init)) \
,INIT_SET(M_C(name, _init_set)) \
,SET(M_C(name, _set)) \
,CLEAR(M_C(name, _clear)) \
,TYPE(M_C(name,_t)) \
,SUBTYPE(M_C(name, _type_t)) \
,CLEAN(M_C(name,_clean)) \
,PUSH(M_C(name,_push)) \
,INIT_SET(M_C(name, _init_set)) \
,SET(M_C(name, _set)) \
,CLEAR(M_C(name, _clear)) \
,TYPE(M_C(name,_t)) \
,SUBTYPE(M_C(name, _type_t)) \
,CLEAN(M_C(name,_clean)) \
,PUSH(M_C(name,_push)) \
,POP(M_C(name,_pop)) \
,OPLIST(oplist) \
,TEST_EMPTY(M_C(name, _empty_p)), \
+2 -2
View File
@@ -225,7 +225,7 @@ M_BEGIN_PROTECTED_CODE
memory_order_relaxed)) { \
break; \
} \
/* Failure: perform a random exponential backoff */ \
/* Failure: perform a random exponential backoff */ \
m_core_backoff_wait(bkoff); \
} \
} \
@@ -243,7 +243,7 @@ M_BEGIN_PROTECTED_CODE
/* Dequeue a node if the node is old enough */ \
static inline M_C(name, _lf_node_t) * \
M_C(name, _lflist_pop_if)(M_C(name, _lflist_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) *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))
/* 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 */
#define M_TEST_NDEBUG_P() M_C3(M_, NDEBUG, _TEST)
#define M_NDEBUG_TEST 0
@@ -1374,7 +1374,7 @@ M_BEGIN_PROTECTED_CODE
#define f(...) M_APPLY(f, M_IF_DEFAULT1(0, __VA_ARGS__))
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, )
/* 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_SWAP_DEFAULT(el1, el2) do { \
char _tmp[sizeof (el1)]; \
M_CHECK_SAME(el1, el2); \
M_CHECK_SAME(el1, el2); \
memcpy(&_tmp, &(el1), sizeof (el1)); \
memcpy(&(el1), &(el2), 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.
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)))
/* 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, ) */
#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)))
/* 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.
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__))
/* 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 */
#define M_DO_INIT_MOVE(oplist, dest, src) do { \
M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_INIT_MOVE(oplist, (dest), (src)), \
M_CALL_INIT_SET(oplist, (dest), (src)) ; \
M_CALL_CLEAR(oplist, (src) )); \
M_CALL_INIT_SET(oplist, (dest), (src)) ; \
M_CALL_CLEAR(oplist, (src) )); \
} while (0)
/* Perform a MOVE if present, or emulate it using CLEAR/INIT_MOVE
if possible, or with SET/CLEAR otherwise */
#define M_DO_MOVE(oplist, dest, src) do { \
M_IF_METHOD(MOVE, oplist) (M_CALL_MOVE(oplist, (dest), (src)), \
M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_CLEAR(oplist, (dest)); \
M_CALL_INIT_MOVE(oplist, (dest), (src)), \
M_CALL_SET(oplist, (dest), (src)); \
M_CALL_CLEAR(oplist, (src)) \
M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_CLEAR(oplist, (dest)); \
M_CALL_INIT_MOVE(oplist, (dest), (src)), \
M_CALL_SET(oplist, (dest), (src)); \
M_CALL_CLEAR(oplist, (src)) \
)); \
} while (0)
@@ -2800,13 +2800,13 @@ m_core_parse2_enum (const char str[], const char **endptr)
otherwise it returns the argument.
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)
#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_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)
#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.
*/
#if defined(__cplusplus)
# define M_STATIC_ASSERT(cond, error, msg) \
# define M_STATIC_ASSERT(cond, error, msg) \
([] { static_assert(cond, #error ": " msg); } ())
#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); })
#else
# define M_STATIC_ASSERT(cond, error, msg) \
# define M_STATIC_ASSERT(cond, error, msg) \
((void) sizeof(struct { int error : !!(cond);}))
#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 */
#define FUNCOBJI_INS_NO_ATTR_OPLIST(name) \
#define FUNCOBJI_INS_NO_ATTR_OPLIST(name) \
(NAME(name), TYPE(M_C(name, _t)), \
CLEAR(M_C(name, _clear)), \
INIT(M_C(name,_init)) \
)
/* Validate the oplist before going further */
#define FUNCOBJI_INS_ATTR_OPLIST_P1(name, ...) \
#define FUNCOBJI_INS_ATTR_OPLIST_P1(name, ...) \
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(FUNCOBJI_INS_ATTR_OPLIST_P3, FUNCOBJI_INS_ATTR_OPLIST_FAILURE)(name, __VA_ARGS__)
/* Prepare a clean compilation failure */
#define FUNCOBJI_INS_ATTR_OPLIST_FAILURE(name, ...) \
#define FUNCOBJI_INS_ATTR_OPLIST_FAILURE(name, ...) \
((M_LIB_ERROR(ONE_ARGUMENT_OF_FUNC_OBJ_INS_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__)))
/* Define 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)), \
INIT_WITH(M_C(name, _init_with)), \
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__) )
/* Inject the oplist within the list of arguments */
#define FUNCOBJI_INJECT_GLOBAL(...) \
#define FUNCOBJI_INJECT_GLOBAL(...) \
M_MAP_C(FUNCOBJI_INJECT_OPLIST_A, __VA_ARGS__)
/* Transform (x, type) into (x, type, oplist) if there is global registered oplist
or (x, type, M_DEFAULT_OPLIST) if there is no global one,
or keep (x, type, oplist) if oplist was already present */
#define FUNCOBJI_INJECT_OPLIST_A( duo_or_trio ) \
#define FUNCOBJI_INJECT_OPLIST_A( duo_or_trio ) \
FUNCOBJI_INJECT_OPLIST_B duo_or_trio
#define FUNCOBJI_INJECT_OPLIST_B( f, ... ) \
#define FUNCOBJI_INJECT_OPLIST_B( f, ... ) \
M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) )
// Test if all third argument of all arguments is an oplist
#define FUNCOBJI_IF_ALL_OPLIST(...) \
#define FUNCOBJI_IF_ALL_OPLIST(...) \
M_IF(M_REDUCE(FUNCOBJI_IS_OPLIST_P, M_AND, __VA_ARGS__))
// Test if the third argument is an oplist
#define FUNCOBJI_IS_OPLIST_P(a) \
#define FUNCOBJI_IS_OPLIST_P(a) \
M_OPLIST_P(M_RET_ARG3 a)
/* Validate the oplist before going further */
@@ -297,24 +297,24 @@
/* 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);
/* Define a list of the type of arguments for a function definition */
#define FUNCOBJI_BASE_ARGLIST(name, num, type) \
#define FUNCOBJI_BASE_ARGLIST(name, num, type) \
M_DEFERRED_COMMA type M_C(param_, num)
/* Define a list of arguments for a function call */
#define FUNCOBJI_BASE_ARGCALL(name, num, type) \
#define FUNCOBJI_BASE_ARGCALL(name, num, type) \
M_DEFERRED_COMMA M_C(param_, num)
/* Helper macros */
/* arg = (name, type [, oplist]) */
#define FUNCOBJI_INS_ATTR_STRUCT(arg) \
#define FUNCOBJI_INS_ATTR_STRUCT(arg) \
M_RET_ARG2 arg M_RET_ARG1 arg;
#define FUNCOBJI_INS_ATTR_LIST(arg) \
#define FUNCOBJI_INS_ATTR_LIST(arg) \
M_DEFERRED_COMMA M_RET_ARG2 arg const M_RET_ARG1 arg
#define FUNCOBJI_INS_ATTR_INIT(arg) \
@@ -327,12 +327,12 @@
M_CALL_CLEAR(M_RET_ARG3 arg, obj -> M_RET_ARG1 arg);
/* Define the list of arguments of the instance of the callback */
#define FUNCOBJI_INS_ARGLIST(name, num, param) \
#define FUNCOBJI_INS_ARGLIST(name, num, param) \
M_DEFERRED_COMMA M_C4(name, _param_, num, _t) param
/* Macros for testing for a method presence in all the attributes */
#define FUNCOBJI_TEST_METHOD2_P(method, op) \
#define FUNCOBJI_TEST_METHOD2_P(method, op) \
M_TEST_METHOD_P(method, op)
#define FUNCOBJI_TEST_METHOD1_P(method, arg) \
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__))
/* Macro for checking compatible type and oplist for all the attributes */
#define FUNCOBJI_CONTROL_ALL_OPLIST(name, ...) \
#define FUNCOBJI_CONTROL_ALL_OPLIST(name, ...) \
M_MAP2(FUNCOBJI_CONTROL_OPLIST, name, __VA_ARGS__)
#define FUNCOBJI_CONTROL_OPLIST(name, a) \
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;
*/
#define ILIST_INTERFACE(name, type) \
#define ILIST_INTERFACE(name, type) \
struct ilist_head_s name
/* Define a doubly-linked intrusive list of a given type.
@@ -57,7 +57,7 @@
ILIST_OPLIST(name [, oplist_of_the_type]) */
#define ILIST_OPLIST(...) \
ILISTI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((__VA_ARGS__, M_DEFAULT_OPLIST), \
((__VA_ARGS__, M_DEFAULT_OPLIST), \
(__VA_ARGS__ )))
@@ -73,37 +73,37 @@ typedef struct ilist_head_s {
#define ILISTI_OPLIST_P1(arg) ILISTI_OPLIST_P2 arg
/* 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)
/* 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)))
/* Define the oplist of an ilist of type */
#define ILISTI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _init)), \
CLEAR(M_C(name, _clear)), \
#define ILISTI_OPLIST_P3(name, oplist) \
(INIT(M_C(name, _init)), \
CLEAR(M_C(name, _clear)), \
INIT_MOVE(M_C(name, _init_move)), \
MOVE(M_C(name, _move)), \
TYPE(M_C(name,_t)), \
TYPE(M_C(name,_t)), \
CLEAN(M_C(name,_clean)), \
SUBTYPE(M_C(name,_type_t)), \
SUBTYPE(M_C(name,_type_t)), \
TEST_EMPTY(M_C(name,_empty_p)), \
IT_TYPE(M_C(name,_it_t)), \
IT_FIRST(M_C(name,_it)), \
IT_SET(M_C(name,_it_set)), \
IT_LAST(M_C(name,_it_last)), \
IT_END(M_C(name,_it_end)), \
IT_END_P(M_C(name,_end_p)), \
IT_LAST_P(M_C(name,_last_p)), \
IT_EQUAL_P(M_C(name,_it_equal_p)), \
IT_NEXT(M_C(name,_next)), \
IT_PREVIOUS(M_C(name,_previous)), \
IT_REF(M_C(name,_ref)), \
IT_CREF(M_C(name,_cref)), \
IT_REMOVE(M_C(name,_remove)), \
M_IF_METHOD(NEW, oplist)(IT_INSERT(M_C(name,_insert)),), \
IT_TYPE(M_C(name,_it_t)), \
IT_FIRST(M_C(name,_it)), \
IT_SET(M_C(name,_it_set)), \
IT_LAST(M_C(name,_it_last)), \
IT_END(M_C(name,_it_end)), \
IT_END_P(M_C(name,_end_p)), \
IT_LAST_P(M_C(name,_last_p)), \
IT_EQUAL_P(M_C(name,_it_equal_p)), \
IT_NEXT(M_C(name,_next)), \
IT_PREVIOUS(M_C(name,_previous)), \
IT_REF(M_C(name,_ref)), \
IT_CREF(M_C(name,_cref)), \
IT_REMOVE(M_C(name,_remove)), \
M_IF_METHOD(NEW, oplist)(IT_INSERT(M_C(name,_insert)),), \
OPLIST(oplist), \
SPLICE_BACK(M_C(name,_splice_back)) \
,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 */
#define ILISTI_CONTRACT(name, list) do { \
#define ILISTI_CONTRACT(name, list) do { \
assert(list != NULL); \
assert(list->name.prev != NULL); \
assert(list->name.next != NULL); \
@@ -131,11 +131,11 @@ typedef struct ilist_head_s {
#define ILISTI_DEF_P1(arg) ILISTI_DEF_P2 arg
/* 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)
/* 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)
/* 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)
*/
#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; \
} list_t[1]; \
typedef struct M_C(name, _s) *M_C(name, _ptr); \
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 *previous; \
struct ilist_head_s *current; \
struct ilist_head_s *next; \
} it_t[1]; \
\
\
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); \
list->name.next = &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); \
for(struct ilist_head_s *it = list->name.next, *next ; \
it != &list->name; it = next) { \
ILISTI_CONTRACT(name, list); \
for(struct ilist_head_s *it = list->name.next, *next ; \
it != &list->name; it = next) { \
/* Cannot check node contract as previous node may be deleted */ \
type *obj = M_TYPE_FROM_FIELD(type, it, \
struct ilist_head_s, name); \
/* Read next now before the object is destroyed */ \
next = it->next; \
assert (next != NULL); \
M_CALL_CLEAR(oplist, *obj); \
type *obj = M_TYPE_FROM_FIELD(type, it, \
struct ilist_head_s, name); \
/* Read next now before the object is destroyed */ \
next = it->next; \
assert (next != NULL); \
M_CALL_CLEAR(oplist, *obj); \
/* 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 */ \
list->name.next = &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; \
} \
\
\
\
static inline void M_C(name, _init_move)(list_t list, list_t ref) \
{ \
ILISTI_CONTRACT(name, ref); \
@@ -219,18 +219,18 @@ typedef struct ilist_head_s {
} \
ref->name.next = 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) \
{ \
M_C(name, _clear)(list); \
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; \
for(const struct ilist_head_s *it = list->name.next ; \
it != &list->name; it = it->next) { \
@@ -240,28 +240,28 @@ typedef struct ilist_head_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); \
assert (obj != NULL); \
ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \
struct ilist_head_s *prev = list->name.prev; \
list->name.prev = &obj->name; \
obj->name.prev = prev; \
obj->name.next = &list->name; \
prev->next = &obj->name; \
ILISTI_CONTRACT(name, list); \
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); \
assert (obj != NULL); \
ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \
struct ilist_head_s *next = list->name.next; \
list->name.next = &obj->name; \
obj->name.next = next; \
obj->name.prev = &list->name; \
next->prev = &obj->name; \
ILISTI_CONTRACT(name, list); \
ILISTI_CONTRACT(name, list); \
} \
\
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; \
} \
\
static inline void M_C(name, _init_field)(type *obj) \
static inline void M_C(name, _init_field)(type *obj) \
{ \
assert (obj != NULL); \
obj->name.next = 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); \
struct ilist_head_s *next = obj->name.next; \
@@ -294,50 +294,50 @@ typedef struct ilist_head_s {
} \
\
static inline type * \
M_C(name, _back)(const list_t list) \
M_C(name, _back)(const list_t list) \
{ \
ILISTI_CONTRACT(name, list); \
assert(!M_C(name, _empty_p)(list)); \
ILISTI_CONTRACT(name, list); \
assert(!M_C(name, _empty_p)(list)); \
return M_TYPE_FROM_FIELD(type, list->name.prev, \
struct ilist_head_s, name); \
} \
\
\
static inline type * \
M_C(name, _front)(const list_t list) \
M_C(name, _front)(const list_t list) \
{ \
ILISTI_CONTRACT(name, list); \
assert(!M_C(name, _empty_p)(list)); \
ILISTI_CONTRACT(name, list); \
assert(!M_C(name, _empty_p)(list)); \
return M_TYPE_FROM_FIELD(type, list->name.next, \
struct ilist_head_s, name); \
} \
\
static inline type * \
M_C(name, _next_obj)(const list_t list, type const *obj) \
{ \
ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \
static inline type * \
M_C(name, _next_obj)(const list_t list, type const *obj) \
{ \
ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \
ILISTI_NODE_CONTRACT(&obj->name); \
return obj->name.next == &list->name ? NULL : \
M_TYPE_FROM_FIELD(type, obj->name.next, \
struct ilist_head_s, name); \
} \
\
static inline type * \
M_C(name, _previous_obj)(const list_t list, type const *obj) \
{ \
ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \
return obj->name.next == &list->name ? NULL : \
M_TYPE_FROM_FIELD(type, obj->name.next, \
struct ilist_head_s, name); \
} \
\
static inline type * \
M_C(name, _previous_obj)(const list_t list, type const *obj) \
{ \
ILISTI_CONTRACT(name, list); \
assert (obj != NULL); \
ILISTI_NODE_CONTRACT(&obj->name); \
return obj->name.prev == &list->name ? NULL : \
M_TYPE_FROM_FIELD(type, obj->name.prev, \
struct ilist_head_s, name); \
} \
\
return obj->name.prev == &list->name ? NULL : \
M_TYPE_FROM_FIELD(type, obj->name.prev, \
struct ilist_head_s, name); \
} \
\
static inline void \
M_C(name, _it)(it_t it, const list_t list) \
{ \
ILISTI_CONTRACT(name, list); \
assert (it != NULL); \
ILISTI_CONTRACT(name, list); \
assert (it != NULL); \
it->head = list->name.next->prev; \
it->current = list->name.next; \
it->next = list->name.next->next; \
@@ -355,19 +355,19 @@ typedef struct ilist_head_s {
it->previous = cit->previous; \
ILISTI_NODE_CONTRACT(it->current); \
} \
\
\
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); \
assert (it != NULL); \
ILISTI_CONTRACT(name, list); \
assert (it != NULL); \
it->head = list->name.next->prev; \
it->current = list->name.prev; \
it->next = it->head; \
it->previous = list->name.prev->prev; \
ILISTI_NODE_CONTRACT(it->current); \
} \
\
\
static inline void \
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; \
ILISTI_NODE_CONTRACT(it->current); \
} \
\
\
static inline bool \
M_C(name, _end_p)(const it_t it) \
M_C(name, _end_p)(const it_t it) \
{ \
assert (it != NULL); \
ILISTI_NODE_CONTRACT(it->current); \
return it->current == it->head; \
} \
\
\
static inline bool \
M_C(name, _last_p)(const it_t it) \
{ \
assert (it != NULL); \
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 \
M_C(name, _next)(it_t it) \
{ \
@@ -424,7 +424,7 @@ typedef struct ilist_head_s {
assert (it->next != NULL && it->previous != NULL); \
ILISTI_NODE_CONTRACT(it->current); \
} \
\
\
static inline bool \
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 */ \
return it1->head == it2->head && it1->current == it2->current; \
} \
\
\
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); \
ILISTI_NODE_CONTRACT(it->current); \
/* check if 'it' was not deleted */ \
assert (it->current->next == it->next); \
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, \
struct ilist_head_s, name); \
struct ilist_head_s, name); \
} \
\
\
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); \
} \
\
static inline void \
M_C(name, _remove)(list_t list, it_t it) \
\
static inline void \
M_C(name, _remove)(list_t list, it_t it) \
{ \
ILISTI_CONTRACT(name, list); \
ILISTI_CONTRACT(name, list); \
ILISTI_NODE_CONTRACT(it->current); \
(void)list; /* list param is not used */ \
type *obj = M_TYPE_FROM_FIELD(type, it->current, \
struct ilist_head_s, name); \
M_C(name, _unlink)(obj); \
M_CALL_CLEAR(oplist, obj); \
(void)list; /* list param is not used */ \
type *obj = M_TYPE_FROM_FIELD(type, it->current, \
struct ilist_head_s, name); \
M_C(name, _unlink)(obj); \
M_CALL_CLEAR(oplist, obj); \
M_IF_METHOD(DEL, oplist)(M_CALL_DEL(oplist, obj), (void) 0); \
M_C(name, _next)(it); \
} \
\
M_IF_METHOD(NEW, oplist)( \
static inline void \
M_C(name, _insert)(list_t list, it_t it, type x) \
M_C(name, _next)(it); \
} \
\
M_IF_METHOD(NEW, oplist)( \
static inline void \
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); \
type *p = M_CALL_NEW(oplist, type); \
if (M_UNLIKELY (p == NULL)) { \
M_MEMORY_FULL (sizeof (type)); \
return ; \
} \
M_CALL_INIT_SET(oplist, *p, x); \
type *obj = M_C(name, _ref)(it); \
M_C(name, _push_after)(obj, p); \
it->current = p; \
(void) list; \
ILISTI_CONTRACT(name, list); \
} \
, /* NEW not defined */) \
\
if (M_UNLIKELY (p == NULL)) { \
M_MEMORY_FULL (sizeof (type)); \
return ; \
} \
M_CALL_INIT_SET(oplist, *p, x); \
type *obj = M_C(name, _ref)(it); \
M_C(name, _push_after)(obj, p); \
it->current = p; \
(void) list; \
ILISTI_CONTRACT(name, list); \
} \
, /* NEW not defined */) \
\
static inline type * \
M_C(name, _pop_back)(list_t list) \
M_C(name, _pop_back)(list_t list) \
{ \
ILISTI_CONTRACT(name, list); \
assert (!M_C(name, _empty_p)(list)); \
type *obj = M_C(name, _back)(list); \
ILISTI_CONTRACT(name, list); \
assert (!M_C(name, _empty_p)(list)); \
type *obj = M_C(name, _back)(list); \
list->name.prev = list->name.prev->prev; \
list->name.prev->next = &list->name; \
return obj; \
} \
\
\
static inline type * \
M_C(name, _pop_front)(list_t list) \
M_C(name, _pop_front)(list_t list) \
{ \
ILISTI_CONTRACT(name, list); \
assert (!M_C(name, _empty_p)(list)); \
type *obj = M_C(name, _front)(list); \
ILISTI_CONTRACT(name, list); \
assert (!M_C(name, _empty_p)(list)); \
type *obj = M_C(name, _front)(list); \
list->name.next = list->name.next->next; \
list->name.next->prev = &list->name; \
return obj; \
} \
\
\
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, list2); \
struct ilist_head_s *midle1 = list1->name.prev; \
struct ilist_head_s *midle2 = list2->name.next; \
midle1->next = midle2; \
midle2->prev = midle1; \
list1->name.prev = list2->name.prev; \
list2->name.prev->next = &list1->name; \
list2->name.next = &list2->name; \
list2->name.prev = &list2->name; \
ILISTI_CONTRACT(name, list1); \
ILISTI_CONTRACT(name, list2); \
} \
\
ILISTI_CONTRACT(name, list1); \
ILISTI_CONTRACT(name, list2); \
struct ilist_head_s *midle1 = list1->name.prev; \
struct ilist_head_s *midle2 = list2->name.next; \
midle1->next = midle2; \
midle2->prev = midle1; \
list1->name.prev = list2->name.prev; \
list2->name.prev->next = &list1->name; \
list2->name.next = &list2->name; \
list2->name.prev = &list2->name; \
ILISTI_CONTRACT(name, list1); \
ILISTI_CONTRACT(name, list2); \
} \
\
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, ov); \
ILISTI_CONTRACT(name, nv); \
ILISTI_CONTRACT(name, ov); \
ILISTI_NODE_CONTRACT(it->current); \
assert (it != NULL); \
(void) ov; \
type *obj = M_C(name, _ref)(it); \
M_C(name, _unlink)(obj); \
M_C(name, _push_back)(nv, obj); \
assert (it != NULL); \
(void) ov; \
type *obj = M_C(name, _ref)(it); \
M_C(name, _unlink)(obj); \
M_C(name, _push_back)(nv, obj); \
M_C(name, _next)(it); \
ILISTI_CONTRACT(name, nv); \
ILISTI_CONTRACT(name, ov); \
} \
\
static inline void \
ILISTI_CONTRACT(name, nv); \
ILISTI_CONTRACT(name, ov); \
} \
\
static inline void \
M_C(name, _splice_at)(list_t nlist, it_t npos, \
list_t olist, it_t opos) \
{ \
ILISTI_CONTRACT(name, nlist); \
ILISTI_CONTRACT(name, olist); \
ILISTI_CONTRACT(name, nlist); \
ILISTI_CONTRACT(name, olist); \
assert (npos != NULL && opos != NULL); \
assert (!M_C(name, _end_p)(opos)); \
assert (!M_C(name, _end_p)(opos)); \
/* npos may be end */ \
(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; \
/* Remove object */ \
M_C(name, _unlink)(obj); \
M_C(name, _unlink)(obj); \
/* Push 'obj' after 'ref' */ \
struct ilist_head_s *next = ref->next; \
ref->next = &obj->name; \
@@ -568,15 +568,15 @@ typedef struct ilist_head_s {
npos->previous = ref; \
npos->current = &obj->name; \
npos->next = next; \
ILISTI_CONTRACT(name, nlist); \
ILISTI_CONTRACT(name, olist); \
} \
\
static inline void \
M_C(name, _swap)(list_t d, list_t e) \
{ \
ILISTI_CONTRACT(name, d); \
ILISTI_CONTRACT(name, e); \
ILISTI_CONTRACT(name, nlist); \
ILISTI_CONTRACT(name, olist); \
} \
\
static inline void \
M_C(name, _swap)(list_t d, list_t e) \
{ \
ILISTI_CONTRACT(name, d); \
ILISTI_CONTRACT(name, e); \
struct ilist_head_s *d_item = d->name.next; \
struct ilist_head_s *e_item = e->name.next; \
d->name.next = e_item == &e->name ? &d->name : e_item; \
@@ -589,13 +589,13 @@ typedef struct ilist_head_s {
d->name.prev->next = &d->name; \
e->name.next->prev = &e->name; \
e->name.prev->next = &e->name; \
ILISTI_CONTRACT(name, d); \
ILISTI_CONTRACT(name, e); \
} \
\
static inline void \
ILISTI_CONTRACT(name, d); \
ILISTI_CONTRACT(name, e); \
} \
\
static inline void \
M_C(name, _reverse)(list_t list) \
{ \
{ \
ILISTI_CONTRACT(name, list); \
struct ilist_head_s *next, *it; \
for(it = list->name.next ; it != &list->name; it = next) { \
@@ -607,7 +607,7 @@ typedef struct ilist_head_s {
it->next = it->prev; \
it->prev = next; \
ILISTI_CONTRACT(name, list); \
} \
} \
\
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.
type: name of the type of the structure (aka. struct test_s) - not used currently.
NOTE: There can be only one interface of this kind in a type! */
#define ISHARED_PTR_INTERFACE(name, type) \
#define ISHARED_PTR_INTERFACE(name, type) \
atomic_int M_C(name, _cpt)
@@ -52,7 +52,7 @@ M_BEGIN_PROTECTED_CODE
M_BEGIN_PROTECTED_CODE \
ISHAREDI_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)() ), \
(name, __VA_ARGS__ ))) \
(name, __VA_ARGS__ ))) \
M_END_PROTECTED_CODE
@@ -62,23 +62,23 @@ M_BEGIN_PROTECTED_CODE
#define ISHAREDI_PTR_OPLIST_P1(arg) ISHAREDI_PTR_OPLIST_P2 arg
/* Validation of the given oplist */
#define ISHAREDI_PTR_OPLIST_P2(name, oplist) \
#define ISHAREDI_PTR_OPLIST_P2(name, oplist) \
M_IF_OPLIST(oplist)(ISHAREDI_PTR_OPLIST_P3, ISHAREDI_PTR_OPLIST_FAILURE)(name, oplist)
/* Prepare a clean compilation failure */
#define ISHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
#define ISHAREDI_PTR_OPLIST_FAILURE(name, oplist) \
((M_LIB_ERROR(ARGUMENT_OF_ISHARED_PTR_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
// Define the oplist
#define ISHAREDI_PTR_OPLIST_P3(name, oplist) ( \
INIT(M_INIT_DEFAULT), \
INIT_SET(API_4(M_C(name, _init_set))), \
SET(M_C(name, _set) M_IPTR), \
CLEAR(M_C(name, _clear)), \
CLEAN(M_C(name, _clean) M_IPTR), \
INIT_SET(API_4(M_C(name, _init_set))), \
SET(M_C(name, _set) M_IPTR), \
CLEAR(M_C(name, _clear)), \
CLEAN(M_C(name, _clean) M_IPTR), \
TYPE(M_C(name, _t)), \
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(REALLOC, oplist)(REALLOC(M_GET_REALLOC 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)
/* 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)
#define ISHAREDI_PTR_DEF_P3(name, type, oplist) \
\
typedef type *M_C(name,_t); \
typedef type M_C(name, _type_t); \
typedef type *M_C(name,_t); \
typedef type M_C(name, _type_t); \
\
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
\
static inline M_C(name,_t) \
M_C(name, _init)(type *ptr) \
{ \
M_C(name, _init)(type *ptr) \
{ \
if (M_LIKELY (ptr != NULL)) \
atomic_init(&ptr->M_C(name, _cpt), 1); \
return ptr; \
} \
\
} \
\
static inline M_C(name,_t) \
M_C(name, _init_set)(M_C(name,_t) shared) \
{ \
if (M_LIKELY (shared != NULL)) { \
int n = atomic_fetch_add(&(shared->M_C(name, _cpt)), 1); \
(void) n; \
} \
M_C(name, _init_set)(M_C(name,_t) shared) \
{ \
if (M_LIKELY (shared != NULL)) { \
int n = atomic_fetch_add(&(shared->M_C(name, _cpt)), 1); \
(void) n; \
} \
return shared; \
} \
\
} \
\
static inline void M_ATTR_DEPRECATED \
M_C(name, _init_set2)(M_C(name,_t) *ptr, M_C(name,_t) shared) \
{ \
{ \
assert (ptr != NULL); \
*ptr = M_C(name, _init_set)(shared); \
} \
\
*ptr = M_C(name, _init_set)(shared); \
} \
\
M_IF_DISABLED_METHOD(NEW, oplist) \
( /* Nothing to do */, M_IF_METHOD(INIT, oplist) \
( \
static inline M_C(name,_t) \
M_C(name, _init_new)(void) \
{ \
{ \
type *ptr = M_CALL_NEW(oplist, type); \
if (ptr == NULL) { \
M_MEMORY_FULL(sizeof(type)); \
@@ -141,45 +141,45 @@ M_BEGIN_PROTECTED_CODE
M_CALL_INIT(oplist, *ptr); \
atomic_init (&ptr->M_C(name, _cpt), 1); \
return ptr; \
} \
} \
, /* End of INIT */) \
/* End of NEW */) \
\
static inline void \
\
static inline void \
M_C(name, _clear)(M_C(name,_t) shared) \
{ \
if (shared != NULL) { \
if (atomic_fetch_sub(&(shared->M_C(name, _cpt)), 1) == 1) { \
{ \
if (shared != NULL) { \
if (atomic_fetch_sub(&(shared->M_C(name, _cpt)), 1) == 1) { \
M_CALL_CLEAR(oplist, *shared); \
M_IF_DISABLED_METHOD(DEL, oplist)(, M_CALL_DEL(oplist, shared);) \
} \
} \
} \
} \
\
static inline void \
} \
\
static inline void \
M_C(name, _clear_ptr)(M_C(name,_t) *shared) \
{ \
{ \
assert(shared != NULL); \
M_C(name, _clear)(*shared); \
*shared = NULL; \
} \
\
static inline void \
} \
\
static inline void \
M_C(name, _clean)(M_C(name,_t) *shared) \
{ \
M_C(name, _clear)(*shared); \
{ \
M_C(name, _clear)(*shared); \
*shared = NULL; \
} \
\
static inline void \
static inline void \
M_C(name, _set)(M_C(name,_t) *ptr, M_C(name,_t)shared) \
{ \
{ \
assert (ptr != NULL); \
if (M_LIKELY (*ptr != shared)) { \
M_C(name, _clear)(*ptr); \
*ptr = M_C(name, _init_set)(shared); \
M_C(name, _clear)(*ptr); \
*ptr = M_C(name, _init_set)(shared); \
} \
} \
} \
\
M_END_PROTECTED_CODE
+1 -1
View File
@@ -1118,7 +1118,7 @@ typedef enum {
size_t estimated_size = 0; \
type key; \
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; \
M_CALL_INIT(oplist, key); \
do { \
+31 -31
View File
@@ -578,7 +578,7 @@ string_search_char (const string_t v, char c, size_t start)
STRINGI_CONTRACT (v);
assert (start <= string_size(v));
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));
}
@@ -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
// possible since we know the size)
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));
}
@@ -610,7 +610,7 @@ string_search_str (const string_t v, const char str[], size_t start)
assert (start <= string_size(v));
M_ASSUME (str != NULL);
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));
}
@@ -636,7 +636,7 @@ string_search_pbrk(const string_t v1, const char first_of[], size_t start)
assert (start <= string_size(v1));
M_ASSUME (first_of != NULL);
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));
}
@@ -1652,14 +1652,14 @@ namespace m_string {
EXT_ALGO(STRING_SPLIT), \
OOR_EQUAL(string_oor_equal_p), OOR_SET(string_oor_set) \
,SUBTYPE(string_unicode_t) \
,IT_TYPE(string_it_t) \
,IT_TYPE(string_it_t) \
,IT_FIRST(string_it) \
,IT_END(string_it_end) \
,IT_SET(string_it_set) \
,IT_END_P(string_end_p) \
,IT_EQUAL_P(string_it_equal_p) \
,IT_NEXT(string_next) \
,IT_CREF(string_cref) \
,IT_SET(string_it_set) \
,IT_END_P(string_end_p) \
,IT_EQUAL_P(string_it_equal_p) \
,IT_NEXT(string_next) \
,IT_CREF(string_cref) \
)
/* 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 */
/* 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__))
/* 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__))
/* 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__))
/* 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__))
/* 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__))
/* 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__))
/* 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__))
/* 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
the b operade to the function.
func1 is the string function / func2 is the str function. */
# define STRINGI_SELECT2(func1,func2,a,b) \
_Generic((b)+0, \
char*: func2, \
const char *: func2, \
default : func1 \
# define STRINGI_SELECT2(func1,func2,a,b) \
_Generic((b)+0, \
char*: func2, \
const char *: func2, \
default : func1 \
)(a,b)
# define STRINGI_SELECT3(func1,func2,a,b,c) \
_Generic((b)+0, \
char*: func2, \
const char *: func2, \
default : func1 \
# define STRINGI_SELECT3(func1,func2,a,b,c) \
_Generic((b)+0, \
char*: func2, \
const char *: func2, \
default : func1 \
)(a,b,c)
/* Init & Set the string a to the string (or C string) b (constructor) */
@@ -1739,9 +1739,9 @@ namespace m_string {
#undef string_search
/* Search for a string in a string (or C string) (string, string[, start=0]) */
#define string_search(v, ...) \
M_APPLY(STRINGI_SELECT3, string_search, string_search_str, \
v, M_IF_DEFAULT1(0, __VA_ARGS__))
#define string_search(v, ...) \
M_APPLY(STRINGI_SELECT3, string_search, string_search_str, \
v, M_IF_DEFAULT1(0, __VA_ARGS__))
/* Internal Macro: Provide GET_STR method to 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))
#endif