Update comments

This commit is contained in:
Patrick Pelissier committed 2019-07-11 12:36:01 +02:00
1 parent f855e24b56
commit 1f18e788e6
1 file changed
+29 -5
+29 -5
View File
@@ -44,11 +44,12 @@
/********************************** INTERNAL ************************************/ /********************************** INTERNAL ************************************/
/* Default initial size of a bucket of items */
#ifndef DEQUEUI_DEFAULT_SIZE #ifndef DEQUEUI_DEFAULT_SIZE
#define DEQUEUI_DEFAULT_SIZE 8 #define DEQUEUI_DEFAULT_SIZE 8
#endif #endif
/* Define the internal contract of an deque */ /* Define the internal contract of a deque */
#define DEQUEI_CONTRACT(d) do { \ #define DEQUEI_CONTRACT(d) do { \
assert ((d) != NULL); \ assert ((d) != NULL); \
assert ((d)->default_size >= DEQUEUI_DEFAULT_SIZE); \ assert ((d)->default_size >= DEQUEUI_DEFAULT_SIZE); \
@@ -76,25 +77,41 @@
*/ */
#define DEQUEI_DEF_P2(name, type, oplist, deque_t, it_t, node_t) \ #define DEQUEI_DEF_P2(name, type, oplist, deque_t, it_t, node_t) \
\ \
/* It is a linked list of buckets of the types, \
each new created bucket size grows compared to the previous one \
resulting in: \
strict O(1) for push/pop \
O(ln(n)) for random access. \
No insert / delete operations are planned. \
[Could be done in O(n) complexity if needed] \
Define the bucket (aka node) structure. \
*/ \
typedef struct M_C(name, _node_s) { \ typedef struct M_C(name, _node_s) { \
ILIST_INTERFACE(M_C(name, _node_list), struct M_C(name, _node_s)); \ ILIST_INTERFACE(M_C(name, _node_list), struct M_C(name, _node_s)); \
size_t size; \ size_t size; \
type data[M_MIN_FLEX_ARRAY_SIZE]; \ type data[M_MIN_FLEX_ARRAY_SIZE]; \
} node_t; \ } node_t; \
\ \
/* Each node is allocated with a variable size (so we use \ /* Each node is allocated with a variable size bucket (so we use \
M_GET_REALLOC for the allocation). But we need to delete the nodes \ M_GET_REALLOC for the allocation). But we want to delete the nodes \
automatically with the intrusive list used for storing the nodes: \ automatically with the intrusive list used for storing the nodes: \
so we register as a DEL operator the FREE operator of the oplist. \ so we register as a DEL operator the FREE operator of the oplist. \
The interfaces are compatible. \ The interfaces are compatible. \
*/ \ */ \
ILIST_DEF(M_C(name, _node_list), node_t, (DEL(M_GET_FREE oplist)) ) \ ILIST_DEF(M_C(name, _node_list), node_t, (DEL(M_GET_FREE oplist)) ) \
\ \
/* Define an internal iterator */ \
typedef struct M_C(name, _it2_s) { \ typedef struct M_C(name, _it2_s) { \
node_t *node; \ node_t *node; \
size_t index; \ size_t index; \
} M_C(name, _it2_t)[1]; \ } M_C(name, _it2_t)[1]; \
\ \
/* Define the deque type: \
- 'list' if the list of buckets containing the objects. \
- 'front' and 'back' are iterators to the first and last elements. \
- 'default_size' is the size used for the creation of a new bucket \
- 'count' is the number of elements in the container. \
*/ \
typedef struct M_C(name, _s) { \ typedef struct M_C(name, _s) { \
M_C(name, _node_list_t) list; \ M_C(name, _node_list_t) list; \
M_C(name, _it2_t) front; \ M_C(name, _it2_t) front; \
@@ -102,6 +119,7 @@
size_t default_size; \ size_t default_size; \
size_t count; \ size_t count; \
} deque_t[1]; \ } deque_t[1]; \
\
typedef struct M_C(name, _s) *M_C(name, _ptr); \ typedef struct M_C(name, _s) *M_C(name, _ptr); \
typedef const struct M_C(name, _s) *M_C(name, _srcptr); \ typedef const struct M_C(name, _s) *M_C(name, _srcptr); \
\ \
@@ -117,19 +135,23 @@
M_C(name, _int_new_node)(deque_t d) \ M_C(name, _int_new_node)(deque_t d) \
{ \ { \
size_t def = d->default_size; \ 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)))) { \ 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)); \ M_MEMORY_FULL(sizeof(M_C(name, _node_t))+def * sizeof(type)); \
return NULL; \ return NULL; \
} \ } \
/* Alloc a new node */ \
M_C(name, _node_t)*n = (M_C(name, _node_t)*) (void*) \ M_C(name, _node_t)*n = (M_C(name, _node_t)*) (void*) \
M_CALL_REALLOC(oplist, char, NULL, \ M_CALL_REALLOC(oplist, char, NULL, \
sizeof(M_C(name, _node_t)) + def * sizeof(type) ); \ sizeof(M_C(name, _node_t)) + def * sizeof(type) ); \
if (n==NULL) { \ if (n==NULL) { \
M_MEMORY_FULL(sizeof(M_C(name, _node_t))+def * sizeof(type)); \ M_MEMORY_FULL(sizeof(M_C(name, _node_t))+def * sizeof(type)); \
return NULL; \ return NULL; \
} \ } \
/* Initialize the node */ \
n->size = def; \ n->size = def; \
M_C(name, _node_list_init_field)(n); \ M_C(name, _node_list_init_field)(n); \
/* Increase the next bucket allocation */ \
/* Do not increase it too much if there are few items */ \ /* Do not increase it too much if there are few items */ \
def = M_MIN(def, d->count); \ def = M_MIN(def, d->count); \
d->default_size = M_CALL_INC_ALLOC(oplist, def); \ d->default_size = M_CALL_INC_ALLOC(oplist, def); \
@@ -197,8 +219,10 @@
M_C(name, _node_t) *n = d->back->node; \ M_C(name, _node_t) *n = d->back->node; \
size_t index = d->back->index; \ size_t index = d->back->index; \
if (M_UNLIKELY (n->size <= index)) { \ if (M_UNLIKELY (n->size <= index)) { \
/* try to get an already allocated node */ \
n = M_C(name, _node_list_next_obj)(d->list, n); \ n = M_C(name, _node_list_next_obj)(d->list, n); \
if (n == NULL) { \ if (n == NULL) { \
/* No node exists, allocate a new one */ \
n = M_C(name, _int_new_node)(d); \ n = M_C(name, _int_new_node)(d); \
if (M_UNLIKELY (n == NULL)) return NULL; \ if (M_UNLIKELY (n == NULL)) return NULL; \
M_C(name, _node_list_push_back)(d->list, n); \ M_C(name, _node_list_push_back)(d->list, n); \