From bcc9f2c894b2e83e4cc981a00c0f64cf8937acd8 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sun, 9 Mar 2025 20:41:17 +0100 Subject: [PATCH] Port B+TREE to new memory model --- m-bptree.h | 142 ++++++++++++++++++++++++++--------------------------- m-core.h | 24 +++++---- 2 files changed, 85 insertions(+), 81 deletions(-) diff --git a/m-bptree.h b/m-bptree.h index a99e03c9..a10af74c 100644 --- a/m-bptree.h +++ b/m-bptree.h @@ -343,6 +343,7 @@ M_BPTR33_DEF_IT(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \ M_BPTR33_DEF_EXT(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \ M_EMPLACE_ASS_ARRAY_OR_QUEUE_DEF(M_INV(isMap), name, tree_t, key_oplist, value_oplist) + /* TODO: Check if key type has not disabled INIT_MOVE */ /* Define the types of a B+Tree */ #define M_BPTR33_DEF_TYPE(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \ @@ -406,7 +407,7 @@ \ /* Allocate a new node */ \ /* TODO: Can be specialized to alloc for leaf or for non leaf */ \ - M_INLINE node_t M_F(name, _new_node)(void) \ + M_INLINE node_t M_F(name, _new_node)(M_P_EXPAND_void) \ { \ M_STATIC_ASSERT(N >= 2, M_LIB_ILLEGAL_PARAM, \ "Number of items per node shall be >= 2."); \ @@ -420,9 +421,9 @@ return n; \ } \ \ - M_INLINE void M_F(name, _init)(tree_t b) \ + M_P(void, name, _init, tree_t b) \ { \ - b->root = M_F(name, _new_node)(); \ + b->root = M_F(name, _new_node)(M_R_EXPAND_void); \ b->size = 0; \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ } \ @@ -443,7 +444,7 @@ return num; \ } \ \ - M_INLINE void M_F(name, _reset)(tree_t b) \ + M_P(void, name, _reset, tree_t b) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ node_t next, n = b->root; \ @@ -486,19 +487,19 @@ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ } \ \ - M_INLINE void M_F(name, _clear)(tree_t b) \ + M_P(void, name, _clear, tree_t b) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ - M_F(name, _reset)(b); \ + M_F(name, _reset)M_R(b); \ /* Once the tree is clean, only the root remains */ \ M_CALL_DEL(key_oplist, b->root); \ b->root = NULL; \ } \ \ /* Copy recursively the node 'o' of root node 'root' */ \ - M_INLINE node_t M_F(name, _copy_node)(const node_t o, const node_t root) \ + M_P(node_t, name, _copy_node, const node_t o, const node_t root) \ { \ - node_t n = M_F(name, _new_node)(); \ + node_t n = M_F(name, _new_node)(M_R_EXPAND_void); \ /* Set default number of keys and type to copy */ \ n->num = o->num; \ /* By default it is not linked to its brother. \ @@ -520,7 +521,7 @@ /* Copy recursively the associated nodes if it is not a leaf */ \ for(int i = 0; i <= num; i++) { \ M_ASSERT(o->kind.node[i] != root); \ - n->kind.node[i] = M_F(name, _copy_node)(o->kind.node[i], root); \ + n->kind.node[i] = M_F(name, _copy_node)M_R(o->kind.node[i], root); \ } \ /* The copied nodes don't have their next field correct */ \ /* Fix the next field for the copied nodes */ \ @@ -542,22 +543,22 @@ return n; \ } \ \ - M_INLINE void M_F(name, _init_set)(tree_t b, const tree_t o) \ + M_P(void, name, _init_set, tree_t b, const tree_t o) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, o); \ M_ASSERT (b != NULL); \ /* Just copy recursively the root node */ \ - b->root = M_F(name, _copy_node)(o->root, o->root); \ + b->root = M_F(name, _copy_node)M_R(o->root, o->root); \ b->size = o->size; \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ } \ \ - M_INLINE void M_F(name, _set)(tree_t b, const tree_t o) \ + M_P(void, name, _set, tree_t b, const tree_t o) \ { \ /* NOTE: We could reuse the already allocated nodes of 'b'. \ Not sure if it worth the effort */ \ - M_F(name, _clear)(b); \ - M_F(name, _init_set)(b, o); \ + M_F(name, _clear)M_R(b); \ + M_F(name, _init_set)M_R(b, o); \ } \ \ M_INLINE bool M_F(name, _empty_p)(const tree_t b) \ @@ -573,7 +574,7 @@ return b->size; \ } \ \ - M_INLINE node_t M_F(name, _search_for_leaf)(pit_t pit, const tree_t b, key_t const key) \ + M_INLINE node_t M_F(name, _i_search_for_leaf)(pit_t pit, const tree_t b, key_t const key) \ { \ node_t n = b->root; \ int np = 0; \ @@ -607,7 +608,7 @@ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ pit_t pit; \ /* Get the leaf node where the key can be */ \ - node_t n = M_F(name, _search_for_leaf)(pit, b, key); \ + node_t n = M_F(name, _i_search_for_leaf)(pit, b, key); \ int cmp = 0; \ M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \ /* Search in the leaf for key */ \ @@ -627,11 +628,11 @@ return M_CONST_CAST(value_t, M_F(name, _get)(b, key)); \ } \ \ - M_INLINE int \ - M_F(name, _search_and_insert_in_leaf)(node_t n, key_t const key \ + M_P(int, name, _i_search_and_insert_in_leaf, node_t n, key_t const key \ M_IF(isMap)( M_DEFERRED_COMMA value_t const value,) ) \ { \ M_ASSERT (M_F(name, _is_leaf)(n)); \ + M_ASSERT_POOL(); \ int i, num = M_F(name, _get_num)(n); \ M_ASSERT (num <= N); \ /* Search for the key in the node n (a leaf) for insertion */ \ @@ -659,10 +660,10 @@ return i; \ } \ \ - M_INLINE int \ - M_F(name, _search_and_insert_in_node)(node_t n, node_t l, key_t key) \ + M_P(int, name, _i_search_and_insert_in_node, node_t n, node_t l, key_t key) \ { \ M_ASSERT (!M_F(name, _is_leaf)(n)); \ + M_ASSERT_POOL(); \ int i, num = M_F(name, _get_num)(n); \ M_ASSERT (num <= N); \ /* Search for the key in the node n (not a leaf) for insertion */ \ @@ -682,16 +683,16 @@ return i; \ } \ \ - M_INLINE void \ - M_IF(isMap)(M_F(name, _set_at),M_F(name,_push))(tree_t b, key_t const key \ - M_IF(isMap)(M_DEFERRED_COMMA value_t const value,)) \ + M_IF(isMap)( \ + M_P(void, name, _set_at, tree_t b, key_t const key, value_t const value) , \ + M_P(void, name, _push, tree_t b, key_t const key) ) \ { \ pit_t pit; \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ - node_t leaf = M_F(name, _search_for_leaf)(pit, b, key); \ + node_t leaf = M_F(name, _i_search_for_leaf)(pit, b, key); \ /* Insert key into the leaf.*/ \ /* NOTE: Even if there is N elements, we can still add one more.*/ \ - int i = M_F(name, _search_and_insert_in_leaf)(leaf, key M_IF (isMap)(M_DEFERRED_COMMA value,)); \ + int i = M_F(name, _i_search_and_insert_in_leaf)M_R(leaf, key M_IF (isMap)(M_DEFERRED_COMMA value,)); \ if (i < 0) { \ /* Nothing to do anymore. key already exists in the tree. \ value has been updated if needed */ \ @@ -713,7 +714,7 @@ /* leaf is full: need to slip the leaf in two */ \ int nnum = (N + 1) / 2; \ num = N + 1 - nnum; \ - node_t nleaf = M_F(name, _new_node)(); \ + node_t nleaf = M_F(name, _new_node)(M_R_EXPAND_void); \ /* Move half objects to the new node */ \ memmove(&nleaf->key[0], &leaf->key[num], sizeof(key_t)*(unsigned int)nnum); \ M_IF(isMap)(memmove(&nleaf->kind.value[0], &leaf->kind.value[num], sizeof(value_t)*(unsigned int)nnum);,) \ @@ -728,7 +729,7 @@ while (true) { \ if (pit->num == 0) { \ /* We reach root ==> Need to increase the height of the tree.*/ \ - node_t parent = M_F(name, _new_node)(); \ + node_t parent = M_F(name, _new_node)(M_R_EXPAND_void); \ parent->num = 1; \ /* TBC: DO_INIT_MOVE instead ? If key was in a node !*/ \ M_CALL_INIT_SET(key_oplist, parent->key[0], *key_ptr); \ @@ -741,7 +742,7 @@ /* Non root node. Get the parent node */ \ node_t parent = pit->parent[--pit->num]; \ /* Insert into parent (It is big enough to receive temporary one more) */ \ - i = M_F(name, _search_and_insert_in_node)(parent, leaf, *key_ptr); \ + i = M_F(name, _i_search_and_insert_in_node)M_R(parent, leaf, *key_ptr); \ parent->kind.node[i] = leaf; \ parent->kind.node[i+1] = nleaf; \ /* Test if parent node is full? */ \ @@ -754,7 +755,7 @@ int nnp = N / 2; \ int np = N - nnp; \ M_ASSERT (nnp > 0 && np > 0 && nnp+np+1 == N+1); \ - node_t nparent = M_F(name, _new_node)(); \ + node_t nparent = M_F(name, _new_node)(M_R_EXPAND_void); \ /* Move half items to new node (Like a classic B-TREE) \ and the median key to the grand-parent*/ \ memmove(&nparent->key[0], &parent->key[np+1], sizeof(key_t)*(unsigned int)nnp); \ @@ -772,7 +773,7 @@ } \ } \ \ - M_INLINE value_t *M_F(name, _safe_get)(tree_t b, key_t const key) \ + M_P(value_t *, name, _safe_get, tree_t b, key_t const key) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ /* Not optimized implementation */ \ @@ -781,7 +782,7 @@ M_IF(isMap)( \ value_t v; \ M_CALL_INIT(value_oplist, v); \ - M_F(name, _set_at)(b, key, v); \ + M_F(name, _set_at)M_R(b, key, v); \ M_CALL_CLEAR(value_oplist, v); \ , \ M_F(name, _push)(b, key); \ @@ -791,10 +792,10 @@ return ret; \ } \ \ - M_INLINE int \ - M_F(name, _search_and_remove_in_leaf)(node_t n, key_t const key) \ + M_P(int, name, _i_search_and_remove_in_leaf, node_t n, key_t const key) \ { \ M_ASSERT(M_F(name, _is_leaf)(n)); \ + M_ASSERT_POOL(); \ const int num = M_F(name, _get_num)(n); \ for(int i = 0; i < num; i++) { \ const int cmp = M_CALL_CMP(key_oplist, key, n->key[i]); \ @@ -811,10 +812,11 @@ return -1; /* Not found */ \ } \ \ - M_INLINE void M_F(name, _left_shift)(node_t parent, int k) \ + M_P(void, name, _i_left_shift, node_t parent, int k) \ { \ M_ASSERT (parent != NULL && !M_F(name, _is_leaf)(parent)); \ M_ASSERT (0 <= k && k < M_F(name, _get_num)(parent)); \ + M_ASSERT_POOL(); \ node_t left = parent->kind.node[k]; \ node_t right = parent->kind.node[k+1]; \ M_ASSERT (left != NULL && right != NULL); \ @@ -846,10 +848,11 @@ M_ASSERT (left->num != 0); \ } \ \ - M_INLINE void M_F(name, _right_shift)(node_t parent, int k) \ + M_P(void, name, _i_right_shift, node_t parent, int k) \ { \ M_ASSERT (parent != NULL && !M_F(name, _is_leaf)(parent)); \ M_ASSERT (0 <= k && k < M_F(name, _get_num)(parent)); \ + M_ASSERT_POOL(); \ node_t left = parent->kind.node[k]; \ node_t right = parent->kind.node[k+1]; \ M_ASSERT (left != NULL && right != NULL); \ @@ -880,7 +883,7 @@ M_ASSERT (left->num != 0); \ } \ \ - M_INLINE void M_F(name, _merge_node)(node_t parent, int k, bool leaf) \ + M_P(void, name, _i_merge_node, node_t parent, int k, bool leaf) \ { \ M_ASSERT (parent != NULL && !M_F(name, _is_leaf)(parent)); \ M_ASSERT (0 <= k && k < M_F(name, _get_num(parent))); \ @@ -916,7 +919,7 @@ /* We can also cache the index when we descend the tree. \ TODO: Bench if this is worth the effort.*/ \ M_INLINE int \ - M_F(name, _search_for_node)(node_t parent, node_t child) \ + M_F(name, _i_search_for_node)(node_t parent, node_t child) \ { \ M_ASSERT (!M_F(name, _is_leaf)(parent)); \ int i = 0; \ @@ -928,12 +931,12 @@ } \ } \ \ - M_INLINE bool M_F(name, _erase)(tree_t b, key_t const key) \ + M_P(bool, name, _erase, tree_t b, key_t const key) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ pit_t pit; \ - node_t leaf = M_F(name, _search_for_leaf)(pit, b, key); \ - int k = M_F(name, _search_and_remove_in_leaf)(leaf, key); \ + node_t leaf = M_F(name, _i_search_for_leaf)(pit, b, key); \ + int k = M_F(name, _i_search_and_remove_in_leaf)M_R(leaf, key); \ /* If key is not found ==> erase failed */ \ if (k < 0) return false; \ /* Remove one item from the B+TREE */ \ @@ -949,15 +952,15 @@ /* Search for node 'leaf' in parent */ \ node_t parent = pit->parent[--pit->num]; \ M_ASSERT (parent != NULL); \ - k = M_F(name, _search_for_node)(parent, leaf); \ + k = M_F(name, _i_search_for_node)(parent, leaf); \ /* Look for the neighbour of the removed key. */ \ /* if we can steal one key from them to keep our node balanced */ \ if (k > 0 && M_F(name, _get_num)(parent->kind.node[k-1]) > N/2) { \ - M_F(name, _left_shift)(parent, k-1); \ + M_F(name, _i_left_shift)M_R(parent, k-1); \ return true; \ } else if (k < M_F(name, _get_num)(parent) \ && M_F(name, _get_num)(parent->kind.node[k+1]) > N/2) { \ - M_F(name, _right_shift)(parent, k); \ + M_F(name, _i_right_shift)M_R(parent, k); \ return true; \ } \ /* Merge both nodes, removing 'k' from parent */ \ @@ -965,7 +968,7 @@ k--; \ M_ASSERT(k >= 0 && k < M_F(name, _get_num)(parent)); \ /* Merge 'k' & 'k+1' & remove 'k' from parent */ \ - M_F(name, _merge_node)(parent, k, pass1); \ + M_F(name, _i_merge_node)M_R(parent, k, pass1); \ /* Check if we need to continue */ \ if (M_F(name, _get_num)(parent) >= N/2) \ return true; \ @@ -984,16 +987,17 @@ } \ } \ \ - M_INLINE bool M_F(name, _pop_at)(value_t *ptr, tree_t b, key_t const key) \ + M_P(bool, name, _pop_at, value_t *ptr, tree_t b, key_t const key) \ { \ if (ptr != NULL) { \ + /* Not optimized tree parsing */ \ value_t *ref = M_F(name, _get)(b, key); \ if (ref == NULL) { \ return false; \ } \ M_CALL_SET(value_oplist, *ptr, *ref); \ } \ - return M_F(name, _erase)(b, key); \ + return M_F(name, _erase)M_R(b, key); \ } \ \ M_INLINE value_t * \ @@ -1046,13 +1050,12 @@ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ } \ \ - M_INLINE void \ - M_F(name, _move)(tree_t b, tree_t ref) \ + M_P(void, name, _move, tree_t b, tree_t ref) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, ref); \ M_ASSERT (b != ref); \ - M_F(name,_clear)(b); \ + M_F(name,_clear)M_R(b); \ M_F(name,_init_move)(b, ref); \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ } \ @@ -1161,7 +1164,7 @@ M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \ M_ASSERT (it != NULL); \ pit_t pit; \ - node_t n = M_F(name, _search_for_leaf)(pit, b, key); \ + node_t n = M_F(name, _i_search_for_leaf)(pit, b, key); \ it->node = n; \ int i; \ M_BPTR33_NODE_CONTRACT(N, isMulti, key_oplist, n, b->root); \ @@ -1259,29 +1262,29 @@ , /* NO HASH METHOD */ ) \ \ M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)( \ - M_INLINE void M_F(name, _get_str)(m_string_t str, \ - const tree_t t1, bool append) { \ + M_P(void, name, _get_str, m_string_t str, const tree_t t1, bool append) \ + { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \ M_ASSERT(str != NULL); \ - (append ? m_string_cat_cstr : m_string_set_cstr) (str, "["); \ + (append ? m_string_cat_cstr : m_string_set_cstr) M_R(str, "["); \ bool commaToPrint = false; \ it_t it; \ for (M_F(name, _it)(it, t1) ; \ !M_F(name, _end_p)(it); \ M_F(name, _next)(it)) { \ if (commaToPrint) \ - m_string_push_back (str, M_GET_SEPARATOR key_oplist); \ + m_string_push_back M_R(str, M_GET_SEPARATOR key_oplist); \ commaToPrint = true; \ subtype_t const *ref1 = M_F(name, _cref)(it); \ M_IF(isMap)( \ M_CALL_GET_STR(key_oplist, str, *ref1->key_ptr, true); \ - m_string_cat_cstr(str, ":"); \ + m_string_cat_cstr M_R(str, ":"); \ M_CALL_GET_STR(value_oplist,str, *ref1->value_ptr, true) \ , \ M_CALL_GET_STR(key_oplist, str, *ref1, true); \ ); \ } \ - m_string_push_back (str, ']'); \ + m_string_push_back M_R(str, ']'); \ } \ , /* NO GET_STR */ ) \ \ @@ -1314,12 +1317,11 @@ , /* no out_str */ ) \ \ M_IF_METHOD_BOTH(PARSE_STR, key_oplist, value_oplist)( \ - M_INLINE bool \ - M_F(name, _parse_str)(tree_t t1, const char str[], const char **endp) \ + M_P(bool, name, _parse_str, tree_t t1, const char str[], const char **endp) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \ M_ASSERT (str != NULL); \ - M_F(name,_reset)(t1); \ + M_F(name,_reset)M_R(t1); \ int c = *str++; \ if (M_UNLIKELY (c != '[')) { c = 0; goto exit; } \ c = *str++; \ @@ -1335,9 +1337,9 @@ b = M_CALL_PARSE_STR(value_oplist, value, str, &str); \ c = m_core_str_nospace(&str); \ if (b == false || c == 0) { c = 0; break; } \ - M_F(name, _set_at)(t1, key, value); \ + M_F(name, _set_at)M_R(t1, key, value); \ , \ - M_F(name, _push)(t1, key); \ + M_F(name, _push)M_R(t1, key); \ ) \ } while (c == M_GET_SEPARATOR key_oplist); \ } \ @@ -1349,12 +1351,11 @@ , /* no parse_str */ ) \ \ M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)( \ - M_INLINE bool \ - M_F(name, _in_str)(tree_t t1, FILE *file) \ + M_P(bool, name, _in_str, tree_t t1, FILE *file) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \ M_ASSERT (file != NULL); \ - M_F(name,_reset)(t1); \ + M_F(name,_reset)M_R(t1); \ int c = fgetc(file); \ if (M_UNLIKELY (c != '[')) return false; \ c = fgetc(file); \ @@ -1371,9 +1372,9 @@ b = M_CALL_IN_STR(value_oplist,value, file); \ c = m_core_fgetc_nospace(file); \ if (b == false || c == EOF) { c = 0; break; } \ - M_F(name, _set_at)(t1, key, value) \ + M_F(name, _set_at)M_R(t1, key, value) \ , \ - M_F(name, _push)(t1, key) \ + M_F(name, _push)M_R(t1, key) \ ); \ } while (c == M_GET_SEPARATOR key_oplist); \ } \ @@ -1427,15 +1428,14 @@ , /* no OUT_SERIAL */ ) \ \ M_IF_METHOD_BOTH(IN_SERIAL, key_oplist, value_oplist)( \ - M_INLINE m_serial_return_code_t \ - M_F(name, _in_serial)(tree_t t1, m_serial_read_t f) \ + M_P(m_serial_return_code_t, name, _in_serial, tree_t t1, m_serial_read_t f) \ { \ M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \ M_ASSERT (f != NULL && f->m_interface != NULL); \ m_serial_local_t local; \ m_serial_return_code_t ret; \ size_t estimated_size = 0; \ - M_F(name,_reset)(t1); \ + M_F(name,_reset)M_R(t1); \ M_QLET(1, key, key_t, key_oplist) \ M_IF(isMap)(M_QLET(2, value, value_t, value_oplist) , /*nothing*/) { \ M_IF(isMap)( \ @@ -1448,7 +1448,7 @@ if (ret != M_SERIAL_OK_CONTINUE) break; \ ret = M_CALL_IN_SERIAL(value_oplist, value, f); \ if (ret != M_SERIAL_OK_DONE) break; \ - M_F(name, _set_at)(t1, key, value); \ + M_F(name, _set_at)M_R(t1, key, value); \ } while ((ret = f->m_interface->read_map_next(local, f)) == M_SERIAL_OK_CONTINUE); \ , /* queue style */ \ ret = f->m_interface->read_array_start(local, f, &estimated_size); \ @@ -1456,7 +1456,7 @@ do { \ ret = M_CALL_IN_SERIAL(key_oplist, key, f); \ if (ret != M_SERIAL_OK_DONE) break; \ - M_F(name, _push)(t1, key); \ + M_F(name, _push)M_R(t1, key); \ } while ((ret = f->m_interface->read_array_next(local, f)) == M_SERIAL_OK_CONTINUE); \ ) /* End of IF isMap */ \ } \ diff --git a/m-core.h b/m-core.h index d7b04d44..7e8166d4 100644 --- a/m-core.h +++ b/m-core.h @@ -412,33 +412,37 @@ M_BEGIN_PROTECTED_CODE #endif +// FIXME: Rename to M_USE_MEMORY_CONTEXT? #ifndef M_USE_POOL // Memory pool parameter not used for memory function. Stub it with 0 as it won't be used (global definition). # define M_P_EXPAND +# define M_P_EXPAND_void void # define M_R_EXPAND +# define M_R_EXPAND_void # define M_R # define M_ASSERT_POOL() #else // Memory pool parameter is used for function using memory. (local definition to the function). // Expand to a prototype to a function that may not trigger exception # define M_P_EXPAND M_USE_POOL m_pool, +# define M_P_EXPAND_void M_USE_POOL m_pool # define M_R_EXPAND m_pool , +# define M_R_EXPAND_void m_pool # define M_R(...) (m_pool, __VA_ARGS__) # define M_ASSERT_POOL() (void) m_pool #endif -// Expand to a prototype of a function that may trigger exception / accept memory context -// TODO: If not M_F, M_INLINE overloaded and no M_P_EXPAND, simplify M_P -// (faster build: 0.54s instead of 0.80s in extreme expanding +// M_P: Expand to a prototype of a function that may trigger exception / accept memory context +// M_N: Expand to a prototype of a function that may not trigger exception or accept memory context +// If not M_F, no overloaded M_INLINE and no M_P_EXPAND, simplify M_P +// (faster build: 0.54s instead of 0.80s in extreme expanding) +#if !defined(M_USE_POOL) && !defined(M_F) && !defined(M_USE_FINE_GRAINED_LINKAGE) && !defined(M_USE_DEF) && !defined(M_USE_DECL) +# define M_P(rettype, name, suffix, ...) static inline rettype name ## suffix(__VA_ARGS__) +# define M_N(rettype, name, suffix, ...) static inline rettype name ## suffix(__VA_ARGS__) +#else # define M_P(rettype, name, suffix, ...) M_INLINE rettype M_F(name, suffix)(M_P_EXPAND __VA_ARGS__) -//#define M_P(rettype, name, suffix, ...) static inline rettype name ## suffix(__VA_ARGS__) - -// Expand to a prototype of a function that may not trigger exception or accept memory context # define M_N(rettype, name, suffix, ...) M_INLINE rettype M_F(name, suffix)(__VA_ARGS__) - - -// TODO: Add for API special, the support of the POOL special keyword ==> m_pool -// Or document m_pool directly? Can still be overriden later. +#endif // TODO: Add for all Assertions: M_ASSERT_POOL() // to avoid warnings about unused parameter m_pool.