Rename internal types:
a suffix ending with _ct means confidential type ans is reserved for M*LIB internal usage. OPLIST doesn't use the external types but rather the internal types. It enables to be independent of the real names of the external types. Such external names are planned to be fully customizable (i.e. the user may define a name that suits its coding style)
This commit is contained in:
1 parent
eb7556f88f
commit
b3a1a75f6f
27 files changed
+643
-469
No files matched your search
@@ -2227,15 +2227,17 @@ Return true if 'it' references the last element or is no longer valid.
|
||||
|
||||
Update the iterator 'it' to the next element.
|
||||
|
||||
##### struct name\_pair\_s *name\_ref(name\_it\_t it)
|
||||
##### name\_type\_t *name\_ref(name\_it\_t it)
|
||||
|
||||
Return a pointer to the pair composed by the key ('key' field) and its value ('value' field).
|
||||
'key' element can not be modified.
|
||||
Return a pointer to the pair composed by the key ('key' field) and its value ('value' field) if it is not a set,
|
||||
to the key type if it is a set.
|
||||
'key' element shall not be modified.
|
||||
This pointer remains valid until the dictionary is modified by another method.
|
||||
|
||||
##### const struct name\_pair\_s *name\_ref(name\_it\_t it)
|
||||
##### const name\_type\_t *name\_ref(name\_it\_t it)
|
||||
|
||||
Return a constant pointer to the pair composed by the key('key' field) and its value ('value' field).
|
||||
Return a constant pointer to the pair composed by the key ('key' field) and its value ('value' field) if it is not a set,
|
||||
to the key type if it is a set.
|
||||
This pointer remains valid until the dictionary is modified by another method.
|
||||
|
||||
##### void name\_get\_str(string\_t str, const name\_t dict, bool append)
|
||||
|
||||
@@ -142,12 +142,12 @@
|
||||
ALGOI_FIND_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
, /* NO EQUAL */) \
|
||||
\
|
||||
ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, if, M_C(name, _test_cb_t), M_C(name, _eq_cb_t), M_APPLY, M_APPLY) \
|
||||
ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, if, M_C(name, _test_cb_ct), M_C(name, _eq_cb_ct), M_APPLY, M_APPLY) \
|
||||
M_IF_FUNCOBJ(ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, fo, M_C(name, _test_obj_t), M_C(name, _eq_obj_t), M_C(name, _test_obj_call), M_C(name, _eq_obj_call))) \
|
||||
\
|
||||
ALGOI_MAP_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
|
||||
\
|
||||
ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _, M_C(name, _test_cb_t), M_APPLY) \
|
||||
ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _, M_C(name, _test_cb_ct), M_APPLY) \
|
||||
M_IF_FUNCOBJ(ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _fo_, M_C(name, _test_obj_t), M_C(name, _test_obj_call)) ) \
|
||||
\
|
||||
/* If there is a IT_REF method, we consider the container as modifiable through iterator */ \
|
||||
@@ -175,11 +175,11 @@
|
||||
/* Define the types of the callbacks associated to the algorithms */
|
||||
#define ALGOI_CALLBACK_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t)\
|
||||
\
|
||||
typedef bool (*M_C(name, _test_cb_t))(type_t const); \
|
||||
typedef bool (*M_C(name, _eq_cb_t))(type_t const, type_t const); \
|
||||
typedef int (*M_C(name, _cmp_cb_t))(type_t const, type_t const); \
|
||||
typedef void (*M_C(name, _transform_cb_t))(type_t *, type_t const); \
|
||||
typedef void (*M_C(name, _apply_cb_t))(type_t); \
|
||||
typedef bool (*M_C(name, _test_cb_ct))(type_t const); \
|
||||
typedef bool (*M_C(name, _eq_cb_ct))(type_t const, type_t const); \
|
||||
typedef int (*M_C(name, _cmp_cb_ct))(type_t const, type_t const); \
|
||||
typedef void (*M_C(name, _transform_cb_ct))(type_t *, type_t const); \
|
||||
typedef void (*M_C(name, _apply_cb_ct))(type_t); \
|
||||
|
||||
|
||||
/* Define the function objects associated to the algorithms */
|
||||
@@ -752,7 +752,7 @@
|
||||
\
|
||||
/* Apply func for all elements of the container */ \
|
||||
static inline void \
|
||||
M_C(name, _for_each) (container_t l, M_C(name, _apply_cb_t) func) \
|
||||
M_C(name, _for_each) (container_t l, M_C(name, _apply_cb_ct) func) \
|
||||
{ \
|
||||
for M_EACH(item, l, cont_oplist) { \
|
||||
func(*item); \
|
||||
@@ -766,7 +766,7 @@
|
||||
static inline void \
|
||||
M_C(name, _transform) (container_t dst, \
|
||||
container_t src, \
|
||||
M_C(name, _transform_cb_t) func) \
|
||||
M_C(name, _transform_cb_ct) func) \
|
||||
{ \
|
||||
assert(dst != src); \
|
||||
M_CALL_CLEAN(cont_oplist, dst); \
|
||||
@@ -784,7 +784,7 @@
|
||||
M_IF_METHOD(SET, type_oplist)( \
|
||||
static inline void \
|
||||
M_C(name, _reduce) (type_t *dest, container_t const l, \
|
||||
M_C(name, _transform_cb_t) func) \
|
||||
M_C(name, _transform_cb_ct) func) \
|
||||
{ \
|
||||
bool initDone = false; \
|
||||
for M_EACH(item, l, cont_oplist) { \
|
||||
@@ -803,8 +803,8 @@
|
||||
static inline \
|
||||
void M_C(name, _map_reduce) (type_t *dest, \
|
||||
const container_t l, \
|
||||
M_C(name, _transform_cb_t) redFunc, \
|
||||
M_C(name, _transform_cb_t) mapFunc) \
|
||||
M_C(name, _transform_cb_ct) redFunc, \
|
||||
M_C(name, _transform_cb_ct) mapFunc) \
|
||||
{ \
|
||||
bool initDone = false; \
|
||||
type_t tmp; \
|
||||
@@ -950,7 +950,7 @@
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _remove_if)(container_t l, M_C(name, _test_cb_t) func) \
|
||||
M_C(name, _remove_if)(container_t l, M_C(name, _test_cb_ct) func) \
|
||||
{ \
|
||||
it_t it1; \
|
||||
M_CALL_IT_FIRST(cont_oplist, it1, l); \
|
||||
|
||||
@@ -75,10 +75,10 @@
|
||||
,INIT_MOVE(M_C(name, _init_move)) \
|
||||
,MOVE(M_C(name, _move)) \
|
||||
,SWAP(M_C(name, _swap)) \
|
||||
,TYPE(M_C(name,_t)) \
|
||||
,SUBTYPE(M_C(name, _type_t)) \
|
||||
,TYPE(M_C(name,_ct)) \
|
||||
,SUBTYPE(M_C(name, _subtype_ct)) \
|
||||
,TEST_EMPTY(M_C(name,_empty_p)) \
|
||||
,IT_TYPE(M_C(name,_it_t)) \
|
||||
,IT_TYPE(M_C(name,_it_ct)), \
|
||||
,IT_FIRST(M_C(name,_it)) \
|
||||
,IT_LAST(M_C(name,_it_last)) \
|
||||
,IT_END(M_C(name,_it_end)) \
|
||||
@@ -94,7 +94,7 @@
|
||||
,M_IF_AT_LEAST_METHOD(SET,INIT_MOVE,oplist)(IT_REMOVE(M_C(name,_remove)),) \
|
||||
,CLEAN(M_C(name,_clean)) \
|
||||
,KEY_TYPE(size_t) \
|
||||
,VALUE_TYPE(M_C(name, _type_t)) \
|
||||
,VALUE_TYPE(M_C(name, _subtype_ct)) \
|
||||
,KEY_OPLIST(M_DEFAULT_OPLIST) \
|
||||
,VALUE_OPLIST(oplist) \
|
||||
,M_IF_METHOD(SET, oplist)(SET_KEY(M_C(name, _set_at)) ,) \
|
||||
@@ -103,7 +103,7 @@
|
||||
,M_IF_AT_LEAST_METHOD(SET,INIT_MOVE,oplist)(ERASE_KEY(M_C(name, _erase)),) \
|
||||
,GET_SIZE(M_C(name, _size)) \
|
||||
,M_IF_METHOD(INIT_SET, oplist)(PUSH(M_C(name,_push_back)) ,) \
|
||||
,M_IF_AT_LEAST_METHOD(SET,INIT_MOVE,oplist)(POP(M_C(name,_pop_back)) ,) \
|
||||
,M_IF_AT_LEAST_METHOD(SET,INIT_MOVE,oplist)(POP(M_C(name,_pop_back)) ,) \
|
||||
,M_IF_AT_LEAST_METHOD(INIT_SET,INIT_MOVE,oplist)(PUSH_MOVE(M_C(name,_push_move)) ,) \
|
||||
,M_IF_AT_LEAST_METHOD(INIT_SET,INIT_MOVE,oplist)(POP_MOVE(M_C(name,_pop_move)) ,) \
|
||||
,OPLIST(oplist) \
|
||||
@@ -144,8 +144,8 @@
|
||||
- name: prefix to be used
|
||||
- type: type of the elements of the array
|
||||
- oplist: oplist of the type of the elements of the array
|
||||
- array_t: alias for M_C(name, _t) [ type of the array ]
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the array ]
|
||||
- array_t: alias for the type of the array
|
||||
- it_t: alias for the iterator of the array
|
||||
*/
|
||||
#define ARRAYI_DEF_P3(name, type, oplist, array_t, it_t) \
|
||||
\
|
||||
@@ -155,16 +155,19 @@
|
||||
size_t alloc; /* Allocated size for the array base */ \
|
||||
type *ptr; /* Pointer to the array base */ \
|
||||
} array_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 struct M_C(name, _it_s) { \
|
||||
size_t index; /* Index of the element */ \
|
||||
const struct M_C(name, _s) *array; /* Reference of the array */ \
|
||||
} it_t[1]; \
|
||||
\
|
||||
/* Definition of the synonyms of the type */ \
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
typedef array_t M_C(name, _ct); \
|
||||
typedef it_t M_C(name, _it_ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
static inline void \
|
||||
|
||||
+36
-36
@@ -33,9 +33,9 @@
|
||||
M_BEGIN_PROTECTED_CODE
|
||||
|
||||
// Define the basic limb of a bitset
|
||||
typedef uint64_t bitset_limb;
|
||||
typedef uint64_t bitset_limb_ct;
|
||||
// And its size in bits
|
||||
#define BITSET_LIMB_BIT (sizeof(bitset_limb) * CHAR_BIT)
|
||||
#define BITSET_LIMB_BIT (sizeof(bitset_limb_ct) * CHAR_BIT)
|
||||
|
||||
// bitset grow policy. n is limb size
|
||||
#define BITSETI_INC_ALLOC_SIZE(n) ((n) < 4 ? 4 : (n) * 2)
|
||||
@@ -63,7 +63,7 @@ typedef uint64_t bitset_limb;
|
||||
typedef struct bitset_s {
|
||||
size_t size; // Size is the number of bits
|
||||
size_t alloc; // Alloc is the number of allocated limbs
|
||||
bitset_limb *ptr; // Pointer to the allocated limbs
|
||||
bitset_limb_ct *ptr; // Pointer to the allocated limbs
|
||||
} bitset_t[1];
|
||||
|
||||
/* Pointer to a bitset_t */
|
||||
@@ -121,7 +121,7 @@ bitset_set(bitset_t d, const bitset_t s)
|
||||
if (M_UNLIKELY (d == s)) return;
|
||||
const size_t needAlloc = BITSETI_TO_ALLOC (s->size);
|
||||
if (s->size > BITSETI_FROM_ALLOC (d->alloc)) {
|
||||
bitset_limb *ptr = M_MEMORY_REALLOC (bitset_limb, d->ptr, needAlloc);
|
||||
bitset_limb_ct *ptr = M_MEMORY_REALLOC (bitset_limb_ct, d->ptr, needAlloc);
|
||||
if (M_UNLIKELY (ptr == NULL)) {
|
||||
M_MEMORY_FULL(needAlloc);
|
||||
return ;
|
||||
@@ -129,7 +129,7 @@ bitset_set(bitset_t d, const bitset_t s)
|
||||
d->ptr = ptr;
|
||||
d->alloc = needAlloc;
|
||||
}
|
||||
memcpy (d->ptr, s->ptr, needAlloc * sizeof(bitset_limb) );
|
||||
memcpy (d->ptr, s->ptr, needAlloc * sizeof(bitset_limb_ct) );
|
||||
d->size = s->size;
|
||||
BITSETI_CONTRACT(d);
|
||||
}
|
||||
@@ -173,8 +173,8 @@ bitset_set_at(bitset_t v, size_t i, bool x)
|
||||
const size_t offset = i / BITSET_LIMB_BIT;
|
||||
const size_t index = i % BITSET_LIMB_BIT;
|
||||
// This is a branchless version as x can only be 0 or 1 with only one variable shift.
|
||||
const bitset_limb mask = ((bitset_limb)1)<<index;
|
||||
v->ptr[offset] = (v->ptr[offset] & ~mask) | (mask & (0-(bitset_limb)x));
|
||||
const bitset_limb_ct mask = ((bitset_limb_ct)1)<<index;
|
||||
v->ptr[offset] = (v->ptr[offset] & ~mask) | (mask & (0-(bitset_limb_ct)x));
|
||||
BITSETI_CONTRACT (v);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ bitset_flip_at(bitset_t v, size_t i)
|
||||
assert (i < v->size && v->ptr != NULL);
|
||||
size_t offset = i / BITSET_LIMB_BIT;
|
||||
size_t index = i % BITSET_LIMB_BIT;
|
||||
v->ptr[offset] ^= ((bitset_limb)1)<<index;
|
||||
v->ptr[offset] ^= ((bitset_limb_ct)1)<<index;
|
||||
BITSETI_CONTRACT (v);
|
||||
}
|
||||
|
||||
@@ -200,14 +200,14 @@ bitset_push_back (bitset_t v, bool x)
|
||||
const size_t needAlloc = BITSETI_INC_ALLOC_SIZE(v->alloc);
|
||||
// Check for integer overflow
|
||||
if (M_UNLIKELY (needAlloc <= v->alloc)) {
|
||||
M_MEMORY_FULL(needAlloc * sizeof(bitset_limb));
|
||||
M_MEMORY_FULL(needAlloc * sizeof(bitset_limb_ct));
|
||||
return;
|
||||
}
|
||||
// Alloc memory
|
||||
bitset_limb *ptr = M_MEMORY_REALLOC (bitset_limb, v->ptr, needAlloc);
|
||||
bitset_limb_ct *ptr = M_MEMORY_REALLOC (bitset_limb_ct, v->ptr, needAlloc);
|
||||
// Check if success
|
||||
if (M_UNLIKELY (ptr == NULL) ) {
|
||||
M_MEMORY_FULL(needAlloc * sizeof(bitset_limb));
|
||||
M_MEMORY_FULL(needAlloc * sizeof(bitset_limb_ct));
|
||||
return;
|
||||
}
|
||||
// Clear allocated memory
|
||||
@@ -235,9 +235,9 @@ bitset_resize (bitset_t v, size_t size)
|
||||
// Compute the needed allocation.
|
||||
size_t newAlloc = BITSETI_TO_ALLOC (size);
|
||||
if (newAlloc > v->alloc) {
|
||||
bitset_limb *ptr = M_MEMORY_REALLOC (bitset_limb, v->ptr, newAlloc);
|
||||
bitset_limb_ct *ptr = M_MEMORY_REALLOC (bitset_limb_ct, v->ptr, newAlloc);
|
||||
if (M_UNLIKELY (ptr == NULL) ) {
|
||||
M_MEMORY_FULL(newAlloc * sizeof(bitset_limb));
|
||||
M_MEMORY_FULL(newAlloc * sizeof(bitset_limb_ct));
|
||||
return;
|
||||
}
|
||||
v->ptr = ptr;
|
||||
@@ -267,9 +267,9 @@ bitset_reserve (bitset_t v, size_t size)
|
||||
v->size = v->alloc = 0;
|
||||
v->ptr = NULL;
|
||||
} else {
|
||||
bitset_limb *ptr = M_MEMORY_REALLOC (bitset_limb, v->ptr, newAlloc);
|
||||
bitset_limb_ct *ptr = M_MEMORY_REALLOC (bitset_limb_ct, v->ptr, newAlloc);
|
||||
if (M_UNLIKELY (ptr == NULL) ) {
|
||||
M_MEMORY_FULL(newAlloc * sizeof(bitset_limb));
|
||||
M_MEMORY_FULL(newAlloc * sizeof(bitset_limb_ct));
|
||||
return;
|
||||
}
|
||||
v->ptr = ptr;
|
||||
@@ -289,7 +289,7 @@ bitset_get(const bitset_t v, size_t i)
|
||||
assert (v->ptr != NULL && i < v->size);
|
||||
size_t offset = i / BITSET_LIMB_BIT;
|
||||
size_t index = i % BITSET_LIMB_BIT;
|
||||
return ( v->ptr[offset] & (((bitset_limb)1) << index) ) != 0;
|
||||
return ( v->ptr[offset] & (((bitset_limb_ct)1) << index) ) != 0;
|
||||
}
|
||||
|
||||
/* bitset_cget is the exact same service than bitset_get */
|
||||
@@ -372,18 +372,18 @@ bitset_swap (bitset_t v1, bitset_t v2)
|
||||
BITSETI_CONTRACT (v2);
|
||||
M_SWAP (size_t, v1->size, v2->size);
|
||||
M_SWAP (size_t, v1->alloc, v2->alloc);
|
||||
M_SWAP (bitset_limb *, v1->ptr, v2->ptr);
|
||||
M_SWAP (bitset_limb_ct *, v1->ptr, v2->ptr);
|
||||
}
|
||||
|
||||
/* (INTERNAL) Left shift of the bitset (ptr+size) by 1 bit,
|
||||
* integrating the carry in the lowest position.
|
||||
* Return the new carry.
|
||||
*/
|
||||
static inline bitset_limb
|
||||
bitseti_lshift(bitset_limb ptr[], size_t n, bitset_limb carry)
|
||||
static inline bitset_limb_ct
|
||||
bitseti_lshift(bitset_limb_ct ptr[], size_t n, bitset_limb_ct carry)
|
||||
{
|
||||
for(size_t i = 0; i < n; i++) {
|
||||
bitset_limb v = ptr[i];
|
||||
bitset_limb_ct v = ptr[i];
|
||||
ptr[i] = (v << 1) | carry;
|
||||
carry = (v >> (BITSET_LIMB_BIT-1) );
|
||||
}
|
||||
@@ -394,11 +394,11 @@ bitseti_lshift(bitset_limb ptr[], size_t n, bitset_limb carry)
|
||||
* integrating the carry in the lowest position.
|
||||
* Return the new carry.
|
||||
*/
|
||||
static inline bitset_limb
|
||||
bitseti_rshift(bitset_limb ptr[], size_t n, bitset_limb carry)
|
||||
static inline bitset_limb_ct
|
||||
bitseti_rshift(bitset_limb_ct ptr[], size_t n, bitset_limb_ct carry)
|
||||
{
|
||||
for(size_t i = n - 1; i < n; i--) {
|
||||
bitset_limb v = ptr[i];
|
||||
bitset_limb_ct v = ptr[i];
|
||||
v = (v >> 1) | (carry << (BITSET_LIMB_BIT-1) );
|
||||
carry = v & 1;
|
||||
}
|
||||
@@ -416,9 +416,9 @@ bitset_push_at(bitset_t set, size_t key, bool value)
|
||||
// Then shift it
|
||||
size_t offset = key / BITSET_LIMB_BIT;
|
||||
size_t index = key % BITSET_LIMB_BIT;
|
||||
bitset_limb v = set->ptr[offset];
|
||||
bitset_limb mask = (((bitset_limb)1)<<index)-1;
|
||||
bitset_limb carry = (v >> (BITSET_LIMB_BIT-1) );
|
||||
bitset_limb_ct v = set->ptr[offset];
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1)<<index)-1;
|
||||
bitset_limb_ct carry = (v >> (BITSET_LIMB_BIT-1) );
|
||||
v = (v & mask) | ((unsigned int) value << index) | ((v & ~mask) << 1);
|
||||
set->ptr[offset] = v;
|
||||
size_t size = (set->size + BITSET_LIMB_BIT - 1) / BITSET_LIMB_BIT;
|
||||
@@ -443,10 +443,10 @@ bitset_pop_at(bool *dest, bitset_t set, size_t key)
|
||||
size_t offset = key / BITSET_LIMB_BIT;
|
||||
size_t index = key % BITSET_LIMB_BIT;
|
||||
size_t size = (set->size + BITSET_LIMB_BIT - 1) / BITSET_LIMB_BIT;
|
||||
bitset_limb v, mask, carry;
|
||||
bitset_limb_ct v, mask, carry;
|
||||
carry = bitseti_rshift(&set->ptr[offset+1], size - offset - 1, false);
|
||||
v = set->ptr[offset];
|
||||
mask = (((bitset_limb)1)<<index)-1;
|
||||
mask = (((bitset_limb_ct)1)<<index)-1;
|
||||
v = (v & mask) | ((v>>1) & ~mask) | (carry << (BITSET_LIMB_BIT-1)) ;
|
||||
set->ptr[offset] = v;
|
||||
// Decrease size
|
||||
@@ -471,7 +471,7 @@ bitset_equal_p (const bitset_t set1, const bitset_t set2)
|
||||
/* Compare the last limb if needed */
|
||||
const size_t index = set1->size % BITSET_LIMB_BIT;
|
||||
if (index > 0) {
|
||||
const bitset_limb mask = (((bitset_limb)1) << index) - 1;
|
||||
const bitset_limb_ct mask = (((bitset_limb_ct)1) << index) - 1;
|
||||
if ((set1->ptr[limbSize] & mask) != (set2->ptr[limbSize] & mask))
|
||||
return false;
|
||||
}
|
||||
@@ -644,7 +644,7 @@ bitset_and(bitset_t dest, const bitset_t src)
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
dest->ptr[i] &= src->ptr[i];
|
||||
if (m) {
|
||||
bitset_limb mask = (((bitset_limb)1) << m) - 1;
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1) << m) - 1;
|
||||
dest->ptr[n] = (dest->ptr[n] & src->ptr[n]) & mask;
|
||||
}
|
||||
dest->size = s;
|
||||
@@ -664,7 +664,7 @@ bitset_or(bitset_t dest, const bitset_t src)
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
dest->ptr[i] |= src->ptr[i];
|
||||
if (m) {
|
||||
bitset_limb mask = (((bitset_limb)1) << m) - 1;
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1) << m) - 1;
|
||||
dest->ptr[n] = (dest->ptr[n] | src->ptr[n]) & mask;
|
||||
}
|
||||
dest->size = s;
|
||||
@@ -684,7 +684,7 @@ bitset_xor(bitset_t dest, const bitset_t src)
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
dest->ptr[i] ^= src->ptr[i];
|
||||
if (m) {
|
||||
bitset_limb mask = (((bitset_limb)1) << m) - 1;
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1) << m) - 1;
|
||||
dest->ptr[n] = (dest->ptr[n] ^ src->ptr[n]) & mask;
|
||||
}
|
||||
dest->size = s;
|
||||
@@ -702,7 +702,7 @@ bitset_not(bitset_t dest)
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
dest->ptr[i] = ~ (dest->ptr[i]);
|
||||
if (m) {
|
||||
bitset_limb mask = (((bitset_limb)1) << m) - 1;
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1) << m) - 1;
|
||||
dest->ptr[n] = (~ dest->ptr[n]) & mask;
|
||||
}
|
||||
dest->size = s;
|
||||
@@ -721,7 +721,7 @@ bitset_hash(const bitset_t set)
|
||||
for(size_t i = 0 ; i < n; i++)
|
||||
M_HASH_UP(hash, set->ptr[i]);
|
||||
if (m) {
|
||||
bitset_limb mask = (((bitset_limb)1) << m) - 1;
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1) << m) - 1;
|
||||
M_HASH_UP(hash, (set->ptr[n] & mask));
|
||||
}
|
||||
return M_HASH_FINAL (hash);
|
||||
@@ -736,9 +736,9 @@ bitset_clz(const bitset_t set)
|
||||
assert (s > 0);
|
||||
size_t n = (s -1) / BITSET_LIMB_BIT;
|
||||
size_t m = s % BITSET_LIMB_BIT;
|
||||
bitset_limb limb = set->ptr[n];
|
||||
bitset_limb_ct limb = set->ptr[n];
|
||||
if (m) {
|
||||
bitset_limb mask = (((bitset_limb)1) << m) - 1;
|
||||
bitset_limb_ct mask = (((bitset_limb_ct)1) << m) - 1;
|
||||
limb &= mask;
|
||||
} else {
|
||||
m = BITSET_LIMB_BIT;
|
||||
|
||||
+50
-43
@@ -37,8 +37,8 @@
|
||||
#define BPTREE_DEF2(name, N, key_type, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BPTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, N, key_type, M_GLOBAL_OPLIST_OR_DEF(key_type)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 1, 0, M_C(name, _t), M_C(name, _node_t), M_C(name, _pit_t), M_C(name, _it_t) ), \
|
||||
(name, N, key_type, __VA_ARGS__, 1, 0, M_C(name, _t), M_C(name, _node_t), M_C(name, _pit_t), M_C(name, _it_t)))) \
|
||||
((name, N, key_type, M_GLOBAL_OPLIST_OR_DEF(key_type)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 1, 0, M_C(name, _t), M_C(name, _node_ct), M_C(name, _pit_ct), M_C(name, _it_t), M_C(name, _type_t) ), \
|
||||
(name, N, key_type, __VA_ARGS__, 1, 0, M_C(name, _t), M_C(name, _node_ct), M_C(name, _pit_ct), M_C(name, _it_t), M_C(name, _type_t) ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@
|
||||
#define BPTREE_DEF(name, N, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BPTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, N, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 0, 0, M_C(name, _t), M_C(name, _node_t), M_C(name, _pit_t), M_C(name, _it_t) ), \
|
||||
(name, N, __VA_ARGS__, __VA_ARGS__, 0, 0, M_C(name, _t), M_C(name, _node_t), M_C(name, _pit_t), M_C(name, _it_t) ))) \
|
||||
((name, N, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 0, 0, M_C(name, _t), M_C(name, _node_ct), M_C(name, _pit_ct), M_C(name, _it_t), M_C(name, _type_t) ), \
|
||||
(name, N, __VA_ARGS__, __VA_ARGS__, 0, 0, M_C(name, _t), M_C(name, _node_ct), M_C(name, _pit_ct), M_C(name, _it_t), M_C(name, _type_t) ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -64,8 +64,8 @@
|
||||
#define BPTREE_MULTI_DEF2(name, N, key_type, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BPTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, N, key_type, M_GLOBAL_OPLIST_OR_DEF(key_type)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 1, 1, M_C(name, _t), M_C(name, _node_t), M_C(name, _pit_t), M_C(name, _it_t) ), \
|
||||
(name, N, key_type, __VA_ARGS__, 1, 1, M_C(name, _t), M_C(name, _node_t), M_C(name, _pit_t), M_C(name, _it_t)))) \
|
||||
((name, N, key_type, M_GLOBAL_OPLIST_OR_DEF(key_type)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 1, 1, M_C(name, _t), M_C(name, _node_ct), M_C(name, _pit_ct), M_C(name, _it_t), M_C(name, _type_t) ), \
|
||||
(name, N, key_type, __VA_ARGS__, 1, 1, M_C(name, _t), M_C(name, _node_ct), M_C(name, _pit_ct), M_C(name, _it_t), M_C(name, _type_t) ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -76,8 +76,8 @@
|
||||
#define BPTREE_MULTI_DEF(name, N, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BPTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, N, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 0, 1, M_C(name, _t), M_C(name, _node_t), M_C(name, _pit_t), M_C(name, _it_t) ), \
|
||||
(name, N, __VA_ARGS__, __VA_ARGS__, 0, 1, M_C(name, _t), M_C(name, _node_t), M_C(name, _pit_t), M_C(name, _it_t) ))) \
|
||||
((name, N, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), 0, 1, M_C(name, _t), M_C(name, _node_ct), M_C(name, _pit_ct), M_C(name, _it_t), M_C(name, _type_t) ), \
|
||||
(name, N, __VA_ARGS__, __VA_ARGS__, 0, 1, M_C(name, _t), M_C(name, _node_ct), M_C(name, _pit_ct), M_C(name, _it_t), M_C(name, _type_t) ))) \
|
||||
M_BEGIN_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -125,9 +125,9 @@
|
||||
INIT_MOVE(M_C(name, _init_move)), \
|
||||
MOVE(M_C(name, _move)), \
|
||||
SWAP(M_C(name, _swap)), \
|
||||
TYPE(M_C(name,_t)), \
|
||||
SUBTYPE(M_C(name, _type_t)), \
|
||||
IT_TYPE(M_C(name, _it_t)), \
|
||||
TYPE(M_C(name,_ct)), \
|
||||
SUBTYPE(M_C(name, _subtype_ct)), \
|
||||
IT_TYPE(M_C(name, _it_ct)), \
|
||||
IT_FIRST(M_C(name,_it)), \
|
||||
IT_SET(M_C(name,_it_set)), \
|
||||
IT_END(M_C(name,_it_end)), \
|
||||
@@ -174,10 +174,10 @@
|
||||
INIT_MOVE(M_C(name, _init_move)), \
|
||||
MOVE(M_C(name, _move)), \
|
||||
SWAP(M_C(name, _swap)), \
|
||||
TYPE(M_C(name,_t)), \
|
||||
SUBTYPE(M_C(name, _type_t)), \
|
||||
TYPE(M_C(name,_ct)), \
|
||||
SUBTYPE(M_C(name, _subtype_ct)), \
|
||||
TEST_EMPTY(M_C(name,_empty_p)), \
|
||||
IT_TYPE(M_C(name, _it_t)), \
|
||||
IT_TYPE(M_C(name, _it_ct)), \
|
||||
IT_FIRST(M_C(name,_it)), \
|
||||
IT_SET(M_C(name,_it_set)), \
|
||||
IT_END(M_C(name,_it_end)), \
|
||||
@@ -188,8 +188,8 @@
|
||||
CLEAN(M_C(name,_clean)), \
|
||||
GET_MIN(M_C(name,_min)), \
|
||||
GET_MAX(M_C(name,_max)), \
|
||||
KEY_TYPE(M_C(name, _key_type_t)), \
|
||||
VALUE_TYPE(M_C(name, _value_type_t)), \
|
||||
KEY_TYPE(M_C(name, _key_ct)), \
|
||||
VALUE_TYPE(M_C(name, _value_ct)), \
|
||||
SET_KEY(M_C(name, _set_at)), \
|
||||
GET_KEY(M_C(name, _get)), \
|
||||
ERASE_KEY(M_C(name, _erase)), \
|
||||
@@ -210,7 +210,7 @@
|
||||
|
||||
|
||||
|
||||
/* Internal contract of a B+TREE node 'node' or root 'root' */
|
||||
/* Internal contract of a B+TREE of size 'N' for a node 'node' or root 'root' */
|
||||
#ifdef NDEBUG
|
||||
# define BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, node, root) do { } while (0)
|
||||
#else
|
||||
@@ -238,6 +238,7 @@
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Contract for a B+TREE of size N named 'b' */
|
||||
#define BPTREEI_CONTRACT(N, isMulti, key_oplist, b) do { \
|
||||
assert (N >= 3); /* TBC: 2 instead ? */ \
|
||||
BPTREEI_NODE_CONTRACT(N, isMulti, key_oplist, (b)->root, (b)->root); \
|
||||
@@ -253,15 +254,15 @@
|
||||
#define BPTREEI_DEF_P1(arg) BPTREEI_DEF_P2 arg
|
||||
|
||||
/* Validate the key oplist before going further */
|
||||
#define BPTREEI_DEF_P2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
|
||||
M_IF_OPLIST(key_oplist)(BPTREEI_DEF_P3, BPTREEI_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t)
|
||||
#define BPTREEI_DEF_P2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
M_IF_OPLIST(key_oplist)(BPTREEI_DEF_P3, BPTREEI_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
|
||||
/* Validate the value oplist before going further */
|
||||
#define BPTREEI_DEF_P3(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
|
||||
M_IF_OPLIST(value_oplist)(BPTREEI_DEF_P4, BPTREEI_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t)
|
||||
#define BPTREEI_DEF_P3(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
M_IF_OPLIST(value_oplist)(BPTREEI_DEF_P4, BPTREEI_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define BPTREEI_DEF_FAILURE(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
|
||||
#define BPTREEI_DEF_FAILURE(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(BPTREE*_DEF): one of the given argument is not a valid oplist: " M_AS_STR(key_oplist) " / " M_AS_STR(value_oplist))
|
||||
|
||||
/* Internal b+tree definition
|
||||
@@ -273,12 +274,13 @@
|
||||
- value_oplist: oplist of the value type of the elements of the container
|
||||
- isMap: true if map, false if set
|
||||
- isMulti: true if multimap/multiset, false otherwise
|
||||
- tree_t: alias for M_C(name, _t) [ type of the container ]
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
- node_t: alias for M_C(name, _node_t) [ node ]
|
||||
- pit_t: alias for M_C(name, _pit_t) [parent iterator]
|
||||
- tree_t: alias for the type of the container
|
||||
- it_t: alias for the iterator of the container
|
||||
- node_t: alias for internal node
|
||||
- pit_t: alias for internal parent iterator
|
||||
- subtype_t: alias for the type referenced by the iterator
|
||||
*/
|
||||
#define BPTREEI_DEF_P4(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
|
||||
#define BPTREEI_DEF_P4(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
\
|
||||
M_IF(isMap)( \
|
||||
/* Type returned by the iterator. Due to having key and value \
|
||||
@@ -287,12 +289,10 @@
|
||||
typedef struct M_C(name, _pair_s) { \
|
||||
key_t *key_ptr; \
|
||||
value_t *value_ptr; \
|
||||
} M_C(name, _type_t); \
|
||||
} subtype_t; \
|
||||
, \
|
||||
typedef key_t M_C(name, _type_t); \
|
||||
) \
|
||||
typedef key_t M_C(name, _key_type_t); \
|
||||
typedef value_t M_C(name, _value_type_t); \
|
||||
typedef key_t subtype_t; \
|
||||
) \
|
||||
\
|
||||
/* Node of a B+TREE */ \
|
||||
typedef struct M_C(name, _node_s) { \
|
||||
@@ -313,6 +313,12 @@
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
\
|
||||
/* Definition of the alias used by the oplists */ \
|
||||
typedef subtype_t M_C(name, _subtype_ct); \
|
||||
typedef key_t M_C(name, _key_ct); \
|
||||
typedef value_t M_C(name, _value_ct); \
|
||||
typedef tree_t M_C(name, _ct); \
|
||||
\
|
||||
/* Parent Iterator */ \
|
||||
typedef struct M_C(name, _parent_it_s) { \
|
||||
int num; \
|
||||
@@ -325,6 +331,7 @@
|
||||
node_t node; \
|
||||
int idx; \
|
||||
} it_t[1]; \
|
||||
typedef it_t M_C(name, _it_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, key_t, key_oplist) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 2, value_t, value_oplist) \
|
||||
@@ -961,7 +968,7 @@
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static inline M_C(name, _type_t) * \
|
||||
static inline subtype_t * \
|
||||
M_C(name, _ref)(it_t it) \
|
||||
{ \
|
||||
assert (it != NULL && it->node != NULL); \
|
||||
@@ -975,10 +982,10 @@
|
||||
); \
|
||||
} \
|
||||
\
|
||||
static inline M_C(name, _type_t) const * \
|
||||
static inline subtype_t const * \
|
||||
M_C(name, _cref)(it_t it) \
|
||||
{ \
|
||||
return M_CONST_CAST(M_C(name, _type_t), M_C(name, _ref)(it)); \
|
||||
return M_CONST_CAST(subtype_t, M_C(name, _ref)(it)); \
|
||||
} \
|
||||
\
|
||||
\
|
||||
@@ -1099,12 +1106,12 @@
|
||||
BPTREEI_CONTRACT(N, isMulti, key_oplist, tree2); \
|
||||
} \
|
||||
\
|
||||
BPTREEI_FUNC_ADDITIONAL_DEF2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t)
|
||||
BPTREEI_FUNC_ADDITIONAL_DEF2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t)
|
||||
|
||||
|
||||
/* Define additional functions.
|
||||
Do not used any fields but the already defined methods */
|
||||
#define BPTREEI_FUNC_ADDITIONAL_DEF2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
|
||||
#define BPTREEI_FUNC_ADDITIONAL_DEF2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
|
||||
\
|
||||
M_IF_METHOD_BOTH(EQUAL, key_oplist, value_oplist)( \
|
||||
static inline bool M_C(name,_equal_p)(const tree_t t1, const tree_t t2) { \
|
||||
@@ -1123,8 +1130,8 @@
|
||||
M_C(name, _it)(it2, t2); \
|
||||
while (!M_C(name, _end_p)(it1) \
|
||||
&& !M_C(name, _end_p)(it2)) { \
|
||||
const M_C(name, _type_t) *ref1 = M_C(name, _cref)(it1); \
|
||||
const M_C(name, _type_t) *ref2 = M_C(name, _cref)(it2); \
|
||||
const subtype_t *ref1 = M_C(name, _cref)(it1); \
|
||||
const subtype_t *ref2 = M_C(name, _cref)(it2); \
|
||||
M_IF(isMap)( \
|
||||
if (!M_CALL_EQUAL(key_oplist, *ref1->key_ptr, *ref2->key_ptr)) \
|
||||
return false; \
|
||||
@@ -1151,7 +1158,7 @@
|
||||
it_t it1; \
|
||||
M_C(name, _it)(it1, t1); \
|
||||
while (!M_C(name, _end_p)(it1)) { \
|
||||
const M_C(name, _type_t) *ref1 = M_C(name, _cref)(it1); \
|
||||
subtype_t const *ref1 = M_C(name, _cref)(it1); \
|
||||
M_IF(isMap)( \
|
||||
M_HASH_UP(hash, M_CALL_HASH(key_oplist, *ref1->key_ptr)); \
|
||||
M_HASH_UP(hash, M_CALL_HASH(value_oplist, *ref1->value_ptr)); \
|
||||
@@ -1179,7 +1186,7 @@
|
||||
if (commaToPrint) \
|
||||
string_push_back (str, M_GET_SEPARATOR key_oplist); \
|
||||
commaToPrint = true; \
|
||||
const M_C(name, _type_t) *ref1 = M_C(name, _cref)(it); \
|
||||
subtype_t const *ref1 = M_C(name, _cref)(it); \
|
||||
M_IF(isMap)( \
|
||||
M_CALL_GET_STR(key_oplist, str, *ref1->key_ptr, true); \
|
||||
string_cat_str(str, ":"); \
|
||||
@@ -1207,7 +1214,7 @@
|
||||
if (commaToPrint) \
|
||||
fputc (M_GET_SEPARATOR key_oplist, file); \
|
||||
commaToPrint = true; \
|
||||
const M_C(name, _type_t) *ref1 = M_C(name, _cref)(it); \
|
||||
subtype_t const *ref1 = M_C(name, _cref)(it); \
|
||||
M_IF(isMap)( \
|
||||
M_CALL_OUT_STR(key_oplist, file, *ref1->key_ptr); \
|
||||
fputc (':', file); \
|
||||
@@ -1308,7 +1315,7 @@
|
||||
assert (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_return_code_t ret; \
|
||||
m_serial_local_t local; \
|
||||
const M_C(name, _type_t) *item; \
|
||||
subtype_t const *item; \
|
||||
bool first_done = false; \
|
||||
it_t it; \
|
||||
/* Format is different between associative container \
|
||||
|
||||
+33
-4
@@ -120,6 +120,14 @@ typedef enum {
|
||||
#define BUFFERI_DEF_FAILURE(name, type, m_size, policy, oplist, buffer_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(BUFFER_DEF): the given argument is not a valid oplist: " M_AS_STR(oplist))
|
||||
|
||||
/* Define the buffer type using mutex lock and its functions.
|
||||
- name: main prefix of the container
|
||||
- type: type of an element of the buffer
|
||||
- m_size: constant to 0 if variable runtime size, or else the fixed size of the buffer
|
||||
- policy: the policy of the buffer
|
||||
- oplist: the oplist of the type of an element of the buffer
|
||||
- buffer_t: name of the buffer
|
||||
*/
|
||||
#define BUFFERI_DEF_P3(name, type, m_size, policy, oplist, buffer_t) \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
@@ -141,7 +149,8 @@ typedef enum {
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
typedef union { M_C(name, _srcptr) cptr; M_C(name, _ptr) ptr; } M_C(name, _uptr); \
|
||||
typedef type M_C(name, _type_t); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
typedef buffer_t M_C(name, _ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
@@ -624,6 +633,13 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the buffer type MPMC using atomics and its functions.
|
||||
- name: main prefix of the container
|
||||
- type: type of an element of the buffer
|
||||
- policy: the policy of the buffer
|
||||
- oplist: the oplist of the type of an element of the buffer
|
||||
- buffer_t: name of the buffer
|
||||
*/
|
||||
#define QUEUEI_MPMC_DEF_P3(name, type, policy, oplist, buffer_t) \
|
||||
\
|
||||
/* The sequence number of an element will be equal to either \
|
||||
@@ -651,6 +667,9 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
unsigned int size; \
|
||||
} buffer_t[1]; \
|
||||
\
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
typedef buffer_t M_C(name, _ct); \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _push)(buffer_t table, type const x) \
|
||||
{ \
|
||||
@@ -834,6 +853,13 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Define the buffer type SPSC using atomics and its functions.
|
||||
- name: main prefix of the container
|
||||
- type: type of an element of the buffer
|
||||
- policy: the policy of the buffer
|
||||
- oplist: the oplist of the type of an element of the buffer
|
||||
- buffer_t: name of the buffer
|
||||
*/
|
||||
#define QUEUEI_SPSC_DEF_P3(name, type, policy, oplist, buffer_t) \
|
||||
\
|
||||
typedef struct M_C(name, _el_s) { \
|
||||
@@ -848,6 +874,9 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
atomic_uint prodIdx; /* Can only increase until overflow */ \
|
||||
} buffer_t[1]; \
|
||||
\
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
typedef buffer_t M_C(name, _ct); \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _push)(buffer_t table, type const x) \
|
||||
{ \
|
||||
@@ -1086,14 +1115,14 @@ M_C(name, _init)(buffer_t v, size_t size) \
|
||||
#define BUFFERI_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_BUFFER_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
/* OPLIST defininition of a buffer */
|
||||
/* OPLIST definition of a buffer */
|
||||
#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)) \
|
||||
,TYPE(M_C(name,_ct)) \
|
||||
,SUBTYPE(M_C(name, _subtype_ct)) \
|
||||
,CLEAN(M_C(name,_clean)) \
|
||||
,PUSH(M_C(name,_push)) \
|
||||
,POP(M_C(name,_pop)) \
|
||||
|
||||
+1
-1
@@ -677,7 +677,7 @@ m_gc_sleep(m_gc_t gc_mem, m_gc_tid_t id)
|
||||
|
||||
/***********************************************************************/
|
||||
/* */
|
||||
/* VLA MEMPOOL */
|
||||
/* Variable Length Array MEMPOOL */
|
||||
/* */
|
||||
/***********************************************************************/
|
||||
|
||||
|
||||
+6
-4
@@ -87,8 +87,8 @@
|
||||
,M_IF_METHOD(INIT_MOVE, oplist)(INIT_MOVE(M_C(name, _init_move)),) \
|
||||
,M_IF_METHOD(MOVE, oplist)(MOVE(M_C(name, _move)),) \
|
||||
,M_IF_METHOD(SWAP,oplist)(SWAP(M_C(name, _swap)),) \
|
||||
,TYPE(M_C(name,_t)) \
|
||||
,SUBTYPE(M_C(name, _type_t)) \
|
||||
,TYPE(M_C(name,_ct)) \
|
||||
,SUBTYPE(M_C(name, _subtype_ct)) \
|
||||
,OPLIST(oplist) \
|
||||
,M_IF_METHOD(TEST_EMPTY, oplist)(TEST_EMPTY(M_C(name,_empty_p)),) \
|
||||
,M_IF_METHOD(GET_SIZE, oplist)(GET_SIZE(M_C(name,_size)),) \
|
||||
@@ -132,7 +132,7 @@
|
||||
M_IF_OPLIST(oplist)(CONCURRENTI_DEF_P3, CONCURRENTI_DEF_FAILURE)(name, type, oplist, concurrent_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define CONCURRENTI_DEF_FAILURE(name, type, oplist, concurrent_t) \
|
||||
#define CONCURRENTI_DEF_FAILURE(name, type, oplist, concurrent_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(CONCURRENT_DEF): the given argument is not a valid oplist: " M_AS_STR(oplist))
|
||||
|
||||
/* Internal concurrent definition
|
||||
@@ -153,7 +153,9 @@
|
||||
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); \
|
||||
/* Internal types for oplist */ \
|
||||
typedef concurrent_t M_C(name, _ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#define DEQUE_DEF(name, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
DEQUEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name,_it_t), M_C(name, _node_t) ), \
|
||||
(name, __VA_ARGS__, M_C(name,_t), M_C(name,_it_t), M_C(name, _node_t)))) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name,_it_t), M_C(name, _node_ct) ), \
|
||||
(name, __VA_ARGS__, M_C(name,_t), M_C(name,_it_t), M_C(name, _node_ct)))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
- oplist: oplist of the type of the elements of the container
|
||||
- deque_t: alias for M_C(name, _t) [ type of the container ]
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
- node_t: alias for M_C(name, _node_t) [ node ]
|
||||
- node_t: alias for node_t [ node ]
|
||||
*/
|
||||
#define DEQUEI_DEF_P3(name, type, oplist, deque_t, it_t, node_t) \
|
||||
\
|
||||
@@ -139,25 +139,28 @@
|
||||
const struct M_C(name, _s) *deque; \
|
||||
} it_t[1]; \
|
||||
\
|
||||
typedef type M_C(name, _type_t); \
|
||||
/* Define internal types for oplist */ \
|
||||
typedef deque_t M_C(name, _ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
typedef it_t M_C(name, _it_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
static inline M_C(name, _node_t)* \
|
||||
static inline node_t* \
|
||||
M_C(name, _int_new_node)(deque_t d) \
|
||||
{ \
|
||||
size_t def = d->default_size; \
|
||||
/* Test for overflow of the size computation */ \
|
||||
if (M_UNLIKELY (def > SIZE_MAX / sizeof (type) - sizeof(M_C(name, _node_t)))) { \
|
||||
M_MEMORY_FULL(sizeof(M_C(name, _node_t))+def * sizeof(type)); \
|
||||
if (M_UNLIKELY (def > SIZE_MAX / sizeof (type) - sizeof(node_t))) { \
|
||||
M_MEMORY_FULL(sizeof(node_t)+def * sizeof(type)); \
|
||||
return NULL; \
|
||||
} \
|
||||
/* Alloc a new node */ \
|
||||
M_C(name, _node_t)*n = (M_C(name, _node_t)*) (void*) \
|
||||
node_t*n = (node_t*) (void*) \
|
||||
M_CALL_REALLOC(oplist, char, NULL, \
|
||||
sizeof(M_C(name, _node_t)) + def * sizeof(type) ); \
|
||||
sizeof(node_t) + def * sizeof(type) ); \
|
||||
if (n==NULL) { \
|
||||
M_MEMORY_FULL(sizeof(M_C(name, _node_t))+def * sizeof(type)); \
|
||||
M_MEMORY_FULL(sizeof(node_t)+def * sizeof(type)); \
|
||||
return NULL; \
|
||||
} \
|
||||
/* Initialize the node */ \
|
||||
@@ -177,7 +180,7 @@
|
||||
M_C(name, _node_list_init)(d->list); \
|
||||
d->default_size = DEQUEUI_DEFAULT_SIZE; \
|
||||
d->count = 0; \
|
||||
M_C(name, _node_t) *n = M_C(name, _int_new_node)(d); \
|
||||
node_t *n = M_C(name, _int_new_node)(d); \
|
||||
if (n == NULL) return; \
|
||||
M_C(name, _node_list_push_back)(d->list, n); \
|
||||
d->front->node = n; \
|
||||
@@ -191,8 +194,8 @@
|
||||
M_C(name, _clean)(deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_C(name, _node_t) *min_node = NULL; \
|
||||
for(M_C(name, _node_t) *n = d->front->node; \
|
||||
node_t *min_node = NULL; \
|
||||
for(node_t *n = d->front->node; \
|
||||
n != NULL ; \
|
||||
n = (n == d->back->node) ? NULL : \
|
||||
M_C(name, _node_list_next_obj)(d->list, n) ){ \
|
||||
@@ -229,7 +232,7 @@
|
||||
M_C(name, _push_back_raw)(deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_C(name, _node_t) *n = d->back->node; \
|
||||
node_t *n = d->back->node; \
|
||||
size_t index = d->back->index; \
|
||||
if (M_UNLIKELY (n->size <= index)) { \
|
||||
/* try to get an already allocated node */ \
|
||||
@@ -286,7 +289,7 @@
|
||||
M_C(name, _push_front_raw)(deque_t d) \
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
M_C(name, _node_t) *n = d->front->node; \
|
||||
node_t *n = d->front->node; \
|
||||
size_t index = d->front->index; \
|
||||
index --; \
|
||||
/* If overflow */ \
|
||||
@@ -343,14 +346,14 @@
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
assert(d->count > 0); \
|
||||
M_C(name, _node_t) *n = d->back->node; \
|
||||
node_t *n = d->back->node; \
|
||||
size_t index = d->back->index; \
|
||||
index --; \
|
||||
if (M_UNLIKELY (n->size <= index)) { \
|
||||
/* If there is a next node, \
|
||||
pop the back node and push it back to the front. This \
|
||||
reduce the used memory if the deque is used as a FIFO queue.*/ \
|
||||
M_C(name, _node_t) *next = M_C(name, _node_list_next_obj)(d->list, n); \
|
||||
node_t *next = M_C(name, _node_list_next_obj)(d->list, n); \
|
||||
if (next != NULL) { \
|
||||
next = M_C(name, _node_list_pop_back)(d->list); \
|
||||
assert (next != n); \
|
||||
@@ -389,13 +392,13 @@
|
||||
{ \
|
||||
DEQUEI_CONTRACT(d); \
|
||||
assert(d->count > 0); \
|
||||
M_C(name, _node_t) *n = d->front->node; \
|
||||
node_t *n = d->front->node; \
|
||||
size_t index = d->front->index; \
|
||||
if (M_UNLIKELY (n->size <= index)) { \
|
||||
/* If there is a previous node, \
|
||||
pop the front node and push it back to the back. This \
|
||||
reduce the used memory if the deque is used as a FIFO queue.*/ \
|
||||
M_C(name,_node_t) *prev = M_C(name, _node_list_previous_obj)(d->list, n); \
|
||||
node_t *prev = M_C(name, _node_list_previous_obj)(d->list, n); \
|
||||
if (prev != NULL) { \
|
||||
prev = M_C(name, _node_list_pop_front)(d->list); \
|
||||
assert (prev != n); \
|
||||
@@ -435,7 +438,7 @@
|
||||
DEQUEI_CONTRACT(d); \
|
||||
assert (d->count > 0); \
|
||||
size_t i = d->back->index; \
|
||||
M_C(name, _node_t) *n = d->back->node; \
|
||||
node_t *n = d->back->node; \
|
||||
if (M_UNLIKELY (i == 0)) { \
|
||||
n = M_C(name, _node_list_previous_obj)(d->list, n); \
|
||||
assert (n != NULL); \
|
||||
@@ -450,7 +453,7 @@
|
||||
DEQUEI_CONTRACT(d); \
|
||||
assert (d->count > 0); \
|
||||
size_t i = d->front->index; \
|
||||
M_C(name, _node_t) *n = d->front->node; \
|
||||
node_t *n = d->front->node; \
|
||||
if (M_UNLIKELY (n->size <= i)) { \
|
||||
n = M_C(name, _node_list_next_obj)(d->list, n); \
|
||||
assert (n != NULL); \
|
||||
@@ -471,7 +474,7 @@
|
||||
{ \
|
||||
DEQUEI_CONTRACT(v); \
|
||||
size_t s = 0; \
|
||||
for(M_C(name, _node_t) *n = M_C(name, _node_list_back)(v->list); \
|
||||
for(node_t *n = M_C(name, _node_list_back)(v->list); \
|
||||
n != NULL ; \
|
||||
n = (n == v->back->node) ? NULL : \
|
||||
M_C(name, _node_list_previous_obj)(v->list, n) ){ \
|
||||
@@ -485,7 +488,7 @@
|
||||
{ \
|
||||
DEQUEI_CONTRACT(v); \
|
||||
size_t s = 0; \
|
||||
for(M_C(name, _node_t) *n = M_C(name, _node_list_front)(v->list); \
|
||||
for(node_t *n = M_C(name, _node_list_front)(v->list); \
|
||||
n != NULL ; \
|
||||
n = (n == v->front->node) ? NULL : \
|
||||
M_C(name, _node_list_next_obj)(v->list, n) ){ \
|
||||
@@ -566,7 +569,7 @@
|
||||
M_C(name, _next)(it_t it) \
|
||||
{ \
|
||||
assert (it != NULL); \
|
||||
M_C(name, _node_t) *n = it->node; \
|
||||
node_t *n = it->node; \
|
||||
it->index ++; \
|
||||
if (M_UNLIKELY (it->index >= n->size)) { \
|
||||
n = M_C(name, _node_list_next_obj)(it->deque->list, n); \
|
||||
@@ -585,7 +588,7 @@
|
||||
M_C(name, _previous)(it_t it) \
|
||||
{ \
|
||||
assert (it != NULL); \
|
||||
M_C(name, _node_t) *n = it->node; \
|
||||
node_t *n = it->node; \
|
||||
it->index --; \
|
||||
if (M_UNLIKELY (it->index >= n->size)) { \
|
||||
n = M_C(name, _node_list_previous_obj)(it->deque->list, n); \
|
||||
@@ -644,7 +647,7 @@
|
||||
M_C(name, _node_list_init)(d->list); \
|
||||
d->default_size = DEQUEUI_DEFAULT_SIZE + src->count; \
|
||||
d->count = src->count; \
|
||||
M_C(name, _node_t) *n = M_C(name, _int_new_node)(d); \
|
||||
node_t *n = M_C(name, _int_new_node)(d); \
|
||||
if (n == NULL) return; \
|
||||
d->default_size /= 2; \
|
||||
M_C(name, _node_list_push_back)(d->list, n); \
|
||||
@@ -723,7 +726,7 @@
|
||||
const size_t index0 = d->front->index; \
|
||||
size_t count = 0; \
|
||||
/* This loop is in log(N) since the size increase exponentially.*/ \
|
||||
for(M_C(name, _node_t) *n = d->front->node; \
|
||||
for(node_t *n = d->front->node; \
|
||||
n != NULL ; \
|
||||
n = (n == d->back->node) ? NULL : \
|
||||
M_C(name, _node_list_next_obj)(d->list, n) ){ \
|
||||
@@ -977,10 +980,10 @@
|
||||
,INIT_MOVE(M_C(name, _init_move)) \
|
||||
,MOVE(M_C(name, _move)) \
|
||||
,SWAP(M_C(name, _swap)) \
|
||||
,TYPE(M_C(name,_t)) \
|
||||
,SUBTYPE(M_C(name, _type_t)) \
|
||||
,TYPE(M_C(name,_ct)) \
|
||||
,SUBTYPE(M_C(name, _subtype_ct)) \
|
||||
,TEST_EMPTY(M_C(name,_empty_p)) \
|
||||
,IT_TYPE(M_C(name,_it_t)) \
|
||||
,IT_TYPE(M_C(name,_it_ct)) \
|
||||
,IT_FIRST(M_C(name,_it)) \
|
||||
,IT_LAST(M_C(name,_it_last)) \
|
||||
,IT_END(M_C(name,_it_end)) \
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
/* NOTE: \
|
||||
if isSet is true, all methods of value_oplist are NOP methods */ \
|
||||
\
|
||||
/* Define chained dict type */ \
|
||||
typedef struct M_C(name, _s) { \
|
||||
size_t used, lower_limit, upper_limit; \
|
||||
M_C(name, _array_list_pair_t) table; \
|
||||
@@ -260,19 +261,26 @@
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
\
|
||||
M_IF(isSet)( \
|
||||
typedef key_type M_C(name, _type_t); \
|
||||
, \
|
||||
typedef struct M_C(name, _pair_s) M_C(name, _type_t); \
|
||||
) \
|
||||
typedef key_type M_C(name, _key_type_t); \
|
||||
typedef value_type M_C(name, _value_type_t); \
|
||||
\
|
||||
/* Define iterator type */ \
|
||||
typedef struct M_C(name, _it_s) { \
|
||||
M_C(name, _array_list_pair_it_t) array_it; \
|
||||
M_C(name, _list_pair_it_t) list_it; \
|
||||
} dict_it_t[1]; \
|
||||
\
|
||||
/* Define type returned by the _ref method of an iterator */ \
|
||||
M_IF(isSet)( \
|
||||
typedef key_type M_C(name, _type_t); \
|
||||
, \
|
||||
typedef struct M_C(name, _pair_s) M_C(name, _type_t); \
|
||||
) \
|
||||
\
|
||||
/* Define internal types for oplist */ \
|
||||
typedef dict_t M_C(name, _ct); \
|
||||
typedef M_C(name, _type_t) M_C(name, _subtype_ct); \
|
||||
typedef key_type M_C(name, _key_ct); \
|
||||
typedef value_type M_C(name, _value_ct); \
|
||||
typedef dict_it_t M_C(name, _it_ct); \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init)(dict_t map) \
|
||||
{ \
|
||||
@@ -994,10 +1002,10 @@
|
||||
MOVE(M_C(name, _move)), \
|
||||
SWAP(M_C(name, _swap)), \
|
||||
CLEAN(M_C(name, _clean)), \
|
||||
TYPE(M_C(name, _t)), \
|
||||
SUBTYPE(M_C(name, _type_t)), \
|
||||
TYPE(M_C(name, _ct)), \
|
||||
SUBTYPE(M_C(name, _subtype_ct)), \
|
||||
TEST_EMPTY(M_C(name,_empty_p)), \
|
||||
IT_TYPE(M_C(name, _it_t)), \
|
||||
IT_TYPE(M_C(name, _it_ct)), \
|
||||
IT_FIRST(M_C(name,_it)), \
|
||||
IT_SET(M_C(name, _it_set)), \
|
||||
IT_END(M_C(name,_it_end)), \
|
||||
@@ -1005,8 +1013,8 @@
|
||||
IT_LAST_P(M_C(name,_last_p)), \
|
||||
IT_NEXT(M_C(name,_next)), \
|
||||
IT_CREF(M_C(name,_cref)) \
|
||||
,KEY_TYPE(M_C(name, _key_type_t)) \
|
||||
,VALUE_TYPE(M_C(name, _value_type_t)) \
|
||||
,KEY_TYPE(M_C(name, _key_ct)) \
|
||||
,VALUE_TYPE(M_C(name, _value_ct)) \
|
||||
,SET_KEY(M_C(name, _set_at)) \
|
||||
,GET_KEY(M_C(name, _get)) \
|
||||
,GET_SET_KEY(M_C(name, _get_at)) \
|
||||
@@ -1049,19 +1057,19 @@
|
||||
MOVE(M_C(name, _move)), \
|
||||
SWAP(M_C(name, _swap)), \
|
||||
CLEAN(M_C(name, _clean)), \
|
||||
TYPE(M_C(name, _t)), \
|
||||
SUBTYPE(M_C(name, _type_t)), \
|
||||
TYPE(M_C(name, _ct)), \
|
||||
SUBTYPE(M_C(name, _subtype_ct)), \
|
||||
TEST_EMPTY(M_C(name,_empty_p)), \
|
||||
PUSH(M_C(name,_push)), \
|
||||
KEY_TYPE(M_C(name, _key_type_t)), \
|
||||
VALUE_TYPE(M_C(name, _key_type_t)), \
|
||||
KEY_TYPE(M_C(name, _key_ct)), \
|
||||
VALUE_TYPE(M_C(name, _key_ct)), \
|
||||
GET_KEY(M_C(name, _get)), \
|
||||
GET_SET_KEY(M_C(name, _get_at)), \
|
||||
ERASE_KEY(M_C(name, _erase)), \
|
||||
KEY_OPLIST(oplist), \
|
||||
VALUE_OPLIST(oplist), \
|
||||
GET_SIZE(M_C(name, _size)), \
|
||||
IT_TYPE(M_C(name, _it_t)), \
|
||||
IT_TYPE(M_C(name, _it_ct)), \
|
||||
IT_FIRST(M_C(name,_it)), \
|
||||
IT_SET(M_C(name, _it_set)), \
|
||||
IT_END(M_C(name,_it_end)), \
|
||||
@@ -1111,9 +1119,9 @@
|
||||
/* Open Addressing implementation */
|
||||
/****************************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
enum dicti_oa_element_e {
|
||||
DICTI_OA_EMPTY = 0, DICTI_OA_DELETED = 1
|
||||
} dicti_oa_element_t;
|
||||
};
|
||||
|
||||
/* Performing Quadratic probing
|
||||
Replace it by '1' to perform linear probing */
|
||||
@@ -1182,12 +1190,12 @@ typedef enum {
|
||||
M_IF(isSet)( , value_type value;) \
|
||||
} M_C(name, _pair_t); \
|
||||
\
|
||||
/* Define type returned by the _ref method of an iterator */ \
|
||||
M_IF(isSet)( \
|
||||
typedef key_type M_C(name, _type_t); \
|
||||
typedef key_type M_C(name, _type_t); \
|
||||
, \
|
||||
typedef struct M_C(name, _pair_s) M_C(name, _type_t); ) \
|
||||
typedef key_type M_C(name, _key_type_t); \
|
||||
typedef value_type M_C(name, _value_type_t); \
|
||||
typedef struct M_C(name, _pair_s) M_C(name, _type_t); \
|
||||
) \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, key_type, key_oplist) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 2, value_type, value_oplist) \
|
||||
@@ -1210,6 +1218,13 @@ typedef enum {
|
||||
size_t index; \
|
||||
} dict_it_t[1]; \
|
||||
\
|
||||
/* Define internal types for oplist */ \
|
||||
typedef dict_t M_C(name, _ct); \
|
||||
typedef M_C(name, _type_t) M_C(name, _subtype_ct); \
|
||||
typedef key_type M_C(name, _key_ct); \
|
||||
typedef value_type M_C(name, _value_ct); \
|
||||
typedef dict_it_t M_C(name, _it_ct); \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name,_int_limit)(dict_t dict, size_t size) \
|
||||
{ \
|
||||
|
||||
+34
-16
@@ -90,7 +90,7 @@
|
||||
|
||||
/* Specialization of the OPLIST in function if there is at least one member or not */
|
||||
#define FUNCOBJI_INS_NO_ATTR_OPLIST(name) \
|
||||
(NAME(name), TYPE(M_C(name, _t)), \
|
||||
(NAME(name), TYPE(M_C(name, _ct)), \
|
||||
CLEAR(M_C(name, _clear)), \
|
||||
INIT(M_C(name,_init)) \
|
||||
)
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
/* Define at least the oplist */
|
||||
#define FUNCOBJI_INS_ATTR_OPLIST_P3(name, ...) \
|
||||
(NAME(name), TYPE(M_C(name, _t)), \
|
||||
(NAME(name), TYPE(M_C(name, _ct)), \
|
||||
INIT_WITH(M_C(name, _init_with)), \
|
||||
CLEAR(M_C(name, _clear)), \
|
||||
M_IF_METHOD_ALL(INIT, __VA_ARGS__)(INIT(M_C(name,_init)),), \
|
||||
@@ -114,19 +114,25 @@
|
||||
|
||||
/* Specialization of the definition a function object interface of name 'name'
|
||||
* with a function like retcode () that doesn't have any input parameters.
|
||||
* Define the following types to be used by instance:
|
||||
* - M_C(name, _retcode_ct): internal type of the return code
|
||||
* - M_C(name, _callback_ct): internal type of the callback.
|
||||
* - M_C(name, _ct): synonym of main type used by oplist.
|
||||
*/
|
||||
#define FUNCOBJI_ITF_NO_PARAM_DEF(name, retcode) \
|
||||
typedef retcode M_C(name, _retcode_t); \
|
||||
typedef retcode M_C(name, _retcode_ct); \
|
||||
\
|
||||
struct M_C(name, _s); \
|
||||
\
|
||||
/* No parameters to the callback */ \
|
||||
typedef retcode(*M_C(name, _callback_t))(struct M_C(name, _s) *); \
|
||||
typedef retcode(*M_C(name, _callback_ct))(struct M_C(name, _s) *); \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(name, _callback_t) callback; \
|
||||
M_C(name, _callback_ct) callback; \
|
||||
} M_C(name, _t)[1]; \
|
||||
\
|
||||
typedef M_C(name, _t) M_C(name, _ct); \
|
||||
\
|
||||
static inline retcode \
|
||||
M_C(name, _call)(M_C(name, _t) funcobj) \
|
||||
{ \
|
||||
@@ -138,25 +144,33 @@
|
||||
/* Specialization of the definition a function object interface of name 'name'
|
||||
* with a function like retcode, type of param1, type of param 2, ...
|
||||
* with mandatory input parameters.
|
||||
* Define the following types to be used by instance:
|
||||
* - M_C(name, _retcode_ct): internal type of the return code
|
||||
* - M_C(name, _callback_ct): internal type of the callback.
|
||||
* - M_C4(name, _param_, num, _ct) for each parameter defined
|
||||
* - M_C(name, _ct): synonym of main type used by oplist.
|
||||
*/
|
||||
#define FUNCOBJI_ITF_PARAM_DEF(name, retcode, ...) \
|
||||
typedef retcode M_C(name, _retcode_t); \
|
||||
typedef retcode M_C(name, _retcode_ct); \
|
||||
\
|
||||
/* Define types for all paremeters */ \
|
||||
/* Define types for all parameters */ \
|
||||
M_MAP3(FUNCOBJI_BASE_TYPE, name, __VA_ARGS__) \
|
||||
\
|
||||
struct M_C(name, _s); \
|
||||
\
|
||||
typedef retcode(*M_C(name, _callback_t))(struct M_C(name, _s) *, __VA_ARGS__); \
|
||||
typedef retcode(*M_C(name, _callback_ct))(struct M_C(name, _s) *, __VA_ARGS__); \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(name, _callback_t) callback; \
|
||||
M_C(name, _callback_ct) callback; \
|
||||
} M_C(name, _t)[1]; \
|
||||
\
|
||||
typedef M_C(name, _t) M_C(name, _ct); \
|
||||
\
|
||||
static inline retcode \
|
||||
M_C(name, _call)(M_C(name, _t) funcobj \
|
||||
M_MAP3(FUNCOBJI_BASE_ARGLIST, name, __VA_ARGS__) ) \
|
||||
{ \
|
||||
/* If the retcode is 'void', don't return the value of the callback */ \
|
||||
M_IF(M_KEYWORD_P(void, retcode)) ( /* nothing */,return) \
|
||||
funcobj->callback(funcobj M_MAP3(FUNCOBJI_BASE_ARGCALL, name, __VA_ARGS__) ); \
|
||||
}
|
||||
@@ -167,10 +181,12 @@
|
||||
*/
|
||||
#define FUNCOBJI_INS_NO_ATTR_DEF(name, base_name, param_list, callback_core) \
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(base_name, _callback_t) callback; \
|
||||
M_C(base_name, _callback_ct) callback; \
|
||||
} M_C(name, _t)[1]; \
|
||||
\
|
||||
static inline M_C(base_name, _retcode_t) \
|
||||
typedef M_C(name, _t) M_C(name, _ct); \
|
||||
\
|
||||
static inline M_C(base_name, _retcode_ct) \
|
||||
M_C(name, _callback)(M_C(base_name, _t) _self \
|
||||
M_IF_EMPTY(M_OPFLAT param_list)( \
|
||||
/* No param */, \
|
||||
@@ -245,14 +261,16 @@
|
||||
#define FUNCOBJI_INS_ATTR_DEF_P3(name, base_name, param_list, callback_core, ...) \
|
||||
typedef struct M_C(name, _s) { \
|
||||
/* Callback is the mandatory first argument */ \
|
||||
M_C(base_name, _callback_t) callback; \
|
||||
M_C(base_name, _callback_ct) callback; \
|
||||
/* All the member attribute of the Function Object */ \
|
||||
M_MAP(FUNCOBJI_INS_ATTR_STRUCT, __VA_ARGS__) \
|
||||
} M_C(name, _t)[1]; \
|
||||
\
|
||||
FUNCOBJI_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
|
||||
typedef M_C(name, _t) M_C(name, _ct); \
|
||||
\
|
||||
static inline M_C(base_name, _retcode_t) \
|
||||
FUNCOBJI_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
|
||||
\
|
||||
static inline M_C(base_name, _retcode_ct) \
|
||||
M_C(name, _callback)(M_C(base_name, _t) _self \
|
||||
M_IF_EMPTY(M_OPFLAT param_list)( \
|
||||
/* No param */, \
|
||||
@@ -298,7 +316,7 @@
|
||||
|
||||
/* Define a numbered type of a parameter of the callback*/
|
||||
#define FUNCOBJI_BASE_TYPE(name, num, type) \
|
||||
typedef type M_C4(name, _param_, num, _t);
|
||||
typedef type M_C4(name, _param_, num, _ct);
|
||||
|
||||
/* Define a list of the type of arguments for a function definition */
|
||||
#define FUNCOBJI_BASE_ARGLIST(name, num, type) \
|
||||
@@ -328,7 +346,7 @@
|
||||
|
||||
/* Define the list of arguments of the instance of the callback */
|
||||
#define FUNCOBJI_INS_ARGLIST(name, num, param) \
|
||||
M_DEFERRED_COMMA M_C4(name, _param_, num, _t) param
|
||||
M_DEFERRED_COMMA M_C4(name, _param_, num, _ct) param
|
||||
|
||||
|
||||
/* Macros for testing for a method presence in all the attributes */
|
||||
|
||||
+15
-15
@@ -48,14 +48,14 @@ M_BEGIN_PROTECTED_CODE
|
||||
// TO DO: We may want a specialization with constant N value.
|
||||
|
||||
// Define the limb size used by genint
|
||||
typedef unsigned long long genint_limb_t;
|
||||
typedef unsigned long long genint_limb_ct;
|
||||
|
||||
/* Define a generator of unique integer (Lock Free) */
|
||||
typedef struct genint_s {
|
||||
unsigned int n; // size of the container
|
||||
unsigned int max; // number of allocated limb - 1
|
||||
genint_limb_t mask0; // mask of the last limb (constant)
|
||||
genint_limb_t mask_master; // mask of the master limb that controls others (constant)
|
||||
genint_limb_ct mask0; // mask of the last limb (constant)
|
||||
genint_limb_ct mask_master; // mask of the master limb that controls others (constant)
|
||||
atomic_ullong master; // master bitfield (which informs if a limb is full or not)
|
||||
atomic_ullong *data; // the bitfield which informs if an integer is used or not
|
||||
} genint_t[1];
|
||||
@@ -64,7 +64,7 @@ typedef struct genint_s {
|
||||
#define GENINT_MAX_ALLOC (GENINT_LIMBSIZE * (GENINT_LIMBSIZE - GENINT_ABA_CPT))
|
||||
|
||||
// Define the size of a limb in bits.
|
||||
#define GENINT_LIMBSIZE ((unsigned)(sizeof(genint_limb_t) * CHAR_BIT))
|
||||
#define GENINT_LIMBSIZE ((unsigned)(sizeof(genint_limb_ct) * CHAR_BIT))
|
||||
|
||||
// Define the contract of a genint
|
||||
#define GENINT_CONTRACT(s) do { \
|
||||
@@ -75,7 +75,7 @@ typedef struct genint_s {
|
||||
} while (0)
|
||||
|
||||
// Define the limb one
|
||||
#define GENINT_ONE ((genint_limb_t)1)
|
||||
#define GENINT_ONE ((genint_limb_ct)1)
|
||||
|
||||
#define GENINT_FULL_MASK ULLONG_MAX
|
||||
|
||||
@@ -121,9 +121,9 @@ genint_init(genint_t s, unsigned int n)
|
||||
s->max = (unsigned int) (alloc-1);
|
||||
s->mask0 = (index == 0) ? GENINT_FULL_MASK : ~((GENINT_ONE<<(GENINT_LIMBSIZE-index))-1);
|
||||
s->mask_master = (((GENINT_ONE << alloc) - 1) << (GENINT_LIMBSIZE-alloc)) >> GENINT_ABA_CPT;
|
||||
atomic_init (&s->master, (genint_limb_t)0);
|
||||
atomic_init (&s->master, (genint_limb_ct)0);
|
||||
for(unsigned int i = 0; i < alloc; i++)
|
||||
atomic_init(&s->data[i], (genint_limb_t)0);
|
||||
atomic_init(&s->data[i], (genint_limb_ct)0);
|
||||
GENINT_CONTRACT(s);
|
||||
}
|
||||
|
||||
@@ -151,18 +151,18 @@ genint_pop(genint_t s)
|
||||
{
|
||||
GENINT_CONTRACT(s);
|
||||
// First read master to see which limb is not full.
|
||||
genint_limb_t master = atomic_load(&s->master);
|
||||
genint_limb_ct master = atomic_load(&s->master);
|
||||
// While master is not full
|
||||
while ((master >> GENINT_ABA_CPT) != s->mask_master) {
|
||||
// Let's get the index i of the first not full limb according to master.
|
||||
unsigned int i = m_core_clz64(~master);
|
||||
assert (i < GENINT_LIMBSIZE);
|
||||
// Let's compute the mask of this limb representing the limb as being full
|
||||
genint_limb_t mask = s->mask0;
|
||||
genint_limb_ct mask = s->mask0;
|
||||
mask = (i == s->max) ? mask : GENINT_FULL_MASK;
|
||||
unsigned int bit;
|
||||
// Let's load this limb,
|
||||
genint_limb_t next, org = atomic_load(&s->data[i]);
|
||||
genint_limb_ct next, org = atomic_load(&s->data[i]);
|
||||
do {
|
||||
// If it is now full, we have been preempted by another.
|
||||
if (M_UNLIKELY (org == mask))
|
||||
@@ -181,7 +181,7 @@ genint_pop(genint_t s)
|
||||
// If the limb is now full, try to update master
|
||||
if (M_UNLIKELY(next == mask)) {
|
||||
while (true) {
|
||||
genint_limb_t newMaster;
|
||||
genint_limb_ct newMaster;
|
||||
if (next == mask) {
|
||||
newMaster = GENINT_MASTER_SET(master, i);
|
||||
} else {
|
||||
@@ -213,9 +213,9 @@ genint_push(genint_t s, unsigned int n)
|
||||
assert (n < s->n);
|
||||
const unsigned int i = n / GENINT_LIMBSIZE;
|
||||
const unsigned int bit = GENINT_LIMBSIZE - 1 - (n % GENINT_LIMBSIZE);
|
||||
genint_limb_t master = atomic_load(&s->master);
|
||||
genint_limb_ct master = atomic_load(&s->master);
|
||||
// Load the limb
|
||||
genint_limb_t next, org = atomic_load(&s->data[i]);
|
||||
genint_limb_ct next, org = atomic_load(&s->data[i]);
|
||||
do {
|
||||
assert ((org & (GENINT_ONE << bit)) != 0);
|
||||
// Reset it
|
||||
@@ -223,13 +223,13 @@ genint_push(genint_t s, unsigned int n)
|
||||
// Try to unreserve it.
|
||||
} while (!atomic_compare_exchange_weak (&s->data[i], &org, next));
|
||||
// if the limb was marked as full by master
|
||||
genint_limb_t mask = s->mask0;
|
||||
genint_limb_ct mask = s->mask0;
|
||||
mask = (i == s->max) ? mask : GENINT_FULL_MASK;
|
||||
if (M_UNLIKELY (next != mask)) {
|
||||
// Let's compute the mask of this limb representing the limb as being full
|
||||
// Let's try to update master to say that this limb is not full
|
||||
while (true) {
|
||||
genint_limb_t newMaster;
|
||||
genint_limb_ct newMaster;
|
||||
if (next == mask) {
|
||||
newMaster = GENINT_MASTER_SET(master, i);
|
||||
} else {
|
||||
|
||||
+9
-6
@@ -67,7 +67,7 @@
|
||||
typedef struct ilist_head_s {
|
||||
struct ilist_head_s *next;
|
||||
struct ilist_head_s *prev;
|
||||
} ilist_head_t;
|
||||
} ilist_head_ct;
|
||||
|
||||
/* Indirection call to allow expanding all arguments */
|
||||
#define ILISTI_OPLIST_P1(arg) ILISTI_OPLIST_P2 arg
|
||||
@@ -86,11 +86,11 @@ typedef struct ilist_head_s {
|
||||
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,_ct)), \
|
||||
CLEAN(M_C(name,_clean)), \
|
||||
SUBTYPE(M_C(name,_type_t)), \
|
||||
SUBTYPE(M_C(name,_subtype_ct)), \
|
||||
TEST_EMPTY(M_C(name,_empty_p)), \
|
||||
IT_TYPE(M_C(name,_it_t)), \
|
||||
IT_TYPE(M_C(name,_it_ct)), \
|
||||
IT_FIRST(M_C(name,_it)), \
|
||||
IT_SET(M_C(name,_it_set)), \
|
||||
IT_LAST(M_C(name,_it_last)), \
|
||||
@@ -154,8 +154,6 @@ typedef struct ilist_head_s {
|
||||
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 struct M_C(name, _it_s) { \
|
||||
struct ilist_head_s *head; \
|
||||
struct ilist_head_s *previous; \
|
||||
@@ -163,6 +161,11 @@ typedef struct ilist_head_s {
|
||||
struct ilist_head_s *next; \
|
||||
} it_t[1]; \
|
||||
\
|
||||
/* Define types used by oplist */ \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
typedef list_t M_C(name, _ct); \
|
||||
typedef it_t M_C(name, _it_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
static inline void M_C(name, _init)(list_t list) \
|
||||
|
||||
+28
-23
@@ -51,8 +51,8 @@ M_BEGIN_PROTECTED_CODE
|
||||
#define ISHARED_PTR_DEF(name, ...) \
|
||||
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_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t) ), \
|
||||
(name, __VA_ARGS__ , M_C(name, _t) ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -76,9 +76,9 @@ M_BEGIN_PROTECTED_CODE
|
||||
SET(M_C(name, _set) M_IPTR), \
|
||||
CLEAR(M_C(name, _clear)), \
|
||||
CLEAN(M_C(name, _clean) M_IPTR), \
|
||||
TYPE(M_C(name, _t)), \
|
||||
TYPE(M_C(name, _ct)), \
|
||||
OPLIST(oplist), \
|
||||
SUBTYPE(M_C(name, _type_t)) \
|
||||
SUBTYPE(M_C(name, _subtype_ct)) \
|
||||
,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),) \
|
||||
@@ -88,32 +88,38 @@ M_BEGIN_PROTECTED_CODE
|
||||
#define ISHAREDI_PTR_DEF_P1(arg) ISHAREDI_PTR_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define ISHAREDI_PTR_DEF_P2(name, type, oplist) \
|
||||
M_IF_OPLIST(oplist)(ISHAREDI_PTR_DEF_P3, ISHAREDI_PTR_DEF_FAILURE)(name, type, oplist)
|
||||
#define ISHAREDI_PTR_DEF_P2(name, type, oplist, shared_t) \
|
||||
M_IF_OPLIST(oplist)(ISHAREDI_PTR_DEF_P3, ISHAREDI_PTR_DEF_FAILURE)(name, type, oplist, shared_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define ISHAREDI_PTR_DEF_FAILURE(name, type, oplist) \
|
||||
#define ISHAREDI_PTR_DEF_FAILURE(name, type, oplist, shared_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(ISHARED_PTR_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
#define ISHAREDI_PTR_DEF_P3(name, type, oplist) \
|
||||
#define ISHAREDI_PTR_DEF_P3(name, type, oplist, shared_t) \
|
||||
\
|
||||
typedef type *M_C(name,_t); \
|
||||
typedef type M_C(name, _type_t); \
|
||||
/* The shared pointer is only a pointer to the type */ \
|
||||
typedef type *shared_t; \
|
||||
\
|
||||
/* Define internal types for oplits */ \
|
||||
typedef shared_t M_C(name, _ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
static inline M_C(name,_t) \
|
||||
static inline shared_t \
|
||||
M_C(name, _init)(type *ptr) \
|
||||
{ \
|
||||
if (M_LIKELY (ptr != NULL)) \
|
||||
/* Initialize the type referenced by the pointer */ \
|
||||
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) \
|
||||
static inline shared_t \
|
||||
M_C(name, _init_set)(shared_t shared) \
|
||||
{ \
|
||||
if (M_LIKELY (shared != NULL)) { \
|
||||
if (M_LIKELY (shared != NULL)) { \
|
||||
int n = atomic_fetch_add(&(shared->M_C(name, _cpt)), 1); \
|
||||
(void) n; \
|
||||
} \
|
||||
@@ -121,7 +127,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
} \
|
||||
\
|
||||
static inline void M_ATTR_DEPRECATED \
|
||||
M_C(name, _init_set2)(M_C(name,_t) *ptr, M_C(name,_t) shared) \
|
||||
M_C(name, _init_set2)(shared_t *ptr, shared_t shared) \
|
||||
{ \
|
||||
assert (ptr != NULL); \
|
||||
*ptr = M_C(name, _init_set)(shared); \
|
||||
@@ -130,7 +136,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
M_IF_DISABLED_METHOD(NEW, oplist) \
|
||||
( /* Nothing to do */, M_IF_METHOD(INIT, oplist) \
|
||||
( \
|
||||
static inline M_C(name,_t) \
|
||||
static inline shared_t \
|
||||
M_C(name, _init_new)(void) \
|
||||
{ \
|
||||
type *ptr = M_CALL_NEW(oplist, type); \
|
||||
@@ -146,9 +152,9 @@ M_BEGIN_PROTECTED_CODE
|
||||
/* End of NEW */) \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(M_C(name,_t) shared) \
|
||||
M_C(name, _clear)(shared_t shared) \
|
||||
{ \
|
||||
if (shared != NULL) { \
|
||||
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);) \
|
||||
@@ -157,7 +163,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear_ptr)(M_C(name,_t) *shared) \
|
||||
M_C(name, _clear_ptr)(shared_t *shared) \
|
||||
{ \
|
||||
assert(shared != NULL); \
|
||||
M_C(name, _clear)(*shared); \
|
||||
@@ -165,14 +171,14 @@ M_BEGIN_PROTECTED_CODE
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clean)(M_C(name,_t) *shared) \
|
||||
M_C(name, _clean)(shared_t *shared) \
|
||||
{ \
|
||||
M_C(name, _clear)(*shared); \
|
||||
*shared = NULL; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _set)(M_C(name,_t) *ptr, M_C(name,_t)shared) \
|
||||
M_C(name, _set)(shared_t *ptr, shared_t shared) \
|
||||
{ \
|
||||
assert (ptr != NULL); \
|
||||
if (M_LIKELY (*ptr != shared)) { \
|
||||
@@ -185,4 +191,3 @@ M_BEGIN_PROTECTED_CODE
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
#endif
|
||||
|
||||
@@ -79,10 +79,10 @@
|
||||
MOVE(M_C(name, _move)), \
|
||||
INIT_MOVE(M_C(name, _init_move)), \
|
||||
SWAP(M_C(name, _swap)), \
|
||||
TYPE(M_C(name,_t)), \
|
||||
SUBTYPE(M_C(name, _type_t)), \
|
||||
TYPE(M_C(name,_ct)), \
|
||||
SUBTYPE(M_C(name,_subtype_ct)), \
|
||||
TEST_EMPTY(M_C(name,_empty_p)), \
|
||||
IT_TYPE(M_C(name, _it_t)), \
|
||||
IT_TYPE(M_C(name, _it_ct)), \
|
||||
IT_FIRST(M_C(name,_it)), \
|
||||
IT_END(M_C(name,_it_end)), \
|
||||
IT_SET(M_C(name,_it_set)), \
|
||||
@@ -166,16 +166,19 @@
|
||||
struct M_C(name, _s) *next; \
|
||||
type data; \
|
||||
} *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 struct M_C(name, _it_s) { \
|
||||
struct M_C(name, _s) *previous; \
|
||||
struct M_C(name, _s) *current; \
|
||||
} it_t[1]; \
|
||||
\
|
||||
/* Definition of the synonyms of the type */ \
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
typedef list_t M_C(name, _ct); \
|
||||
typedef it_t M_C(name, _it_ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
LISTI_MEMPOOL_DEF(name, type, oplist, list_t, it_t) \
|
||||
@@ -194,9 +197,8 @@
|
||||
- name: prefix to be used
|
||||
- type: type of the elements of the list
|
||||
- oplist: oplist of the type of the elements of the container
|
||||
- list_t: alias for M_C(name, _t) [ type of the container ]
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
- node_t: alias for M_C(name, _node_t) [ node ]
|
||||
- list_t: alias for type of the container
|
||||
- it_t: alias for iterator of the container
|
||||
*/
|
||||
#define LISTI_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
\
|
||||
@@ -871,16 +873,19 @@
|
||||
struct M_C(name, _s) *front; \
|
||||
struct M_C(name, _s) *back; \
|
||||
} list_t[1]; \
|
||||
typedef struct M_C(name, _head_s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _head_s) *M_C(name, _srcptr); \
|
||||
\
|
||||
typedef type M_C(name, _type_t); \
|
||||
\
|
||||
typedef struct M_C(name, _it_s) { \
|
||||
struct M_C(name, _s) *previous; \
|
||||
struct M_C(name, _s) *current; \
|
||||
} it_t[1]; \
|
||||
\
|
||||
/* Definition of the synonyms of the type */ \
|
||||
typedef struct M_C(name, _head_s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _head_s) *M_C(name, _srcptr); \
|
||||
typedef list_t M_C(name, _ct); \
|
||||
typedef it_t M_C(name, _it_ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
LISTI_MEMPOOL_DEF(name, type, oplist, list_t, it_t) \
|
||||
@@ -899,9 +904,8 @@
|
||||
- name: prefix to be used
|
||||
- type: type of the elements of the array
|
||||
- oplist: oplist of the type of the elements of the container
|
||||
- list_t: alias for M_C(name, _t) [ type of the container ]
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
- node_t: alias for M_C(name, _node_t) [ node ]
|
||||
- list_t: alias for type of the container
|
||||
- it_t: alias for iterator of the container
|
||||
*/
|
||||
#define LISTI_DUAL_PUSH_DEF_P4(name, type, oplist, list_t, it_t) \
|
||||
\
|
||||
|
||||
+22
-21
@@ -41,12 +41,13 @@
|
||||
*/
|
||||
#define MEMPOOL_DEF(name, type) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
MEMPOOL_DEF_P2(name, type) \
|
||||
MEMPOOL_DEF_P2(name, type, M_C(name, _t) ) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
/* User shall be able to cutomize the size of the segment and/or
|
||||
the minimun number of elements.
|
||||
The default is the number of elements that fits in 16KB.
|
||||
*/
|
||||
#ifndef MEMPOOL_MAX_PER_SEGMENT
|
||||
#define MEMPOOL_MAX_PER_SEGMENT(type) \
|
||||
@@ -56,31 +57,31 @@
|
||||
|
||||
/********************************** INTERNAL ************************************/
|
||||
|
||||
#define MEMPOOL_DEF_P2(name, type) \
|
||||
#define MEMPOOL_DEF_P2(name, type, name_t) \
|
||||
\
|
||||
typedef union M_C(name,_union_s) { \
|
||||
type t; \
|
||||
union M_C(name,_union_s) *next; \
|
||||
} M_C(name,_union_t); \
|
||||
} M_C(name,_union_ct); \
|
||||
\
|
||||
typedef struct M_C(name,_segment_s) { \
|
||||
unsigned int count; \
|
||||
struct M_C(name,_segment_s) *next; \
|
||||
M_C(name,_union_t) tab[MEMPOOL_MAX_PER_SEGMENT(type)]; \
|
||||
} M_C(name,_segment_t); \
|
||||
M_C(name,_union_ct) tab[MEMPOOL_MAX_PER_SEGMENT(type)]; \
|
||||
} M_C(name,_segment_ct); \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(name,_union_t) *free_list; \
|
||||
M_C(name,_segment_t) *current_segment; \
|
||||
} M_C(name,_t)[1]; \
|
||||
M_C(name,_union_ct) *free_list; \
|
||||
M_C(name,_segment_ct) *current_segment; \
|
||||
} name_t[1]; \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name,_init)(M_C(name,_t) mem) \
|
||||
M_C(name,_init)(name_t mem) \
|
||||
{ \
|
||||
mem->free_list = NULL; \
|
||||
mem->current_segment = M_MEMORY_ALLOC(M_C(name,_segment_t)); \
|
||||
mem->current_segment = M_MEMORY_ALLOC(M_C(name,_segment_ct)); \
|
||||
if (mem->current_segment == NULL) { \
|
||||
M_MEMORY_FULL(sizeof (M_C(name,_segment_t))); \
|
||||
M_MEMORY_FULL(sizeof (M_C(name,_segment_ct))); \
|
||||
return; \
|
||||
} \
|
||||
mem->current_segment->next = NULL; \
|
||||
@@ -89,12 +90,12 @@
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name,_clear)(M_C(name,_t) mem) \
|
||||
M_C(name,_clear)(name_t mem) \
|
||||
{ \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
M_C(name,_segment_t) *segment = mem->current_segment; \
|
||||
M_C(name,_segment_ct) *segment = mem->current_segment; \
|
||||
while (segment != NULL) { \
|
||||
M_C(name,_segment_t) *next = segment->next; \
|
||||
M_C(name,_segment_ct) *next = segment->next; \
|
||||
M_MEMORY_DEL (segment); \
|
||||
segment = next; \
|
||||
} \
|
||||
@@ -104,21 +105,21 @@
|
||||
} \
|
||||
\
|
||||
static inline type * \
|
||||
M_C(name,_alloc)(M_C(name,_t) mem) \
|
||||
M_C(name,_alloc)(name_t mem) \
|
||||
{ \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
M_C(name,_union_t) *ret = mem->free_list; \
|
||||
M_C(name,_union_ct) *ret = mem->free_list; \
|
||||
if (ret != NULL) { \
|
||||
mem->free_list = ret->next; \
|
||||
return &ret->t; \
|
||||
} \
|
||||
M_C(name,_segment_t) *segment = mem->current_segment; \
|
||||
M_C(name,_segment_ct) *segment = mem->current_segment; \
|
||||
assert(segment != NULL); \
|
||||
unsigned int count = segment->count; \
|
||||
if (M_UNLIKELY (count >= MEMPOOL_MAX_PER_SEGMENT(type))) { \
|
||||
M_C(name,_segment_t) *new_segment = M_MEMORY_ALLOC (M_C(name,_segment_t)); \
|
||||
M_C(name,_segment_ct) *new_segment = M_MEMORY_ALLOC (M_C(name,_segment_ct)); \
|
||||
if (M_UNLIKELY (new_segment == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof (M_C(name,_segment_t))); \
|
||||
M_MEMORY_FULL(sizeof (M_C(name,_segment_ct))); \
|
||||
return NULL; \
|
||||
} \
|
||||
new_segment->next = segment; \
|
||||
@@ -134,12 +135,12 @@
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name,_free)(M_C(name,_t) mem, type *ptr) \
|
||||
M_C(name,_free)(name_t mem, type *ptr) \
|
||||
{ \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
/* NOTE: Unsafe cast: suppose that the given pointer \
|
||||
was allocated by the previous alloc function. */ \
|
||||
M_C(name,_union_t) *ret = (M_C(name,_union_t) *)(uintptr_t)ptr; \
|
||||
M_C(name,_union_ct) *ret = (M_C(name,_union_ct) *)(uintptr_t)ptr; \
|
||||
ret->next = mem->free_list; \
|
||||
mem->free_list = ret; \
|
||||
MEMPOOLI_CONTRACT(mem, type); \
|
||||
|
||||
@@ -153,13 +153,13 @@ static inline bool m_thread_sleep(unsigned long long usec)
|
||||
}
|
||||
|
||||
// Internal type, not exported.
|
||||
typedef once_flag m_oncei_t[1];
|
||||
typedef once_flag m_once_ct[1];
|
||||
|
||||
// Initial value for m_oncei_t
|
||||
// Initial value for m_once_ct
|
||||
#define M_ONCEI_INIT_VALUE { ONCE_FLAG_INIT }
|
||||
|
||||
// Call the function exactly once
|
||||
static inline void m_oncei_call(m_oncei_t o, void (*func)(void))
|
||||
static inline void m_oncei_call(m_once_ct o, void (*func)(void))
|
||||
{
|
||||
call_once(o,func);
|
||||
}
|
||||
@@ -316,7 +316,7 @@ static inline bool m_thread_sleep(unsigned long long usec)
|
||||
|
||||
|
||||
// Internal type, not exported.
|
||||
typedef INIT_ONCE m_oncei_t[1];
|
||||
typedef INIT_ONCE m_once_ct[1];
|
||||
#define M_ONCEI_INIT_VALUE { INIT_ONCE_STATIC_INIT }
|
||||
static inline BOOL CALLBACK m_oncei_callback( PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext)
|
||||
{
|
||||
@@ -327,7 +327,7 @@ static inline BOOL CALLBACK m_oncei_callback( PINIT_ONCE InitOnce, PVOID Paramet
|
||||
(*func)();
|
||||
return TRUE;
|
||||
}
|
||||
static inline void m_oncei_call(m_oncei_t o, void (*func)(void))
|
||||
static inline void m_oncei_call(m_once_ct o, void (*func)(void))
|
||||
{
|
||||
InitOnceExecuteOnce(o, m_oncei_callback, (void*)(intptr_t)func, NULL);
|
||||
}
|
||||
@@ -475,9 +475,9 @@ static inline bool m_thread_sleep(unsigned long long usec)
|
||||
}
|
||||
|
||||
// Internal type, not exported.
|
||||
typedef pthread_once_t m_oncei_t[1];
|
||||
typedef pthread_once_t m_once_ct[1];
|
||||
#define M_ONCEI_INIT_VALUE { PTHREAD_ONCE_INIT }
|
||||
static inline void m_oncei_call(m_oncei_t o, void (*func)(void))
|
||||
static inline void m_oncei_call(m_once_ct o, void (*func)(void))
|
||||
{
|
||||
pthread_once(o,func);
|
||||
}
|
||||
@@ -488,7 +488,6 @@ M_END_PROTECTED_CODE
|
||||
|
||||
#endif
|
||||
|
||||
// TODO: m_thread_sleep doesn't yield thread during waiting, making it a poor choice for active waiting.
|
||||
// TODO: Obsolete M_LOCK macro.
|
||||
|
||||
/* M_LOCK macro. Allow simple locking encapsulation.
|
||||
@@ -512,7 +511,7 @@ M_END_PROTECTED_CODE
|
||||
static void M_C(m_mutex_init_, name)(void) { \
|
||||
m_mutex_init(name); \
|
||||
} \
|
||||
m_oncei_t M_C(m_once_, name) = M_ONCEI_INIT_VALUE
|
||||
m_once_ct M_C(m_once_, name) = M_ONCEI_INIT_VALUE
|
||||
# define M_LOCKI_BY_ONCE(name) \
|
||||
(m_oncei_call(M_C(m_once_, name), M_C(m_mutex_init_, name)), \
|
||||
m_mutex_lock(name), (void) 0 )
|
||||
|
||||
+10
-3
@@ -73,8 +73,8 @@
|
||||
,INIT_MOVE(M_C(name, _init_move)) \
|
||||
,MOVE(M_C(name, _move)) \
|
||||
,SWAP(M_C(name, _swap)) \
|
||||
,TYPE(M_C(name,_t)) \
|
||||
,SUBTYPE(M_C(name, _type_t)) \
|
||||
,TYPE(M_C(name,_ct)) \
|
||||
,SUBTYPE(M_C(name, _subtype_ct)) \
|
||||
,CLEAN(M_C(name,_clean)) \
|
||||
,PUSH(M_C(name,_push)) \
|
||||
,POP(M_C(name,_pop)) \
|
||||
@@ -104,9 +104,10 @@
|
||||
- it_t: iterator of the container
|
||||
*/
|
||||
#define PRIOQUEUEI_DEF_P3(name, type, oplist, prioqueue_t, it_t) \
|
||||
\
|
||||
/* Definition of the internal array used to construct the priority queue */ \
|
||||
ARRAY_DEF(M_C(name, _array), type, oplist) \
|
||||
\
|
||||
typedef type M_C(name, _type_t); \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(name, _array_t) array; \
|
||||
@@ -114,8 +115,14 @@
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
\
|
||||
/* The iterator is the same one as the one of the internal array */ \
|
||||
typedef M_C(name, _array_it_t) it_t; \
|
||||
\
|
||||
/* Definition of the internal types used by the oplist */ \
|
||||
typedef prioqueue_t M_C(name, _ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
typedef it_t M_C(name, _subtype_t); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
static inline void \
|
||||
|
||||
+21
-18
@@ -29,21 +29,21 @@
|
||||
|
||||
/* Define a Red/Black binary tree of a given type.
|
||||
USAGE: RBTREE_DEF(name, type [, oplist_of_the_type]) */
|
||||
#define RBTREE_DEF(name, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
RBTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), \
|
||||
M_C(name, _t), M_C(name, _node_t), M_C(name, _it_t)), \
|
||||
(name, __VA_ARGS__ , \
|
||||
M_C(name, _t), M_C(name, _node_t), M_C(name, _it_t)))) \
|
||||
#define RBTREE_DEF(name, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
RBTREEI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), \
|
||||
M_C(name, _t), M_C(name, _node_ct), M_C(name, _it_t)), \
|
||||
(name, __VA_ARGS__ , \
|
||||
M_C(name, _t), M_C(name, _node_ct), M_C(name, _it_t)))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
/* Define the oplist of a rbtree of type.
|
||||
USAGE: RBTREE_OPLIST(name [, oplist_of_the_type]) */
|
||||
#define RBTREE_OPLIST(...) \
|
||||
RBTREEI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
#define RBTREE_OPLIST(...) \
|
||||
RBTREEI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_DEFAULT_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
|
||||
@@ -73,11 +73,11 @@
|
||||
INIT_MOVE(M_C(name, _init_move)), \
|
||||
MOVE(M_C(name, _move)), \
|
||||
SWAP(M_C(name, _swap)), \
|
||||
TYPE(M_C(name,_t)), \
|
||||
SUBTYPE(M_C(name, _type_t)), \
|
||||
TYPE(M_C(name,_ct)), \
|
||||
SUBTYPE(M_C(name, _subtype_ct)), \
|
||||
TEST_EMPTY(M_C(name,_empty_p)), \
|
||||
GET_SIZE(M_C(name, _size)), \
|
||||
IT_TYPE(M_C(name, _it_t)), \
|
||||
IT_TYPE(M_C(name, _it_ct)), \
|
||||
IT_FIRST(M_C(name,_it)), \
|
||||
IT_SET(M_C(name,_it_set)), \
|
||||
IT_LAST(M_C(name,_it_last)), \
|
||||
@@ -161,9 +161,9 @@ typedef enum {
|
||||
- name: prefix to be used
|
||||
- type: type of the elements of the rbtree
|
||||
- oplist: oplist of the type of the elements of the container
|
||||
- tree_t: alias for M_C(name, _t) [ type of the container ]
|
||||
- it_t: alias for M_C(name, _it_t) [ iterator of the container ]
|
||||
- node_t: alias for M_C(name, _node_t) [ node ]
|
||||
- tree_t: alias for the type of the container
|
||||
- it_t: alias for the iterator of the container
|
||||
- node_t: alias for the node of an element of the container
|
||||
*/
|
||||
#define RBTREEI_DEF_P3(name, type, oplist, tree_t, node_t, it_t) \
|
||||
\
|
||||
@@ -192,7 +192,10 @@ typedef enum {
|
||||
unsigned int cpt; \
|
||||
} it_t[1]; \
|
||||
\
|
||||
typedef type M_C(name, _type_t); \
|
||||
/* Definition of the alias used by the oplists */ \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
typedef tree_t M_C(name, _ct); \
|
||||
typedef it_t M_C(name, _it_ct); \
|
||||
\
|
||||
/* Link with fast memory allocator if requested */ \
|
||||
M_IF_METHOD(MEMPOOL, oplist)( \
|
||||
@@ -1089,7 +1092,7 @@ typedef enum {
|
||||
assert (f != NULL && f->m_interface != NULL); \
|
||||
m_serial_local_t local; \
|
||||
m_serial_return_code_t ret; \
|
||||
const M_C(name, _type_t) *item; \
|
||||
M_C(name, _subtype_ct) const *item; \
|
||||
bool first_done = false; \
|
||||
it_t it; \
|
||||
ret = f->m_interface->write_array_start(local, f, t1->size); \
|
||||
|
||||
+18
-9
@@ -91,7 +91,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
CLEAN(M_C(name, _clean)), \
|
||||
MOVE(M_C(name, _move)), \
|
||||
SWAP(M_C(name, _swap)) \
|
||||
,TYPE(M_C(name, _t)) \
|
||||
,TYPE(M_C(name, _ct)) \
|
||||
,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),) \
|
||||
@@ -127,8 +127,8 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
#define SHAREDI_PTR_DEF_P1(arg) SHAREDI_PTR_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define SHAREDI_PTR_DEF_P2(name, type, oplist, cpt_oplist_t) \
|
||||
M_IF_OPLIST(oplist)(SHAREDI_PTR_DEF_P3, SHAREDI_PTR_DEF_FAILURE)(name, type, oplist, cpt_oplist_t)
|
||||
#define SHAREDI_PTR_DEF_P2(name, type, oplist, cpt_oplist) \
|
||||
M_IF_OPLIST(oplist)(SHAREDI_PTR_DEF_P3, SHAREDI_PTR_DEF_FAILURE)(name, type, oplist, cpt_oplist)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define SHAREDI_PTR_DEF_FAILURE(name, type, oplist, cpt_oplist) \
|
||||
@@ -139,16 +139,19 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
\
|
||||
typedef struct M_C(name, _s){ \
|
||||
type *data; /* Pointer to the data */ \
|
||||
M_GET_TYPE cpt_oplist cpt; /* Counter of how many points to the data */ \
|
||||
M_GET_TYPE cpt_oplist cpt; /* Counter of how many refs the data */ \
|
||||
bool combineAlloc; /* Does the data and the ptr share the slot? */ \
|
||||
} *M_C(name, _t)[1]; \
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
\
|
||||
/* Internal type for oplist */ \
|
||||
typedef M_C(name, _t) M_C(name, _ct); \
|
||||
\
|
||||
typedef struct M_C(name, combine_s) { \
|
||||
type data; \
|
||||
struct M_C(name, _s) ptr; \
|
||||
} M_C(name, combine_t)[1]; \
|
||||
} M_C(name, combine_ct)[1]; \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
@@ -321,6 +324,8 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
return data; \
|
||||
} \
|
||||
|
||||
|
||||
|
||||
/********************************** SHARED RESOURCE ************************************/
|
||||
|
||||
#define SHAREDI_RESOURCE_CONTRACT(s) do { \
|
||||
@@ -346,11 +351,11 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
atomic_uint cpt; \
|
||||
type x; \
|
||||
M_CACHELINE_ALIGN(align, type, atomic_uint); \
|
||||
} M_C(name, _atype_t); \
|
||||
} M_C(name, _atype_ct); \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
genint_t core; \
|
||||
M_C(name, _atype_t) *buffer; \
|
||||
M_C(name, _atype_ct) *buffer; \
|
||||
} M_C(name, _t)[1]; \
|
||||
\
|
||||
typedef struct M_C(name, _it_s) { \
|
||||
@@ -358,14 +363,18 @@ static inline int sharedi_integer_cref(int *p) { return *p; }
|
||||
struct M_C(name, _s) *ref; \
|
||||
} M_C(name, _it_t)[1]; \
|
||||
\
|
||||
/* Internal Types for oplist */ \
|
||||
typedef M_C(name, _t) M_C(name, _ct); \
|
||||
typedef M_C(name, _it_t) M_C(name, _it__ct); \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init)(M_C(name, _t) s, size_t n) \
|
||||
{ \
|
||||
assert(s != NULL); \
|
||||
assert (n > 0 && n < UINT_MAX); \
|
||||
s->buffer = M_CALL_REALLOC(oplist, M_C(name, _atype_t), NULL, n); \
|
||||
s->buffer = M_CALL_REALLOC(oplist, M_C(name, _atype_ct), NULL, n); \
|
||||
if (M_UNLIKELY (s->buffer == NULL)) { \
|
||||
M_MEMORY_FULL(sizeof(M_C(name, _atype_t)) * n); \
|
||||
M_MEMORY_FULL(sizeof(M_C(name, _atype_ct)) * n); \
|
||||
return; \
|
||||
} \
|
||||
for(size_t i = 0; i < n; i++) { \
|
||||
|
||||
+119
-86
@@ -36,8 +36,8 @@ M_BEGIN_PROTECTED_CODE
|
||||
#define SNAPSHOT_SPSC_DEF(name, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
SNAPSHOTI_SPSC_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_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t) ), \
|
||||
(name, __VA_ARGS__ , M_C(name, _t) ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@ M_BEGIN_PROTECTED_CODE
|
||||
#define SNAPSHOT_SPMC_DEF(name, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
SNAPSHOTI_SPMC_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_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t) ), \
|
||||
(name, __VA_ARGS__ , M_C(name, _t) ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ M_BEGIN_PROTECTED_CODE
|
||||
#define SNAPSHOT_MPMC_DEF(name, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
SNAPSHOTI_MPMC_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_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name, _t) ), \
|
||||
(name, __VA_ARGS__ , M_C(name, _t) ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
@@ -88,8 +88,8 @@ M_BEGIN_PROTECTED_CODE
|
||||
,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)) \
|
||||
,TYPE(M_C(name, _ct)) \
|
||||
,SUBTYPE(M_C(name, _subtype_ct)) \
|
||||
,OPLIST(oplist) \
|
||||
,M_IF_METHOD(INIT_MOVE, oplist)(INIT_MOVE(M_C(name, _init_move)),) \
|
||||
,M_IF_METHOD(MOVE, oplist)(MOVE(M_C(name, _move)),) \
|
||||
@@ -137,14 +137,15 @@ M_BEGIN_PROTECTED_CODE
|
||||
#define SNAPSHOTI_SPSC_DEF_P1(arg) SNAPSHOTI_SPSC_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define SNAPSHOTI_SPSC_DEF_P2(name, type, oplist) \
|
||||
M_IF_OPLIST(oplist)(SNAPSHOTI_SPSC_DEF_P3, SNAPSHOTI_SPSC_DEF_FAILURE)(name, type, oplist)
|
||||
#define SNAPSHOTI_SPSC_DEF_P2(name, type, oplist, snapshot_t) \
|
||||
M_IF_OPLIST(oplist)(SNAPSHOTI_SPSC_DEF_P3, SNAPSHOTI_SPSC_DEF_FAILURE)(name, type, oplist, snapshot_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define SNAPSHOTI_SPSC_DEF_FAILURE(name, type, oplist) \
|
||||
#define SNAPSHOTI_SPSC_DEF_FAILURE(name, type, oplist, snapshot_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_SPSC_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
#define SNAPSHOTI_SPSC_DEF_P3(name, type, oplist) \
|
||||
/* Expand the type and the functions of a SPSC snapshot */
|
||||
#define SNAPSHOTI_SPSC_DEF_P3(name, type, oplist, snapshot_t) \
|
||||
\
|
||||
/* Create an aligned type to avoid false sharing between threads */ \
|
||||
typedef struct M_C(name, _aligned_type_s) { \
|
||||
@@ -155,15 +156,18 @@ M_BEGIN_PROTECTED_CODE
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(name, _aligned_type_t) data[SNAPSHOTI_SPSC_MAX_BUFFER]; \
|
||||
atomic_uchar flags; \
|
||||
} M_C(name, _t)[1]; \
|
||||
} snapshot_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); \
|
||||
/* Define internal types for oplist */ \
|
||||
typedef snapshot_t M_C(name, _ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
static inline void M_C(name, _init)(M_C(name, _t) snap) \
|
||||
static inline void \
|
||||
M_C(name, _init)(snapshot_t snap) \
|
||||
{ \
|
||||
assert(snap != NULL); \
|
||||
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
|
||||
@@ -173,7 +177,8 @@ M_BEGIN_PROTECTED_CODE
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _clear)(M_C(name, _t) snap) \
|
||||
static inline void \
|
||||
M_C(name, _clear)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
|
||||
@@ -181,8 +186,9 @@ M_BEGIN_PROTECTED_CODE
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _init_set)(M_C(name, _t) snap, \
|
||||
M_C(name, _t) org) \
|
||||
/* const is missing for org due to use of atomic_load of org */ \
|
||||
static inline void \
|
||||
M_C(name, _init_set)(snapshot_t snap, snapshot_t org) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(org); \
|
||||
assert(snap != NULL && snap != org); \
|
||||
@@ -193,8 +199,9 @@ M_BEGIN_PROTECTED_CODE
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _set)(M_C(name, _t) snap, \
|
||||
M_C(name, _t) org) \
|
||||
/* const is missing for org due to use of atomic_load of org */ \
|
||||
static inline void \
|
||||
M_C(name, _set)(snapshot_t snap, snapshot_t org) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
SNAPSHOTI_SPSC_CONTRACT(org); \
|
||||
@@ -206,8 +213,8 @@ M_BEGIN_PROTECTED_CODE
|
||||
} \
|
||||
\
|
||||
M_IF_METHOD(INIT_MOVE, oplist)( \
|
||||
static inline void M_C(name, _init_move)(M_C(name, _t) snap, \
|
||||
M_C(name, _t) org) \
|
||||
static inline void \
|
||||
M_C(name, _init_move)(snapshot_t snap, snapshot_t org) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(org); \
|
||||
assert(snap != NULL && snap != org); \
|
||||
@@ -218,26 +225,27 @@ M_BEGIN_PROTECTED_CODE
|
||||
atomic_store (&org->flags, SNAPSHOTI_SPSC_FLAG(0,0,0,0) ); \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
} \
|
||||
,) /* IF_METHOD (INIT_MOVE) */ \
|
||||
,) /* IF_METHOD (INIT_MOVE) */ \
|
||||
\
|
||||
M_IF_METHOD(MOVE, oplist)( \
|
||||
static inline void M_C(name, _move)(M_C(name, _t) snap, \
|
||||
M_C(name, _t) org) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
SNAPSHOTI_SPSC_CONTRACT(org); \
|
||||
assert(snap != org); \
|
||||
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
|
||||
M_CALL_MOVE(oplist, snap->data[i].x, org->data[i].x); \
|
||||
} \
|
||||
atomic_store (&snap->flags, atomic_load(&org->flags)); \
|
||||
atomic_store (&org->flags, SNAPSHOTI_SPSC_FLAG(0,0,0,0) ); \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
} \
|
||||
,) /* IF_METHOD (MOVE) */ \
|
||||
M_IF_METHOD(MOVE, oplist)( \
|
||||
static inline void \
|
||||
M_C(name, _move)(snapshot_t snap, \
|
||||
snapshot_t org) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
SNAPSHOTI_SPSC_CONTRACT(org); \
|
||||
assert(snap != org); \
|
||||
for(int i = 0; i < SNAPSHOTI_SPSC_MAX_BUFFER; i++) { \
|
||||
M_CALL_MOVE(oplist, snap->data[i].x, org->data[i].x); \
|
||||
} \
|
||||
atomic_store (&snap->flags, atomic_load(&org->flags)); \
|
||||
atomic_store (&org->flags, SNAPSHOTI_SPSC_FLAG(0,0,0,0) ); \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
} \
|
||||
,) /* IF_METHOD (MOVE) */ \
|
||||
\
|
||||
\
|
||||
static inline type *M_C(name, _write)(M_C(name, _t) snap) \
|
||||
static inline type * \
|
||||
M_C(name, _write)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \
|
||||
@@ -255,7 +263,8 @@ M_BEGIN_PROTECTED_CODE
|
||||
return &snap->data[SNAPSHOTI_SPSC_W(nextFlags)].x; \
|
||||
} \
|
||||
\
|
||||
static inline type const *M_C(name, _read)(M_C(name, _t) snap) \
|
||||
static inline type const * \
|
||||
M_C(name, _read)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
unsigned char nextFlags, origFlags = atomic_load (&snap->flags); \
|
||||
@@ -278,21 +287,27 @@ M_BEGIN_PROTECTED_CODE
|
||||
return M_CONST_CAST(type, &snap->data[SNAPSHOTI_SPSC_R(nextFlags)].x); \
|
||||
} \
|
||||
\
|
||||
static inline bool M_C(name, _updated_p)(M_C(name, _t) snap) \
|
||||
/* Non const due to use of atomic_load */ \
|
||||
static inline bool \
|
||||
M_C(name, _updated_p)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
unsigned char flags = atomic_load (&snap->flags); \
|
||||
return SNAPSHOTI_SPSC_B(flags); \
|
||||
} \
|
||||
\
|
||||
static inline type *M_C(name, _get_write_buffer)(M_C(name, _t) snap) \
|
||||
/* Non const due to use of atomic_load */ \
|
||||
static inline type * \
|
||||
M_C(name, _get_write_buffer)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
unsigned char flags = atomic_load(&snap->flags); \
|
||||
return &snap->data[SNAPSHOTI_SPSC_W(flags)].x; \
|
||||
} \
|
||||
\
|
||||
static inline type const *M_C(name, _get_read_buffer)(M_C(name, _t) snap) \
|
||||
/* Non const due to use of atomic_load */ \
|
||||
static inline type const * \
|
||||
M_C(name, _get_read_buffer)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPSC_CONTRACT(snap); \
|
||||
unsigned char flags = atomic_load(&snap->flags); \
|
||||
@@ -312,7 +327,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
|
||||
#define SNAPSHOTI_SPMC_MAX_READER (GENINT_MAX_ALLOC-SNAPSHOTI_SPMC_EXTRA_BUFFER)
|
||||
|
||||
/* structure to handle SPMC snapshot but return an unique index in the buffer array.
|
||||
/* Internal structure to handle SPMC snapshot but return an unique index in the buffer array.
|
||||
- lastNext: last published written index + next flag (format SNAPSHOTI_SPMC_INT_FLAG)
|
||||
- currentWrite: the index being currently written.
|
||||
- n_reader : number of readers
|
||||
@@ -325,7 +340,7 @@ typedef struct snapshot_mrsw_int_s {
|
||||
size_t n_reader;
|
||||
atomic_uint *cptTab;
|
||||
genint_t freeList;
|
||||
} snapshot_mrsw_int_t[1];
|
||||
} snapshot_mrsw_int_ct[1];
|
||||
|
||||
// can't check currentWrite due to potential data race on it
|
||||
#define SNAPSHOTI_SPMC_INT_CONTRACT(s) do { \
|
||||
@@ -336,9 +351,9 @@ typedef struct snapshot_mrsw_int_s {
|
||||
assert (s->cptTab != NULL); \
|
||||
} while (0)
|
||||
|
||||
/* Initialize snapshot_mrsw_int_t for n readers (constructor) */
|
||||
/* Initialize snapshot_mrsw_int_ct for n readers (constructor) */
|
||||
static inline void
|
||||
snapshot_mrsw_int_init(snapshot_mrsw_int_t s, size_t n)
|
||||
snapshot_mrsw_int_init(snapshot_mrsw_int_ct s, size_t n)
|
||||
{
|
||||
assert (s != NULL);
|
||||
assert (n >= 1 && n <= SNAPSHOTI_SPMC_MAX_READER);
|
||||
@@ -369,9 +384,9 @@ snapshot_mrsw_int_init(snapshot_mrsw_int_t s, size_t n)
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
}
|
||||
|
||||
/* Clear snapshot_mrsw_int_t (destructor) */
|
||||
/* Clear snapshot_mrsw_int_ct (destructor) */
|
||||
static inline void
|
||||
snapshot_mrsw_int_clear(snapshot_mrsw_int_t s)
|
||||
snapshot_mrsw_int_clear(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
M_MEMORY_FREE (s->cptTab);
|
||||
@@ -382,7 +397,7 @@ snapshot_mrsw_int_clear(snapshot_mrsw_int_t s)
|
||||
|
||||
/* Return the current index that is written in the buffer */
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_get_write_idx(snapshot_mrsw_int_t s)
|
||||
snapshot_mrsw_int_get_write_idx(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
return s->currentWrite;
|
||||
@@ -390,7 +405,7 @@ snapshot_mrsw_int_get_write_idx(snapshot_mrsw_int_t s)
|
||||
|
||||
/* Return the number of readers */
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_size(snapshot_mrsw_int_t s)
|
||||
snapshot_mrsw_int_size(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
return (unsigned int) s->n_reader;
|
||||
@@ -399,7 +414,7 @@ snapshot_mrsw_int_size(snapshot_mrsw_int_t s)
|
||||
/* Give the current index that is written to the readers,
|
||||
and return new available index for writter */
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_write_idx(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
snapshot_mrsw_int_write_idx(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
|
||||
@@ -441,7 +456,7 @@ snapshot_mrsw_int_write_idx(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
|
||||
/* Perform a swap of the current write buffer and return a new one */
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_write(snapshot_mrsw_int_t s)
|
||||
snapshot_mrsw_int_write(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
s->currentWrite = snapshot_mrsw_int_write_idx(s, s->currentWrite);
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
@@ -450,7 +465,7 @@ snapshot_mrsw_int_write(snapshot_mrsw_int_t s)
|
||||
|
||||
/* Start writing to the write buffer and return its index */
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_write_start(snapshot_mrsw_int_t s)
|
||||
snapshot_mrsw_int_write_start(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
// Get a new buffer.
|
||||
@@ -465,7 +480,7 @@ snapshot_mrsw_int_write_start(snapshot_mrsw_int_t s)
|
||||
|
||||
/* End writing to the given write buffer */
|
||||
static inline void
|
||||
snapshot_mrsw_int_write_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
snapshot_mrsw_int_write_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
|
||||
@@ -487,7 +502,7 @@ snapshot_mrsw_int_write_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
|
||||
/* Start reading the latest written buffer and return the index to it */
|
||||
static inline unsigned int
|
||||
snapshot_mrsw_int_read_start(snapshot_mrsw_int_t s)
|
||||
snapshot_mrsw_int_read_start(snapshot_mrsw_int_ct s)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
unsigned int idx, previous;
|
||||
@@ -530,7 +545,7 @@ snapshot_mrsw_int_read_start(snapshot_mrsw_int_t s)
|
||||
|
||||
/* End the reading the given buffer */
|
||||
static inline void
|
||||
snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
snapshot_mrsw_int_read_end(snapshot_mrsw_int_ct s, unsigned int idx)
|
||||
{
|
||||
SNAPSHOTI_SPMC_INT_CONTRACT(s);
|
||||
assert (idx < s->n_reader + SNAPSHOTI_SPMC_EXTRA_BUFFER);
|
||||
@@ -546,7 +561,7 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
}
|
||||
|
||||
/* Contract of a SPMC snapshot.
|
||||
Nothing notable */
|
||||
Nothing notable as it can be accessed concurrently */
|
||||
#define SNAPSHOTI_SPMC_CONTRACT(snap) do { \
|
||||
assert (snap != NULL); \
|
||||
assert (snap->data != NULL); \
|
||||
@@ -557,14 +572,15 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
#define SNAPSHOTI_SPMC_DEF_P1(arg) SNAPSHOTI_SPMC_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define SNAPSHOTI_SPMC_DEF_P2(name, type, oplist) \
|
||||
M_IF_OPLIST(oplist)(SNAPSHOTI_SPMC_DEF_P3, SNAPSHOTI_SPMC_DEF_FAILURE)(name, type, oplist)
|
||||
#define SNAPSHOTI_SPMC_DEF_P2(name, type, oplist, snapshot_t) \
|
||||
M_IF_OPLIST(oplist)(SNAPSHOTI_SPMC_DEF_P3, SNAPSHOTI_SPMC_DEF_FAILURE)(name, type, oplist, snapshot_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define SNAPSHOTI_SPMC_DEF_FAILURE(name, type, oplist) \
|
||||
#define SNAPSHOTI_SPMC_DEF_FAILURE(name, type, oplist, snapshot_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_SPMC_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
#define SNAPSHOTI_SPMC_DEF_P3(name, type, oplist) \
|
||||
/* Expand the type and the functions of a SPMC snapshot */
|
||||
#define SNAPSHOTI_SPMC_DEF_P3(name, type, oplist, snapshot_t) \
|
||||
\
|
||||
/* Create an aligned type to avoid false sharing between threads */ \
|
||||
typedef struct M_C(name, _aligned_type_s) { \
|
||||
@@ -574,14 +590,17 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(name, _aligned_type_t) *data; \
|
||||
snapshot_mrsw_int_t core; \
|
||||
} M_C(name, _t)[1]; \
|
||||
snapshot_mrsw_int_ct core; \
|
||||
} snapshot_t[1]; \
|
||||
\
|
||||
typedef type M_C(name, _type_t); \
|
||||
/* Define internal types for oplist */ \
|
||||
typedef snapshot_t M_C(name, _ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
static inline void M_C(name, _init)(M_C(name, _t) snap, size_t nReader) \
|
||||
static inline void \
|
||||
M_C(name, _init)(snapshot_t snap, size_t nReader) \
|
||||
{ \
|
||||
assert (snap != NULL); \
|
||||
assert (nReader > 0 && nReader <= SNAPSHOTI_SPMC_MAX_READER); \
|
||||
@@ -599,7 +618,8 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _clear)(M_C(name, _t) snap) \
|
||||
static inline void \
|
||||
M_C(name, _clear)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
size_t nReader = snapshot_mrsw_int_size(snap->core); \
|
||||
@@ -610,21 +630,24 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
snapshot_mrsw_int_clear(snap->core); \
|
||||
} \
|
||||
\
|
||||
static inline type *M_C(name, _write)(M_C(name, _t) snap) \
|
||||
static inline type * \
|
||||
M_C(name, _write)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
const unsigned int idx = snapshot_mrsw_int_write(snap->core); \
|
||||
return &snap->data[idx].x; \
|
||||
} \
|
||||
\
|
||||
static inline type const *M_C(name, _read_start)(M_C(name, _t) snap) \
|
||||
static inline type const * \
|
||||
M_C(name, _read_start)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
const unsigned int idx = snapshot_mrsw_int_read_start(snap->core); \
|
||||
return M_CONST_CAST(type, &snap->data[idx].x); \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _read_end)(M_C(name, _t) snap, type const *old) \
|
||||
static inline void \
|
||||
M_C(name, _read_end)(snapshot_t snap, type const *old) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
assert (old != NULL); \
|
||||
@@ -637,7 +660,8 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
snapshot_mrsw_int_read_end(snap->core, idx); \
|
||||
} \
|
||||
\
|
||||
static inline type *M_C(name, _get_write_buffer)(M_C(name, _t) snap) \
|
||||
static inline type * \
|
||||
M_C(name, _get_write_buffer)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap); \
|
||||
const unsigned int idx = snapshot_mrsw_int_get_write_idx(snap->core); \
|
||||
@@ -657,26 +681,30 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
#define SNAPSHOTI_MPMC_DEF_P1(arg) SNAPSHOTI_MPMC_DEF_P2 arg
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define SNAPSHOTI_MPMC_DEF_P2(name, type, oplist) \
|
||||
M_IF_OPLIST(oplist)(SNAPSHOTI_MPMC_DEF_P3, SNAPSHOTI_MPMC_DEF_FAILURE)(name, type, oplist)
|
||||
#define SNAPSHOTI_MPMC_DEF_P2(name, type, oplist, snapshot_t) \
|
||||
M_IF_OPLIST(oplist)(SNAPSHOTI_MPMC_DEF_P3, SNAPSHOTI_MPMC_DEF_FAILURE)(name, type, oplist, snapshot_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define SNAPSHOTI_MPMC_DEF_FAILURE(name, type, oplist) \
|
||||
#define SNAPSHOTI_MPMC_DEF_FAILURE(name, type, oplist, snapshot_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(SNAPSHOT_MPMC_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
#define SNAPSHOTI_MPMC_DEF_P3(name, type, oplist) \
|
||||
/* Expand the type and the functions of a MPMC snapshot */
|
||||
#define SNAPSHOTI_MPMC_DEF_P3(name, type, oplist, snapshot_t) \
|
||||
\
|
||||
SNAPSHOTI_SPMC_DEF_P1((M_C(name, _mrsw), type, oplist)) \
|
||||
SNAPSHOTI_SPMC_DEF_P1((M_C(name, _mrsw), type, oplist, M_C(name, _mrsw_pct))) \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_C(name, _mrsw_t) core; \
|
||||
} M_C(name, _t)[1]; \
|
||||
M_C(name, _mrsw_pct) core; \
|
||||
} snapshot_t[1]; \
|
||||
\
|
||||
typedef type M_C(name, _type_t); \
|
||||
/* Define internal types for oplist */ \
|
||||
typedef snapshot_t M_C(name, _ct); \
|
||||
typedef type M_C(name, _subtype_ct); \
|
||||
\
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
\
|
||||
static inline void M_C(name, _init)(M_C(name, _t) snap, size_t nReader, size_t nWriter) \
|
||||
static inline void \
|
||||
M_C(name, _init)(snapshot_t snap, size_t nReader, size_t nWriter) \
|
||||
{ \
|
||||
M_C(name, _mrsw_init)(snap->core, nReader + nWriter -1 ); \
|
||||
unsigned int idx = snap->core->core->currentWrite; \
|
||||
@@ -684,19 +712,22 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
snapshot_mrsw_int_write_end(snap->core->core, idx); \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _clear)(M_C(name, _t) snap) \
|
||||
static inline void \
|
||||
M_C(name, _clear)(snapshot_t snap) \
|
||||
{ \
|
||||
M_C(name, _mrsw_clear)(snap->core); \
|
||||
} \
|
||||
\
|
||||
static inline type *M_C(name, _write_start)(M_C(name, _t) snap) \
|
||||
static inline type * \
|
||||
M_C(name, _write_start)(snapshot_t snap) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap->core); \
|
||||
const unsigned int idx = snapshot_mrsw_int_write_start(snap->core->core); \
|
||||
return &snap->core->data[idx].x; \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _write_end)(M_C(name, _t) snap, type *old) \
|
||||
static inline void \
|
||||
M_C(name, _write_end)(snapshot_t snap, type *old) \
|
||||
{ \
|
||||
SNAPSHOTI_SPMC_CONTRACT(snap->core); \
|
||||
const M_C(name, _mrsw_aligned_type_t) *oldx; \
|
||||
@@ -708,12 +739,14 @@ snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned int idx)
|
||||
snapshot_mrsw_int_write_end(snap->core->core, idx); \
|
||||
} \
|
||||
\
|
||||
static inline type const *M_C(name, _read_start)(M_C(name, _t) snap) \
|
||||
static inline type const * \
|
||||
M_C(name, _read_start)(snapshot_t snap) \
|
||||
{ \
|
||||
return M_C(name, _mrsw_read_start)(snap->core); \
|
||||
} \
|
||||
\
|
||||
static inline void M_C(name, _read_end)(M_C(name, _t) snap, type const *old) \
|
||||
static inline void \
|
||||
M_C(name, _read_end)(snapshot_t snap, type const *old) \
|
||||
{ \
|
||||
M_C(name, _mrsw_read_end)(snap->core, old); \
|
||||
} \
|
||||
|
||||
+73
-51
@@ -1761,26 +1761,58 @@ namespace m_string {
|
||||
/* */
|
||||
/***********************************************************************/
|
||||
|
||||
/* Define a bounded (fixed) string of exactly 'max_size' characters
|
||||
* (excluding the final nul char).
|
||||
*/
|
||||
#define BOUNDED_STRING_DEF(name, max_size) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BOUNDED_STRING_DEF_P2(name, max_size, M_C(name, _t) ) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
/* Define the OPLIST of a BOUNDED_STRING */
|
||||
#define BOUNDED_STRING_OPLIST(name) \
|
||||
(INIT(M_C(name,_init)), \
|
||||
INIT_SET(M_C(name,_init_set)), \
|
||||
SET(M_C(name,_set)), \
|
||||
CLEAR(M_C(name,_clear)), \
|
||||
HASH(M_C(name,_hash)), \
|
||||
EQUAL(M_C(name,_equal_p)), \
|
||||
CMP(M_C(name,_cmp)), \
|
||||
TYPE(M_C(name,_ct)), \
|
||||
OOR_EQUAL(M_C(name,_oor_equal_p)), \
|
||||
OOR_SET(M_C(name, _oor_set)), \
|
||||
PARSE_STR(M_C(name,_parse_str)), \
|
||||
GET_STR(M_C(name,_get_str)), \
|
||||
OUT_STR(M_C(name,_out_str)), \
|
||||
IN_STR(M_C(name,_in_str)), \
|
||||
OUT_SERIAL(M_C(name,_out_serial)), \
|
||||
IN_SERIAL(M_C(name,_in_serial)), \
|
||||
)
|
||||
|
||||
/************************** INTERNAL ***********************************/
|
||||
|
||||
/* Contract of a bounded string.
|
||||
* A bounded string last characters is always zero. */
|
||||
#define BOUNDED_STRINGI_CONTRACT(var, max_size) do { \
|
||||
assert(var != NULL); \
|
||||
assert(var->s[max_size] == 0); \
|
||||
} while (0)
|
||||
|
||||
#define BOUNDED_STRING_DEF(name, max_size) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
BOUNDED_STRING_DEF_P2(name, max_size) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
#define BOUNDED_STRING_DEF_P2(name, max_size) \
|
||||
/* Expand the functions for a bounded string */
|
||||
#define BOUNDED_STRING_DEF_P2(name, max_size, bounded_t) \
|
||||
\
|
||||
/* Define of an array with one more to store the final nul char */ \
|
||||
typedef char M_C(name, _array_t)[max_size+1]; \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
char s[max_size+1]; \
|
||||
} M_C(name,_t)[1]; \
|
||||
} bounded_t[1]; \
|
||||
\
|
||||
/* Internal types for oplist */ \
|
||||
typedef bounded_t M_C(name, _ct); \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init)(M_C(name,_t) s) \
|
||||
M_C(name, _init)(bounded_t s) \
|
||||
{ \
|
||||
assert(s != NULL); \
|
||||
assert(max_size >= 1); \
|
||||
@@ -1790,7 +1822,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clear)(M_C(name,_t) s) \
|
||||
M_C(name, _clear)(bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
/* nothing to do */ \
|
||||
@@ -1798,21 +1830,21 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _clean)(M_C(name,_t) s) \
|
||||
M_C(name, _clean)(bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
s->s[0] = 0; \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const M_C(name,_t) s) \
|
||||
M_C(name, _size)(const bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
return strlen(s->s); \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _capacity)(const M_C(name,_t) s) \
|
||||
M_C(name, _capacity)(const bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
(void)s; /* unused */ \
|
||||
@@ -1820,7 +1852,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline char \
|
||||
M_C(name, _get_char)(const M_C(name,_t) s, size_t index) \
|
||||
M_C(name, _get_char)(const bounded_t s, size_t index) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(index < max_size); \
|
||||
@@ -1828,14 +1860,14 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(const M_C(name,_t) s) \
|
||||
M_C(name, _empty_p)(const bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
return s->s[0] == 0; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _set_str)(M_C(name,_t) s, const char str[]) \
|
||||
M_C(name, _set_str)(bounded_t s, const char str[]) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
m_core_strncpy(s->s, str, max_size); \
|
||||
@@ -1843,7 +1875,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _set_strn)(M_C(name,_t) s, const char str[], size_t n) \
|
||||
M_C(name, _set_strn)(bounded_t s, const char str[], size_t n) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(str != NULL); \
|
||||
@@ -1854,14 +1886,14 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline const char * \
|
||||
M_C(name, _get_cstr)(const M_C(name,_t) s) \
|
||||
M_C(name, _get_cstr)(const bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
return s->s; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _set)(M_C(name,_t) s, const M_C(name,_t) str) \
|
||||
M_C(name, _set)(bounded_t s, const bounded_t str) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
BOUNDED_STRINGI_CONTRACT(str, max_size); \
|
||||
@@ -1869,7 +1901,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _set_n)(M_C(name,_t) s, const M_C(name,_t) str, \
|
||||
M_C(name, _set_n)(bounded_t s, const bounded_t str, \
|
||||
size_t offset, size_t length) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
@@ -1879,21 +1911,21 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init_set)(M_C(name,_t) s, const M_C(name,_t) str) \
|
||||
M_C(name, _init_set)(bounded_t s, const bounded_t str) \
|
||||
{ \
|
||||
M_C(name,_init)(s); \
|
||||
M_C(name,_set)(s, str); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init_set_str)(M_C(name,_t) s, const char str[]) \
|
||||
M_C(name, _init_set_str)(bounded_t s, const char str[]) \
|
||||
{ \
|
||||
M_C(name,_init)(s); \
|
||||
M_C(name,_set_str)(s, str); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _cat_str)(M_C(name,_t) s, const char str[]) \
|
||||
M_C(name, _cat_str)(bounded_t s, const char str[]) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert (str != NULL); \
|
||||
@@ -1902,14 +1934,14 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _cat)(M_C(name,_t) s, const M_C(name,_t) str) \
|
||||
M_C(name, _cat)(bounded_t s, const bounded_t str) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(str, max_size); \
|
||||
M_C(name, _cat_str)(s, str->s); \
|
||||
} \
|
||||
\
|
||||
static inline int \
|
||||
M_C(name, _cmp_str)(const M_C(name,_t) s, const char str[]) \
|
||||
M_C(name, _cmp_str)(const bounded_t s, const char str[]) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(str != NULL); \
|
||||
@@ -1917,7 +1949,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline int \
|
||||
M_C(name, _cmp)(const M_C(name,_t) s, const M_C(name,_t) str) \
|
||||
M_C(name, _cmp)(const bounded_t s, const bounded_t str) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
BOUNDED_STRINGI_CONTRACT(str, max_size); \
|
||||
@@ -1925,7 +1957,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _equal_str_p)(const M_C(name,_t) s, const char str[]) \
|
||||
M_C(name, _equal_str_p)(const bounded_t s, const char str[]) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(str != NULL); \
|
||||
@@ -1933,14 +1965,14 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _equal_p)(const M_C(name,_t) s, const M_C(name,_t) str) \
|
||||
M_C(name, _equal_p)(const bounded_t s, const bounded_t str) \
|
||||
{ \
|
||||
/* _equal_p may be called in context OOR. So contract cannot be verified */ \
|
||||
return (s->s[max_size] == str->s[max_size]) & (strcmp(s->s, str->s) == 0); \
|
||||
} \
|
||||
\
|
||||
static inline int \
|
||||
M_C(name, _printf)(M_C(name,_t) s, const char format[], ...) \
|
||||
M_C(name, _printf)(bounded_t s, const char format[], ...) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(format != NULL); \
|
||||
@@ -1953,7 +1985,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline int \
|
||||
M_C(name, _cat_printf)(M_C(name,_t) s, const char format[], ...) \
|
||||
M_C(name, _cat_printf)(bounded_t s, const char format[], ...) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(format != NULL); \
|
||||
@@ -1968,7 +2000,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _fgets)(M_C(name,_t)s, FILE *f, string_fgets_t arg) \
|
||||
M_C(name, _fgets)(bounded_t s, FILE *f, string_fgets_t arg) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(f != NULL); \
|
||||
@@ -1984,7 +2016,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _fputs)(FILE *f, const M_C(name,_t) s) \
|
||||
M_C(name, _fputs)(FILE *f, const bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(f != NULL); \
|
||||
@@ -1992,7 +2024,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _hash)(const M_C(name,_t) s) \
|
||||
M_C(name, _hash)(const bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
/* Cannot use m_core_hash: alignment not sufficent */ \
|
||||
@@ -2006,7 +2038,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _oor_equal_p)(const M_C(name,_t) s, unsigned char n) \
|
||||
M_C(name, _oor_equal_p)(const bounded_t s, unsigned char n) \
|
||||
{ \
|
||||
/* s may be invalid contract */ \
|
||||
assert (s != NULL); \
|
||||
@@ -2015,7 +2047,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _oor_set)(M_C(name,_t) s, unsigned char n) \
|
||||
M_C(name, _oor_set)(bounded_t s, unsigned char n) \
|
||||
{ \
|
||||
/* s may be invalid contract */ \
|
||||
assert (s != NULL); \
|
||||
@@ -2024,7 +2056,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _get_str)(string_t v, const M_C(name,_t) s, bool append) \
|
||||
M_C(name, _get_str)(string_t v, const bounded_t s, bool append) \
|
||||
{ \
|
||||
STRINGI_CONTRACT(v); \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
@@ -2038,7 +2070,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _out_str)(FILE *f, const M_C(name,_t) s) \
|
||||
M_C(name, _out_str)(FILE *f, const bounded_t s) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(s, max_size); \
|
||||
assert(f != NULL); \
|
||||
@@ -2052,7 +2084,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _in_str)(M_C(name,_t) v, FILE *f) \
|
||||
M_C(name, _in_str)(bounded_t v, FILE *f) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(v, max_size); \
|
||||
assert(f != NULL); \
|
||||
@@ -2065,7 +2097,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _parse_str)(M_C(name,_t) v, const char str[], const char **endptr) \
|
||||
M_C(name, _parse_str)(bounded_t v, const char str[], const char **endptr) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(v, max_size); \
|
||||
assert(str != NULL); \
|
||||
@@ -2078,7 +2110,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _out_serial)(m_serial_write_t serial, const M_C(name,_t) v) \
|
||||
M_C(name, _out_serial)(m_serial_write_t serial, const bounded_t v) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(v, max_size); \
|
||||
assert (serial != NULL && serial->m_interface != NULL); \
|
||||
@@ -2086,7 +2118,7 @@ namespace m_string {
|
||||
} \
|
||||
\
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _in_serial)(M_C(name,_t) v, m_serial_read_t serial) \
|
||||
M_C(name, _in_serial)(bounded_t v, m_serial_read_t serial) \
|
||||
{ \
|
||||
BOUNDED_STRINGI_CONTRACT(v, max_size); \
|
||||
assert (serial != NULL && serial->m_interface != NULL); \
|
||||
@@ -2101,16 +2133,6 @@ namespace m_string {
|
||||
}
|
||||
|
||||
|
||||
/* Define the OPLIST of a BOUNDED_STRING */
|
||||
#define BOUNDED_STRING_OPLIST(name) \
|
||||
(INIT(M_C(name,_init)), INIT_SET(M_C(name,_init_set)), \
|
||||
SET(M_C(name,_set)), CLEAR(M_C(name,_clear)), HASH(M_C(name,_hash)), \
|
||||
EQUAL(M_C(name,_equal_p)), CMP(M_C(name,_cmp)), TYPE(M_C(name,_t)), \
|
||||
OOR_EQUAL(M_C(name,_oor_equal_p)), OOR_SET(M_C(name, _oor_set)) \
|
||||
PARSE_STR(M_C(name,_parse_str)), GET_STR(M_C(name,_get_str)), \
|
||||
OUT_STR(M_C(name,_out_str)), IN_STR(M_C(name,_in_str)), \
|
||||
OUT_SERIAL(M_C(name,_out_serial)), IN_SERIAL(M_C(name,_in_serial)), \
|
||||
)
|
||||
|
||||
/* Init a constant bounded string.
|
||||
Try to do a clean cast */
|
||||
|
||||
@@ -196,8 +196,11 @@ namespace m_tuple {
|
||||
typedef struct M_C(name, _s) { \
|
||||
M_MAP(TUPLEI_DEFINE_RECUR_TYPE_ELE , __VA_ARGS__) \
|
||||
} M_C(name,_t)[1]; \
|
||||
\
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr);
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
/* Define internal type for oplist */ \
|
||||
typedef M_C(name, _t) M_C(name, _ct);
|
||||
|
||||
#define TUPLEI_DEFINE_RECUR_TYPE_ELE(a) \
|
||||
TUPLEI_GET_TYPE a TUPLEI_GET_FIELD a ;
|
||||
@@ -644,7 +647,7 @@ namespace m_tuple {
|
||||
INIT_WITH(M_C(name, _init_set2)), \
|
||||
SET(M_C(name,_set)), \
|
||||
CLEAR(M_C(name, _clear)), \
|
||||
TYPE(M_C(name,_t)), \
|
||||
TYPE(M_C(name,_ct)), \
|
||||
M_IF_METHOD_ALL(CMP, __VA_ARGS__)(CMP(M_C(name, _cmp)),), \
|
||||
M_IF_METHOD_ALL(HASH, __VA_ARGS__)(HASH(M_C(name, _hash)),), \
|
||||
M_IF_METHOD_ALL(EQUAL, __VA_ARGS__)(EQUAL(M_C(name, _equal_p)),), \
|
||||
|
||||
+8
-2
@@ -172,20 +172,26 @@
|
||||
|
||||
/* Define the type */
|
||||
#define VARIANTI_DEFINE_TYPE(name, ...) \
|
||||
/* Define enum of all types of the variant */ \
|
||||
enum M_C(name, _enum) { M_C(name, _EMPTY) \
|
||||
M_MAP2(VARIANTI_DEFINE_UNION_ELE, name, __VA_ARGS__) \
|
||||
}; \
|
||||
/* Define enum equal to the number of types of the variant */ \
|
||||
enum M_C(name, _enum_max) { \
|
||||
M_C(name, _MAX_TYPE) = M_NARGS(__VA_ARGS__) \
|
||||
}; \
|
||||
/* Define the variant */ \
|
||||
typedef struct M_C(name, _s) { \
|
||||
enum M_C(name, _enum) type; \
|
||||
union { \
|
||||
M_MAP(VARIANTI_DEFINE_TYPE_ELE , __VA_ARGS__) \
|
||||
} value; \
|
||||
} M_C(name,_t)[1]; \
|
||||
\
|
||||
typedef struct M_C(name, _s) *M_C(name, _ptr); \
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr);
|
||||
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
|
||||
/* Define internal type for oplist */ \
|
||||
typedef M_C(name, _t) M_C(name, _ct);
|
||||
|
||||
#define VARIANTI_DEFINE_UNION_ELE(name, a) \
|
||||
, M_C4(name, _, VARIANTI_GET_FIELD a, _value)
|
||||
@@ -724,7 +730,7 @@
|
||||
SET(M_C(name,_set)), \
|
||||
CLEAR(M_C(name, _clear)), \
|
||||
CLEAN(M_C(name, _clean)), \
|
||||
TYPE(M_C(name,_t)), \
|
||||
TYPE(M_C(name,_ct)), \
|
||||
TEST_EMPTY(M_C(name,_empty_p)), \
|
||||
M_IF_METHOD_ALL(HASH, __VA_ARGS__)(HASH(M_C(name, _hash)),), \
|
||||
M_IF_METHOD_ALL(EQUAL, __VA_ARGS__)(EQUAL(M_C(name, _equal_p)),), \
|
||||
|
||||
+18
-18
@@ -106,7 +106,7 @@ typedef struct work_order_s {
|
||||
#if M_USE_WORKER_CPP_FUNCTION
|
||||
std::function<void(void*)> function; // The work order function (for C++)
|
||||
#endif
|
||||
} worker_order_t;
|
||||
} worker_order_ct;
|
||||
|
||||
/* Define the macros needed to initialize an order.
|
||||
* * MACRO to be used to send an empty order to stop the thread
|
||||
@@ -124,11 +124,11 @@ typedef struct work_order_s {
|
||||
is not sufficient for initialization of the structure.
|
||||
So let's use C++ constructor, destructor and copy constructor */
|
||||
#if M_USE_WORKER_CPP_FUNCTION
|
||||
# define WORKERI_CPP_INIT(x) (new (&(x)) worker_order_t())
|
||||
# define WORKERI_CPP_INIT_SET(x, y) (new (&(x)) worker_order_t(y))
|
||||
# define WORKERI_CPP_INIT(x) (new (&(x)) worker_order_ct())
|
||||
# define WORKERI_CPP_INIT_SET(x, y) (new (&(x)) worker_order_ct(y))
|
||||
# define WORKERI_CPP_SET(x, y) ((x) = (y))
|
||||
# define WORKERI_CPP_CLEAR(x) ((&(x))->~worker_order_t())
|
||||
# define WORKERI_CPP_INIT_MOVE(x,y) (new (&(x)) worker_order_t(y), ((&(y))->~worker_order_t()))
|
||||
# define WORKERI_CPP_CLEAR(x) ((&(x))->~worker_order_ct())
|
||||
# define WORKERI_CPP_INIT_MOVE(x,y) (new (&(x)) worker_order_ct(y), ((&(y))->~worker_order_ct()))
|
||||
# define WORKER_OPLIST \
|
||||
(INIT(WORKERI_CPP_INIT), INIT_SET(WORKERI_CPP_INIT_SET), \
|
||||
SET(WORKERI_CPP_SET), CLEAR(WORKERI_CPP_CLEAR), INIT_MOVE(WORKERI_CPP_INIT_MOVE) )
|
||||
@@ -139,10 +139,10 @@ typedef struct work_order_s {
|
||||
/* Definition of a worker (implemented by a thread) */
|
||||
typedef struct worker_thread_s {
|
||||
m_thread_t id;
|
||||
} worker_thread_t;
|
||||
} worker_thread_ct;
|
||||
|
||||
/* Definition of the queue that will record the work orders */
|
||||
BUFFER_DEF(worker_queue, worker_order_t, 0,
|
||||
BUFFER_DEF(worker_queue, worker_order_ct, 0,
|
||||
BUFFER_QUEUE|BUFFER_UNBLOCKING_PUSH|BUFFER_BLOCKING_POP|BUFFER_THREAD_SAFE|BUFFER_DEFERRED_POP, WORKER_OPLIST)
|
||||
|
||||
/* Definition the global pool of workers */
|
||||
@@ -151,7 +151,7 @@ typedef struct worker_s {
|
||||
worker_queue_t queue_g;
|
||||
|
||||
/* The table of available workers */
|
||||
worker_thread_t *worker;
|
||||
worker_thread_ct *worker;
|
||||
|
||||
/* Number of workers in the table */
|
||||
unsigned int numWorker_g;
|
||||
@@ -163,7 +163,7 @@ typedef struct worker_s {
|
||||
void (*clearFunc_g)(void);
|
||||
|
||||
m_mutex_t lock;
|
||||
m_cond_t a_thread_ends; // A worker has ended
|
||||
m_cond_t a_thread_ends; // EVENT: A worker has ended
|
||||
|
||||
} worker_t[1];
|
||||
|
||||
@@ -207,7 +207,7 @@ workeri_get_cpu_count(void)
|
||||
|
||||
/* Execute the registered work order **synchronously** */
|
||||
static inline void
|
||||
workeri_exec(worker_order_t *w)
|
||||
workeri_exec(worker_order_ct *w)
|
||||
{
|
||||
assert (w!= NULL && w->block != NULL);
|
||||
WORKERI_DEBUG ("Starting thread with data %p\n", w->data);
|
||||
@@ -236,7 +236,7 @@ workeri_thread(void *arg)
|
||||
// Get back the given argument
|
||||
struct worker_s *g = M_ASSIGN_CAST(struct worker_s *, arg);
|
||||
while (true) {
|
||||
worker_order_t w;
|
||||
worker_order_ct w;
|
||||
// If needed, reset the global state of the worker
|
||||
if (g->resetFunc_g != NULL) {
|
||||
g->resetFunc_g();
|
||||
@@ -282,9 +282,9 @@ worker_init(worker_t g, int numWorker, unsigned int extraQueue, void (*resetFunc
|
||||
// Initialization
|
||||
assert(numWorker > 0);
|
||||
size_t numWorker_st = (size_t) numWorker;
|
||||
g->worker = M_MEMORY_REALLOC(worker_thread_t, NULL, numWorker_st);
|
||||
g->worker = M_MEMORY_REALLOC(worker_thread_ct, NULL, numWorker_st);
|
||||
if (g->worker == NULL) {
|
||||
M_MEMORY_FULL(sizeof (worker_thread_t) * numWorker_st);
|
||||
M_MEMORY_FULL(sizeof (worker_thread_ct) * numWorker_st);
|
||||
return;
|
||||
}
|
||||
worker_queue_init(g->queue_g, numWorker_st + extraQueue);
|
||||
@@ -315,7 +315,7 @@ worker_clear(worker_t g)
|
||||
assert (worker_queue_empty_p (g->queue_g));
|
||||
// Push the terminate order on the queue
|
||||
for(unsigned int i = 0; i < g->numWorker_g; i++) {
|
||||
worker_order_t w = WORKERI_EMPTY_ORDER;
|
||||
worker_order_ct w = WORKERI_EMPTY_ORDER;
|
||||
// Normaly all worker threads shall be waiting at this
|
||||
// stage, so all push won't block as the queue is empty.
|
||||
// But for robustness, let's wait.
|
||||
@@ -350,7 +350,7 @@ worker_start(worker_sync_t block, worker_t g)
|
||||
static inline void
|
||||
worker_spawn(worker_sync_t block, void (*func)(void *data), void *data)
|
||||
{
|
||||
const worker_order_t w = { block, data, func WORKERI_EXTRA_ORDER };
|
||||
const worker_order_ct w = { block, data, func WORKERI_EXTRA_ORDER };
|
||||
if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
|
||||
&& worker_queue_push (block->worker->queue_g, w) == true) {
|
||||
WORKERI_DEBUG ("Sending data to thread: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
@@ -368,7 +368,7 @@ worker_spawn(worker_sync_t block, void (*func)(void *data), void *data)
|
||||
static inline void
|
||||
worker_spawn_block(worker_sync_t block, void (^func)(void *data), void *data)
|
||||
{
|
||||
const worker_order_t w = { block, data, NULL, func };
|
||||
const worker_order_ct w = { block, data, NULL, func };
|
||||
if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
|
||||
&& worker_queue_push (block->worker->queue_g, w) == true) {
|
||||
WORKERI_DEBUG ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
@@ -387,7 +387,7 @@ worker_spawn_block(worker_sync_t block, void (^func)(void *data), void *data)
|
||||
static inline void
|
||||
worker_spawn_function(worker_sync_t block, std::function<void(void *data)> func, void *data)
|
||||
{
|
||||
const worker_order_t w = { block, data, NULL, func };
|
||||
const worker_order_ct w = { block, data, NULL, func };
|
||||
if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
|
||||
&& worker_queue_push (block->worker->queue_g, w) == true) {
|
||||
WORKERI_DEBUG ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
|
||||
@@ -429,7 +429,7 @@ worker_sync(worker_sync_t block)
|
||||
static inline void
|
||||
worker_flush(worker_t g)
|
||||
{
|
||||
worker_order_t w;
|
||||
worker_order_ct w;
|
||||
while (worker_queue_pop_blocking (&w, g->queue_g, false) == true) {
|
||||
workeri_exec(&w);
|
||||
worker_queue_pop_release(g->queue_g);
|
||||
|
||||
@@ -150,7 +150,7 @@ static void test_global(void)
|
||||
|
||||
static void test_mrsw_int1(void)
|
||||
{
|
||||
snapshot_mrsw_int_t idx;
|
||||
snapshot_mrsw_int_ct idx;
|
||||
snapshot_mrsw_int_init(idx, 1);
|
||||
|
||||
assert (snapshot_mrsw_int_get_write_idx(idx) == 1);
|
||||
@@ -180,7 +180,7 @@ static void test_mrsw_int1(void)
|
||||
|
||||
static void test_mrsw_int2(void)
|
||||
{
|
||||
snapshot_mrsw_int_t idx;
|
||||
snapshot_mrsw_int_ct idx;
|
||||
snapshot_mrsw_int_init(idx, 2);
|
||||
|
||||
assert (snapshot_mrsw_int_get_write_idx(idx) == 1);
|
||||
|
||||
Reference in new issue
Block a user