<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>