Replace TAB by SPACE
This commit is contained in:
1 parent
efef35c1e1
commit
5f9feb833c
10 files changed
+1067
-1061
No files matched your search
+7
-7
@@ -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
@@ -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
@@ -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; \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+17
-17
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
Reference in new issue
Block a user