From 02ee296f81d67ce70a30733ef619703f2f9d3e66 Mon Sep 17 00:00:00 2001 From: Corey Farrell Date: Mon, 25 Dec 2017 20:32:53 -0500 Subject: optional_api: Refactor to use vector's and standard allocators. * Replace ad-hoc array management with macro's from vector.h. * Remove redundent logger messages. * Use normal Asterisk allocators instead of directly using libc allocators. * Free memory when an API has no implementation or users. Change-Id: Ic6ecb31798d4a78e7df39ece86a68b60eac05bf5 --- main/optional_api.c | 172 ++++++++++++++-------------------------------------- 1 file changed, 47 insertions(+), 125 deletions(-) (limited to 'main') diff --git a/main/optional_api.c b/main/optional_api.c index 9b9a1a07c..d63129cdd 100644 --- a/main/optional_api.c +++ b/main/optional_api.c @@ -20,6 +20,7 @@ #include "asterisk/optional_api.h" #include "asterisk/utils.h" +#include "asterisk/vector.h" #if defined(OPTIONAL_API) @@ -56,16 +57,18 @@ struct optional_api_user { struct optional_api { /*! Pointer to the implementation function; could be null */ ast_optional_fn impl; - /*! Variable length array of users of this API */ - struct optional_api_user **users; - /*! Allocated size of the \a users array */ - size_t users_maxlen; - /*! Number of entries in the \a users array */ - size_t users_len; + /*! Users of the API */ + AST_VECTOR(, struct optional_api_user *) users; /*! Name of the optional API function */ char symname[]; }; +/*! Vector of \ref optional_api functions */ +AST_VECTOR(, struct optional_api *) apis; + +#define USER_OPTIONAL_REF_CMP(ele, value) (ele->optional_ref == value) +#define OPTIONAL_API_SYMNAME_CMP(ele, value) (!strcmp(ele->symname, value)) + /*! * \brief Free an \ref optional_api_user. * @@ -74,7 +77,7 @@ struct optional_api { static void optional_api_user_destroy(struct optional_api_user *user) { *user->optional_ref = user->stub; - ast_std_free(user); + ast_free(user); } /*! @@ -93,8 +96,10 @@ static struct optional_api_user *optional_api_user_create( struct optional_api_user *user; size_t size = sizeof(*user) + strlen(module) + 1; - user = ast_std_calloc(1, size); + user = ast_calloc(1, size); if (!user) { + ast_do_crash(); + return NULL; } @@ -112,17 +117,15 @@ static struct optional_api_user *optional_api_user_create( */ static void optional_api_destroy(struct optional_api *api) { - while (api->users_len--) { - optional_api_user_destroy(api->users[api->users_len]); - } - ast_std_free(api->users); - api->users = NULL; - api->users_maxlen = 0; - ast_std_free(api); + AST_VECTOR_REMOVE_CMP_UNORDERED(&apis, api, + AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_ELEM_CLEANUP_NOOP); + AST_VECTOR_CALLBACK_VOID(&api->users, optional_api_user_destroy); + AST_VECTOR_FREE(&api->users); + ast_free(api); } /*! - * \brief Create an \ref optional_api. + * \brief Create and link an \ref optional_api. * * \param symname Name of the optional function. * \return New \ref optional_api. @@ -131,12 +134,12 @@ static void optional_api_destroy(struct optional_api *api) static struct optional_api *optional_api_create(const char *symname) { struct optional_api *api; - size_t size; - size = sizeof(*api) + strlen(symname) + 1; - api = ast_std_calloc(1, size); - if (!api) { - ast_log(LOG_ERROR, "Failed to allocate api\n"); + api = ast_calloc(1, sizeof(*api) + strlen(symname) + 1); + if (!api || AST_VECTOR_APPEND(&apis, api)) { + ast_free(api); + ast_do_crash(); + return NULL; } @@ -145,16 +148,6 @@ static struct optional_api *optional_api_create(const char *symname) return api; } -/*! Array of \ref optional_api functions */ -struct { - /*! Variable length array of API's */ - struct optional_api **list; - /*! Allocated size of the \a list array */ - size_t maxlen; - /*! Number of entries in the \a list array */ - size_t len; -} apis; - /*! * \brief Gets (or creates) the \ref optional_api for the given function. * @@ -164,43 +157,16 @@ struct { */ static struct optional_api *get_api(const char *symname) { - struct optional_api *api; - size_t i; + struct optional_api **api; /* Find one, if we already have it */ - if (apis.list) { - for (i = 0; i < apis.len; ++i) { - if (strcmp(symname, apis.list[i]->symname) == 0) { - return apis.list[i]; - } - } + api = AST_VECTOR_GET_CMP(&apis, symname, OPTIONAL_API_SYMNAME_CMP); + if (api) { + return *api; } /* API not found. Build one */ - api = optional_api_create(symname); - if (!api) { - return NULL; - } - - /* Grow the list, if needed */ - if (apis.len + 1 > apis.maxlen) { - size_t new_maxlen = apis.maxlen ? 2 * apis.maxlen : 1; - struct optional_api **new_list; - - new_list = ast_std_realloc(apis.list, new_maxlen * sizeof(*new_list)); - if (!new_list) { - optional_api_destroy(api); - ast_log(LOG_ERROR, "Failed to allocate api list\n"); - return NULL; - } - - apis.maxlen = new_maxlen; - apis.list = new_list; - } - - apis.list[apis.len++] = api; - - return api; + return optional_api_create(symname); } /*! @@ -232,13 +198,14 @@ static void optional_api_user_relink(struct optional_api_user *user, static void optional_api_set_impl(struct optional_api *api, ast_optional_fn impl) { - size_t i; - api->impl = impl; /* re-link all users */ - for (i = 0; i < api->users_len; ++i) { - optional_api_user_relink(api->users[i], api); + if (AST_VECTOR_SIZE(&api->users)) { + AST_VECTOR_CALLBACK_VOID(&api->users, optional_api_user_relink, api); + } else if (!impl) { + /* No users or impl means we should delete this api. */ + optional_api_destroy(api); } } @@ -247,13 +214,9 @@ void ast_optional_api_provide(const char *symname, ast_optional_fn impl) struct optional_api *api; api = get_api(symname); - if (!api) { - ast_log(LOG_ERROR, "%s: Allocation failed\n", symname); - ast_do_crash(); - return; + if (api) { + optional_api_set_impl(api, impl); } - - optional_api_set_impl(api, impl); } void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl) @@ -261,13 +224,9 @@ void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl) struct optional_api *api; api = get_api(symname); - if (!api) { - ast_log(LOG_ERROR, "%s: Could not find api\n", symname); - ast_do_crash(); - return; + if (api) { + optional_api_set_impl(api, 0); } - - optional_api_set_impl(api, 0); } void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref, @@ -276,73 +235,36 @@ void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref, struct optional_api_user *user; struct optional_api *api; - api = get_api(symname); if (!api) { - ast_log(LOG_ERROR, "%s: Allocation failed\n", symname); - ast_do_crash(); return; } user = optional_api_user_create(optional_ref, stub, module); if (!user) { - ast_log(LOG_ERROR, "%s: Allocation failed\n", symname); - ast_do_crash(); return; } /* Add user to the API */ - if (api->users_len + 1 > api->users_maxlen) { - size_t new_maxlen = api->users_maxlen ? 2 * api->users_maxlen : 1; - struct optional_api_user **new_list; - - new_list = ast_std_realloc(api->users, new_maxlen * sizeof(*new_list)); - if (!new_list) { - optional_api_user_destroy(user); - ast_log(LOG_ERROR, "Failed to allocate api list\n"); - ast_do_crash(); - return; - } - - api->users_maxlen = new_maxlen; - api->users = new_list; + if (!AST_VECTOR_APPEND(&api->users, user)) { + optional_api_user_relink(user, api); + } else { + optional_api_user_destroy(user); + ast_do_crash(); } - - api->users[api->users_len++] = user; - - optional_api_user_relink(user, api); } void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref, const char *module) { struct optional_api *api; - size_t i; api = get_api(symname); - if (!api) { - ast_log(LOG_ERROR, "%s: Could not find api\n", symname); - ast_do_crash(); - return; - } - - for (i = 0; i < api->users_len; ++i) { - struct optional_api_user *user = api->users[i]; - - if (user->optional_ref == optional_ref) { - if (*user->optional_ref != user->stub) { - *user->optional_ref = user->stub; - } - - /* Remove from the list */ - api->users[i] = api->users[--api->users_len]; - - optional_api_user_destroy(user); - return; + if (api) { + AST_VECTOR_REMOVE_CMP_UNORDERED(&api->users, optional_ref, USER_OPTIONAL_REF_CMP, optional_api_user_destroy); + if (!api->impl && !AST_VECTOR_SIZE(&api->users)) { + optional_api_destroy(api); } } - - ast_log(LOG_ERROR, "%s: Could not find user %s\n", symname, module); } - #endif /* defined(OPTIONAL_API) */ -- cgit v1.2.3