diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-11-02 04:12:36 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-11-02 04:12:36 +0000 |
commit | 629a5fc39b1ad8bc638106c1f23537e797b5bedc (patch) | |
tree | fc9d6f9fee325d65f5ac96235b6589850f41d3bc /include/asterisk/vector.h | |
parent | a84cff117d1f862a6b345f87d0ba1f158e5feecd (diff) |
vector: Update API to be more flexible.
Made the vector macro API be more like linked lists.
1) Added a name parameter to ast_vector() to name the vector struct.
2) Made the API take a pointer to the vector struct instead of the struct
itself.
3) Added an element cleanup macro/function parameter when removing an
element from the vector for ast_vector_remove_cmp_unordered() and
ast_vector_remove_elem_unordered().
4) Added ast_vector_get_addr() in case the vector element is not a simple
pointer.
* Converted an inline vector usage in stasis_message_router to use the
vector API. It needed the API improvements so it could be converted.
* Fixed topic reference leak in router_dtor() when the
stasis_message_router is destroyed.
* Fixed deadlock potential in stasis_forward_all() and
stasis_forward_cancel(). Locking two topics at the same time requires
deadlock avoidance.
* Made internal_stasis_subscribe() tolerant of a NULL topic.
* Made stasis_message_router_add(),
stasis_message_router_add_cache_update(), stasis_message_router_remove(),
and stasis_message_router_remove_cache_update() tolerant of a NULL
message_type.
* Promoted a LOG_DEBUG message to LOG_ERROR as intended in
dispatch_message().
Review: https://reviewboard.asterisk.org/r/2903/
........
Merged revisions 402429 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@402430 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'include/asterisk/vector.h')
-rw-r--r-- | include/asterisk/vector.h | 134 |
1 files changed, 86 insertions, 48 deletions
diff --git a/include/asterisk/vector.h b/include/asterisk/vector.h index f5d3e9a14..4efc5ce4f 100644 --- a/include/asterisk/vector.h +++ b/include/asterisk/vector.h @@ -33,9 +33,14 @@ * \since 12 */ -/*! \brief Define a vector structure */ -#define ast_vector(type) \ - struct { \ +/*! + * \brief Define a vector structure + * + * \param name Optional vector struct name. + * \param type Vector element type. + */ +#define ast_vector(name, type) \ + struct name { \ type *elems; \ size_t max; \ size_t current; \ @@ -55,15 +60,15 @@ */ #define ast_vector_init(vec, size) ({ \ size_t __size = (size); \ - size_t alloc_size = __size * sizeof(*(vec).elems); \ - (vec).elems = alloc_size ? ast_malloc(alloc_size) : NULL; \ - (vec).current = 0; \ - if ((vec).elems) { \ - (vec).max = __size; \ + size_t alloc_size = __size * sizeof(*((vec)->elems)); \ + (vec)->elems = alloc_size ? ast_malloc(alloc_size) : NULL; \ + (vec)->current = 0; \ + if ((vec)->elems) { \ + (vec)->max = __size; \ } else { \ - (vec).max = 0; \ + (vec)->max = 0; \ } \ - alloc_size == 0 || (vec).elems != NULL ? 0 : -1; \ + (alloc_size == 0 || (vec)->elems != NULL) ? 0 : -1; \ }) /*! @@ -75,10 +80,10 @@ * \param vec Vector to deallocate. */ #define ast_vector_free(vec) do { \ - ast_free((vec).elems); \ - (vec).elems = NULL; \ - (vec).max = 0; \ - (vec).current = 0; \ + ast_free((vec)->elems); \ + (vec)->elems = NULL; \ + (vec)->max = 0; \ + (vec)->current = 0; \ } while (0) /*! @@ -90,25 +95,24 @@ * \return 0 on success. * \return Non-zero on failure. */ -#define ast_vector_append(vec, elem) ({ \ - int res = 0; \ - \ - if ((vec).current + 1 > (vec).max) { \ - size_t new_max = (vec).max ? 2 * (vec).max : 1; \ - typeof((vec).elems) new_elems = ast_realloc( \ - (vec).elems, new_max * sizeof(*new_elems)); \ - if (new_elems) { \ - (vec).elems = new_elems; \ - (vec).max = new_max; \ - } else { \ - res = -1; \ - } \ - } \ - \ - if (res == 0) { \ - (vec).elems[(vec).current++] = (elem); \ - } \ - res; \ +#define ast_vector_append(vec, elem) ({ \ + int res = 0; \ + do { \ + if ((vec)->current + 1 > (vec)->max) { \ + size_t new_max = (vec)->max ? 2 * (vec)->max : 1; \ + typeof((vec)->elems) new_elems = ast_realloc( \ + (vec)->elems, new_max * sizeof(*new_elems)); \ + if (new_elems) { \ + (vec)->elems = new_elems; \ + (vec)->max = new_max; \ + } else { \ + res = -1; \ + break; \ + } \ + } \ + (vec)->elems[(vec)->current++] = (elem); \ + } while (0); \ + res; \ }) /*! @@ -122,11 +126,11 @@ * \return The element that was removed. */ #define ast_vector_remove_unordered(vec, idx) ({ \ - typeof((vec).elems[0]) res; \ + typeof((vec)->elems[0]) res; \ size_t __idx = (idx); \ - ast_assert(__idx < (vec).current); \ - res = (vec).elems[__idx]; \ - (vec).elems[__idx] = (vec).elems[--(vec).current]; \ + ast_assert(__idx < (vec)->current); \ + res = (vec)->elems[__idx]; \ + (vec)->elems[__idx] = (vec)->elems[--(vec)->current]; \ res; \ }) @@ -137,15 +141,18 @@ * \param vec Vector to remove from. * \param value Value to pass into comparator. * \param cmp Comparator function/macros (called as \c cmp(elem, value)) + * \param cleanup How to cleanup a removed element macro/function. + * * \return 0 if element was removed. * \return Non-zero if element was not in the vector. */ -#define ast_vector_remove_cmp_unordered(vec, value, cmp) ({ \ +#define ast_vector_remove_cmp_unordered(vec, value, cmp, cleanup) ({ \ int res = -1; \ size_t idx; \ typeof(value) __value = (value); \ - for (idx = 0; idx < (vec).current; ++idx) { \ - if (cmp((vec).elems[idx], __value)) { \ + for (idx = 0; idx < (vec)->current; ++idx) { \ + if (cmp((vec)->elems[idx], __value)) { \ + cleanup((vec)->elems[idx]); \ ast_vector_remove_unordered((vec), idx); \ res = 0; \ break; \ @@ -154,20 +161,39 @@ res; \ }) -/*! \brief Default comparator for ast_vector_remove_elem_unordered() */ -#define AST_VECTOR_DEFAULT_CMP(a, b) ((a) == (b)) +/*! + * \brief Default comparator for ast_vector_remove_elem_unordered() + * + * \param elem Element to compare against + * \param value Value to compare with the vector element. + * + * \return 0 if element does not match. + * \return Non-zero if element matches. + */ +#define AST_VECTOR_ELEM_DEFAULT_CMP(elem, value) ((elem) == (value)) + +/*! + * \brief Vector element cleanup that does nothing. + * + * \param elem Element to cleanup + * + * \return Nothing + */ +#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem) /*! * \brief Remove an element from a vector. * * \param vec Vector to remove from. * \param elem Element to remove + * \param cleanup How to cleanup a removed element macro/function. + * * \return 0 if element was removed. * \return Non-zero if element was not in the vector. */ -#define ast_vector_remove_elem_unordered(vec, elem) ({ \ - ast_vector_remove_cmp_unordered((vec), (elem), \ - AST_VECTOR_DEFAULT_CMP); \ +#define ast_vector_remove_elem_unordered(vec, elem, cleanup) ({ \ + ast_vector_remove_cmp_unordered((vec), (elem), \ + AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \ }) /*! @@ -176,7 +202,19 @@ * \param vec Vector to query. * \return Number of elements in the vector. */ -#define ast_vector_size(vec) (vec).current +#define ast_vector_size(vec) (vec)->current + +/*! + * \brief Get an address of element in a vector. + * + * \param vec Vector to query. + * \param idx Index of the element to get address of. + */ +#define ast_vector_get_addr(vec, idx) ({ \ + size_t __idx = (idx); \ + ast_assert(__idx < (vec)->current); \ + &(vec)->elems[__idx]; \ +}) /*! * \brief Get an element from a vector. @@ -186,8 +224,8 @@ */ #define ast_vector_get(vec, idx) ({ \ size_t __idx = (idx); \ - ast_assert(__idx < (vec).current); \ - (vec).elems[__idx]; \ + ast_assert(__idx < (vec)->current); \ + (vec)->elems[__idx]; \ }) #endif /* _ASTERISK_VECTOR_H */ |