<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/8203">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">optional_api: Refactor to use vector's and standard allocators.<br><br>* Replace ad-hoc array management with macro's from vector.h.<br>* Remove redundent logger messages.<br>* Use normal Asterisk allocators instead of directly using libc<br> allocators.<br>* Free memory when an API has no implementation or users.<br><br>Change-Id: Ic6ecb31798d4a78e7df39ece86a68b60eac05bf5<br>---<br>M main/optional_api.c<br>1 file changed, 46 insertions(+), 124 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/03/8203/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/main/optional_api.c b/main/optional_api.c<br>index 9b9a1a0..81c0d65 100644<br>--- a/main/optional_api.c<br>+++ b/main/optional_api.c<br>@@ -20,6 +20,7 @@<br> <br> #include "asterisk/optional_api.h"<br> #include "asterisk/utils.h"<br>+#include "asterisk/vector.h"<br> <br> #if defined(OPTIONAL_API)<br> <br>@@ -56,15 +57,17 @@<br> struct optional_api {<br> /*! Pointer to the implementation function; could be null */<br> ast_optional_fn impl;<br>- /*! Variable length array of users of this API */<br>- struct optional_api_user **users;<br>- /*! Allocated size of the \a users array */<br>- size_t users_maxlen;<br>- /*! Number of entries in the \a users array */<br>- size_t users_len;<br>+ /*! Users of the API */<br>+ AST_VECTOR(, struct optional_api_user *) users;<br> /*! Name of the optional API function */<br> char symname[];<br> };<br>+<br>+/*! Vector of \ref optional_api functions */<br>+AST_VECTOR(, struct optional_api *) apis;<br>+<br>+#define USER_OPTIONAL_REF_CMP(ele, value) (ele->optional_ref == value)<br>+#define OPTIONAL_API_SYMNAME_CMP(ele, value) (!strcmp(ele->symname, value))<br> <br> /*!<br> * \brief Free an \ref optional_api_user.<br>@@ -74,7 +77,7 @@<br> static void optional_api_user_destroy(struct optional_api_user *user)<br> {<br> *user->optional_ref = user->stub;<br>- ast_std_free(user);<br>+ ast_free(user);<br> }<br> <br> /*!<br>@@ -93,8 +96,10 @@<br> struct optional_api_user *user;<br> size_t size = sizeof(*user) + strlen(module) + 1;<br> <br>- user = ast_std_calloc(1, size);<br>+ user = ast_calloc(1, size);<br> if (!user) {<br>+ ast_do_crash();<br>+<br> return NULL;<br> }<br> <br>@@ -112,17 +117,15 @@<br> */<br> static void optional_api_destroy(struct optional_api *api)<br> {<br>- while (api->users_len--) {<br>- optional_api_user_destroy(api->users[api->users_len]);<br>- }<br>- ast_std_free(api->users);<br>- api->users = NULL;<br>- api->users_maxlen = 0;<br>- ast_std_free(api);<br>+ AST_VECTOR_REMOVE_CMP_UNORDERED(&apis, api,<br>+ AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_ELEM_CLEANUP_NOOP);<br>+ AST_VECTOR_CALLBACK_VOID(&api->users, optional_api_user_destroy);<br>+ AST_VECTOR_FREE(&api->users);<br>+ ast_free(api);<br> }<br> <br> /*!<br>- * \brief Create an \ref optional_api.<br>+ * \brief Create and link an \ref optional_api.<br> *<br> * \param symname Name of the optional function.<br> * \return New \ref optional_api.<br>@@ -131,12 +134,12 @@<br> static struct optional_api *optional_api_create(const char *symname)<br> {<br> struct optional_api *api;<br>- size_t size;<br> <br>- size = sizeof(*api) + strlen(symname) + 1;<br>- api = ast_std_calloc(1, size);<br>- if (!api) {<br>- ast_log(LOG_ERROR, "Failed to allocate api\n");<br>+ api = ast_calloc(1, sizeof(*api) + strlen(symname) + 1);<br>+ if (!api || AST_VECTOR_APPEND(&apis, api)) {<br>+ ast_free(api);<br>+ ast_do_crash();<br>+<br> return NULL;<br> }<br> <br>@@ -144,16 +147,6 @@<br> <br> return api;<br> }<br>-<br>-/*! Array of \ref optional_api functions */<br>-struct {<br>- /*! Variable length array of API's */<br>- struct optional_api **list;<br>- /*! Allocated size of the \a list array */<br>- size_t maxlen;<br>- /*! Number of entries in the \a list array */<br>- size_t len;<br>-} apis;<br> <br> /*!<br> * \brief Gets (or creates) the \ref optional_api for the given function.<br>@@ -165,42 +158,15 @@<br> static struct optional_api *get_api(const char *symname)<br> {<br> struct optional_api *api;<br>- size_t i;<br> <br> /* Find one, if we already have it */<br>- if (apis.list) {<br>- for (i = 0; i < apis.len; ++i) {<br>- if (strcmp(symname, apis.list[i]->symname) == 0) {<br>- return apis.list[i];<br>- }<br>- }<br>+ api = AST_VECTOR_GET_CMP(&apis, symname, OPTIONAL_API_SYMNAME_CMP);<br>+ if (api) {<br>+ return api;<br> }<br> <br> /* API not found. Build one */<br>- api = optional_api_create(symname);<br>- if (!api) {<br>- return NULL;<br>- }<br>-<br>- /* Grow the list, if needed */<br>- if (apis.len + 1 > apis.maxlen) {<br>- size_t new_maxlen = apis.maxlen ? 2 * apis.maxlen : 1;<br>- struct optional_api **new_list;<br>-<br>- new_list = ast_std_realloc(apis.list, new_maxlen * sizeof(*new_list));<br>- if (!new_list) {<br>- optional_api_destroy(api);<br>- ast_log(LOG_ERROR, "Failed to allocate api list\n");<br>- return NULL;<br>- }<br>-<br>- apis.maxlen = new_maxlen;<br>- apis.list = new_list;<br>- }<br>-<br>- apis.list[apis.len++] = api;<br>-<br>- return api;<br>+ return optional_api_create(symname);<br> }<br> <br> /*!<br>@@ -232,13 +198,14 @@<br> static void optional_api_set_impl(struct optional_api *api,<br> ast_optional_fn impl)<br> {<br>- size_t i;<br>-<br> api->impl = impl;<br> <br> /* re-link all users */<br>- for (i = 0; i < api->users_len; ++i) {<br>- optional_api_user_relink(api->users[i], api);<br>+ if (AST_VECTOR_SIZE(&api->users)) {<br>+ AST_VECTOR_CALLBACK_VOID(&api->users, optional_api_user_relink, api);<br>+ } else if (!impl) {<br>+ /* No users or impl means we should delete this api. */<br>+ optional_api_destroy(api);<br> }<br> }<br> <br>@@ -247,13 +214,9 @@<br> struct optional_api *api;<br> <br> api = get_api(symname);<br>- if (!api) {<br>- ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);<br>- ast_do_crash();<br>- return;<br>+ if (api) {<br>+ optional_api_set_impl(api, impl);<br> }<br>-<br>- optional_api_set_impl(api, impl);<br> }<br> <br> void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl)<br>@@ -261,13 +224,9 @@<br> struct optional_api *api;<br> <br> api = get_api(symname);<br>- if (!api) {<br>- ast_log(LOG_ERROR, "%s: Could not find api\n", symname);<br>- ast_do_crash();<br>- return;<br>+ if (api) {<br>+ optional_api_set_impl(api, 0);<br> }<br>-<br>- optional_api_set_impl(api, 0);<br> }<br> <br> void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref,<br>@@ -276,73 +235,36 @@<br> struct optional_api_user *user;<br> struct optional_api *api;<br> <br>-<br> api = get_api(symname);<br> if (!api) {<br>- ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);<br>- ast_do_crash();<br> return;<br> }<br> <br> user = optional_api_user_create(optional_ref, stub, module);<br> if (!user) {<br>- ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);<br>- ast_do_crash();<br> return;<br> }<br> <br> /* Add user to the API */<br>- if (api->users_len + 1 > api->users_maxlen) {<br>- size_t new_maxlen = api->users_maxlen ? 2 * api->users_maxlen : 1;<br>- struct optional_api_user **new_list;<br>-<br>- new_list = ast_std_realloc(api->users, new_maxlen * sizeof(*new_list));<br>- if (!new_list) {<br>- optional_api_user_destroy(user);<br>- ast_log(LOG_ERROR, "Failed to allocate api list\n");<br>- ast_do_crash();<br>- return;<br>- }<br>-<br>- api->users_maxlen = new_maxlen;<br>- api->users = new_list;<br>+ if (!AST_VECTOR_APPEND(&api->users, user)) {<br>+ optional_api_user_relink(user, api);<br>+ } else {<br>+ optional_api_user_destroy(user);<br>+ ast_do_crash();<br> }<br>-<br>- api->users[api->users_len++] = user;<br>-<br>- optional_api_user_relink(user, api);<br> }<br> <br> void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref,<br> const char *module)<br> {<br> struct optional_api *api;<br>- size_t i;<br> <br> api = get_api(symname);<br>- if (!api) {<br>- ast_log(LOG_ERROR, "%s: Could not find api\n", symname);<br>- ast_do_crash();<br>- return;<br>- }<br>-<br>- for (i = 0; i < api->users_len; ++i) {<br>- struct optional_api_user *user = api->users[i];<br>-<br>- if (user->optional_ref == optional_ref) {<br>- if (*user->optional_ref != user->stub) {<br>- *user->optional_ref = user->stub;<br>- }<br>-<br>- /* Remove from the list */<br>- api->users[i] = api->users[--api->users_len];<br>-<br>- optional_api_user_destroy(user);<br>- return;<br>+ if (api) {<br>+ AST_VECTOR_REMOVE_CMP_UNORDERED(&api->users, optional_ref, USER_OPTIONAL_REF_CMP, optional_api_user_destroy);<br>+ if (!api->impl && !AST_VECTOR_SIZE(&api->users)) {<br>+ optional_api_destroy(api);<br> }<br> }<br>-<br>- ast_log(LOG_ERROR, "%s: Could not find user %s\n", symname, module);<br> }<br>-<br> #endif /* defined(OPTIONAL_API) */<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/8203">change 8203</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/8203"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ic6ecb31798d4a78e7df39ece86a68b60eac05bf5 </div>
<div style="display:none"> Gerrit-Change-Number: 8203 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>