this makes it a bit friendlier to use, as the user will not have to call qb_array_grow().
Signed-off-by: Angus Salkeld asalkeld@redhat.com --- examples/ipcserver.c | 6 +----- include/qb/qbarray.h | 23 +++++++++++++++++++++++ lib/array.c | 26 +++++++++++++++++++++++++- lib/log_dcs.c | 8 ++------ 4 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/examples/ipcserver.c b/examples/ipcserver.c index 4a51121..21d5013 100644 --- a/examples/ipcserver.c +++ b/examples/ipcserver.c @@ -173,10 +173,6 @@ my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts, GIOChannel *channel; int32_t res = 0;
- res = qb_array_grow(gio_map, fd + 1); - if (res < 0) { - return res; - } res = qb_array_index(gio_map, fd, (void**)&adaptor); if (res < 0) { return res; @@ -320,7 +316,7 @@ main(int32_t argc, char *argv[]) } else { #ifdef HAVE_GLIB glib_loop = g_main_loop_new(NULL, FALSE); - gio_map = qb_array_create(64, sizeof(struct gio_to_qb_poll)); + gio_map = qb_array_create_2(64, sizeof(struct gio_to_qb_poll), 1); qb_ipcs_poll_handlers_set(s1, &glib_ph); qb_ipcs_run(s1); g_main_loop_run(glib_loop); diff --git a/include/qb/qbarray.h b/include/qb/qbarray.h index 99069a5..b969fd3 100644 --- a/include/qb/qbarray.h +++ b/include/qb/qbarray.h @@ -36,6 +36,16 @@ extern "C" { /** * @file qbarray.h * This is a dynamic array (it can grow, but without moving memory). + * + * @code + * arr = qb_array_create_2(64, sizeof(struct my_struct), 256); + * ... + * res = qb_array_index(arr, idx, (void**)&my_ptr); + * if (res < 0) { + * return res; + * } + * // use my_ptr, now even if there is a grow, this pointer will be valid. + * @endcode */
struct qb_array; @@ -55,6 +65,19 @@ typedef struct qb_array qb_array_t; qb_array_t* qb_array_create(size_t max_elements, size_t element_size);
/** + * Create an array with fixed sized elements. + * + * @param max_elements initial max elements. + * @param element_size size of each element. + * @param autogrow_elements the number of elements to grow automatically by. + * + * @return array instance. + */ +qb_array_t* qb_array_create_2(size_t max_elements, size_t element_size, + size_t autogrow_elements); + + +/** * Get an element at a particular index. * @param a array instance. * @param idx the index diff --git a/lib/array.c b/lib/array.c index 96a7f43..a3a1e5c 100644 --- a/lib/array.c +++ b/lib/array.c @@ -33,11 +33,19 @@ struct qb_array { size_t max_elements; size_t element_size; size_t num_bins; + size_t autogrow_elements; };
qb_array_t * qb_array_create(size_t max_elements, size_t element_size) { + return qb_array_create_2(max_elements, element_size, 0); +} + +qb_array_t * +qb_array_create_2(size_t max_elements, size_t element_size, + size_t autogrow_elements) +{ int32_t i; struct qb_array *a = NULL;
@@ -49,6 +57,10 @@ qb_array_create(size_t max_elements, size_t element_size) errno = -EINVAL; return NULL; } + if (autogrow_elements > MAX_BIN_ELEMENTS) { + errno = -EINVAL; + return NULL; + } a = calloc(1, sizeof(struct qb_array)); if (a == NULL) { return NULL; @@ -56,6 +68,7 @@ qb_array_create(size_t max_elements, size_t element_size) a->element_size = element_size; a->max_elements = max_elements; a->num_bins = QB_MIN((max_elements / MAX_BIN_ELEMENTS) + 1, MAX_BINS); + a->autogrow_elements = autogrow_elements;
for (i = 0; i < MAX_BINS; i++) { if (i < a->num_bins) { @@ -77,9 +90,20 @@ qb_array_index(struct qb_array * a, int32_t idx, void **element_out) if (a == NULL || element_out == NULL) { return -EINVAL; } - if (idx >= a->max_elements || idx < 0) { + if (idx < 0) { return -ERANGE; } + if (idx >= a->max_elements) { + elem = idx + a->autogrow_elements; + if (a->autogrow_elements == 0) { + return -ERANGE; + } else { + int32_t rc = qb_array_grow(a, elem); + if (rc != 0) { + return rc; + } + } + } b = BIN_NUM_GET(idx); assert(b < a->num_bins); elem = ELEM_NUM_GET(idx); diff --git a/lib/log_dcs.c b/lib/log_dcs.c index 64a8bc4..c5022a5 100644 --- a/lib/log_dcs.c +++ b/lib/log_dcs.c @@ -78,8 +78,6 @@ _log_dcs_new_cs(const char *function, int32_t call_register = QB_FALSE;
if (qb_array_index(callsite_arr, callsite_arr_next, (void **)&cs) < 0) { - rc = qb_array_grow(callsite_arr, callsite_arr_next + 255); - assert(rc == 0); rc = qb_array_index(callsite_arr, callsite_arr_next, (void **)&cs); assert(rc == 0); @@ -128,8 +126,6 @@ qb_log_dcs_get(int32_t * newly_created, */ (void)qb_thread_lock(arr_next_lock); if (rc < 0) { - rc = qb_array_grow(lookup_arr, lineno + 255); - assert(rc == 0); rc = qb_array_index(lookup_arr, lineno, (void **)&csl_head); assert(rc == 0); } @@ -171,8 +167,8 @@ cleanup: void qb_log_dcs_init(void) { - lookup_arr = qb_array_create(256, sizeof(struct callsite_list)); - callsite_arr = qb_array_create(256, sizeof(struct qb_log_callsite)); + lookup_arr = qb_array_create_2(256, sizeof(struct callsite_list), 256); + callsite_arr = qb_array_create_2(256, sizeof(struct qb_log_callsite), 256);
arr_next_lock = qb_thread_lock_create(QB_THREAD_LOCK_SHORT);
quarterback-devel@lists.fedorahosted.org