[vlc-devel] [PATCH] modules: split module sorting from probing
Steve Lhomme
robux4 at ycbcr.xyz
Mon Jul 20 09:52:33 CEST 2020
Looks OK. Tested successfully on Windows (without a plugins.dat).
On 2020-07-18 9:47, RĂ©mi Denis-Courmont wrote:
> This adds a separate function to determine the order in which modules
> should be probed. The vlc_module_load() function now only does the
> probing.
> ---
> src/modules/modules.c | 190 ++++++++++++++++++++++++++----------------
> 1 file changed, 117 insertions(+), 73 deletions(-)
>
> diff --git a/src/modules/modules.c b/src/modules/modules.c
> index 700f1ca36b..702931f978 100644
> --- a/src/modules/modules.c
> +++ b/src/modules/modules.c
> @@ -94,10 +94,6 @@ const char *module_gettext (const module_t *m, const char *str)
>
> static bool module_match_name(const module_t *m, const char *name, size_t len)
> {
> - /* Plugins with zero score must be matched explicitly. */
> - if (len == 3 && strncasecmp("any", name, len) == 0)
> - return m->i_score > 0;
> -
> for (size_t i = 0; i < m->i_shortcuts; i++)
> if (strncasecmp(m->pp_shortcuts[i], name, len) == 0
> && m->pp_shortcuts[i][len] == '\0')
> @@ -106,6 +102,100 @@ static bool module_match_name(const module_t *m, const char *name, size_t len)
> return false;
> }
>
> +/**
> + * Finds the candidate modules for given criteria.
> + *
> + * All candidates modules having the specified capability and name will be
> + * sorted in decreasing order of priority and returned in a heap-allocated
> + * table.
> + *
> + * \param capability capability, i.e. class of module
> + * \param names string of comma-separated requested module shortcut names
> + * \param strict whether to exclude modules with no unmatching shortcut names
> + * \param modules storage location for the base address of a sorted table
> + * of candidate modules [OUT]
> + * \param strict_matches storage location for the count of strictly matched
> + * modules (optional) [OUT]
> + * \return number of modules found or a strictly negative value on error
> + */
> +static
> +ssize_t vlc_module_match(const char *capability, const char *names,
> + bool strict, module_t ***restrict modules,
> + size_t *restrict strict_matches)
> +{
> + module_t *const *tab;
> + size_t total = module_list_cap(&tab, capability);
> + module_t **unsorted = malloc(total * sizeof (*unsorted));
> + module_t **sorted = malloc(total * sizeof (*sorted));
> + size_t matches = 0;
> +
> + *modules = sorted;
> +
> + if (total > 0) {
> + if (unlikely(unsorted == NULL || sorted == NULL)) {
> + free(unsorted);
> + free(sorted);
> + return -1;
> + }
> + memcpy(unsorted, tab, total * sizeof (*unsorted));
> + }
> +
> + /* Go through the list of module shortcut names. */
> + while (names[0] != '\0') {
> + const char *shortcut = names;
> + size_t slen = strcspn(names, ",");
> +
> + names += slen;
> + names += strspn(names, ",");
> +
> + /* "none" matches nothing and ends the search */
> + if (slen == 4 && strncasecmp("none", shortcut, 4) == 0) {
> + total = 0;
> + break;
> + }
> +
> + /* "any" matches everything with strictly positive score */
> + if (slen == 3 && strncasecmp("any", shortcut, 3) == 0) {
> + strict = false;
> + break;
> + }
> +
> + for (size_t i = 0; i < total; i++) {
> + module_t *cand = unsorted[i];
> +
> + if (cand != NULL && module_match_name(cand, shortcut, slen)) {
> + assert(matches < total);
> + sorted[matches++] = cand;
> + unsorted[i] = NULL;
> + }
> + }
> + }
> +
> + if (strict_matches != NULL)
> + *strict_matches = matches;
> +
> + if (!strict) {
> + /* List remaining modules with strictly positive score. */
> + for (size_t i = 0; i < total; i++) {
> + module_t *cand = unsorted[i];
> +
> + if (cand != NULL) {
> + /* Modules are sorted by decreasing score, so there is no point
> + * carrying on after the first zero score is found.
> + */
> + if (module_get_score(cand) <= 0)
> + break;
> +
> + assert(matches < total);
> + sorted[matches++] = cand;
> + }
> + }
> + }
> +
> + free(unsorted);
> + return matches;
> +}
> +
> static int module_load(vlc_logger_t *log, module_t *m,
> vlc_activate_t init, bool forced, va_list args)
> {
> @@ -154,89 +244,43 @@ module_t *(vlc_module_load)(struct vlc_logger *log, const char *capability,
> name = "any";
>
> /* Find matching modules */
> - module_t *const *tab;
> - size_t total = module_list_cap(&tab, capability);
> -
> - vlc_debug(log, "looking for %s module matching \"%s\": %zu candidates",
> - capability, name, total);
> - if (total == 0)
> - {
> - vlc_debug(log, "no %s modules", capability);
> - return NULL;
> - }
> + module_t **mods;
> + size_t strict_total;
> + ssize_t total = vlc_module_match(capability, name, strict,
> + &mods, &strict_total);
>
> - module_t **mods = malloc(total * sizeof (*mods));
> - if (unlikely(mods == NULL))
> + if (unlikely(total < 0))
> return NULL;
>
> - memcpy(mods, tab, total * sizeof (*mods));
> + vlc_debug(log, "looking for %s module matching \"%s\": %zd candidates",
> + capability, name, total);
>
> module_t *module = NULL;
> va_list args;
>
> va_start(args, probe);
> - while (*name)
> - {
> - const char *shortcut = name;
> - size_t slen = strcspn (name, ",");
> -
> - name += slen;
> - name += strspn (name, ",");
> -
> - if (!strcasecmp ("none", shortcut))
> - goto done;
>
> - bool force = strict && strcasecmp ("any", shortcut);
> - for (size_t i = 0; i < total; i++)
> - {
> - module_t *cand = mods[i];
> - if (cand == NULL)
> - continue; // module failed in previous iteration
> - if (!module_match_name(cand, shortcut, slen))
> - continue;
> - mods[i] = NULL; // only try each module once at most...
> -
> - int ret = module_load(log, cand, probe, force, args);
> - switch (ret)
> - {
> - case VLC_SUCCESS:
> - module = cand;
> - /* fall through */
> - case VLC_ETIMEOUT:
> - goto done;
> - }
> + for (size_t i = 0; i < (size_t)total; i++) {
> + module_t *cand = mods[i];
> + int ret = module_load(log, cand, probe, i < strict_total, args);
> +
> + switch (ret) {
> + case VLC_SUCCESS:
> + vlc_debug(log, "using %s module \"%s\"", capability,
> + module_get_object(cand));
> + module = cand;
> + /* fall through */
> + case VLC_ETIMEOUT:
> + goto done;
> }
> }
>
> - /* None of the shortcuts matched, fall back to any module */
> - if (!strict)
> - {
> - for (size_t i = 0; i < total; i++)
> - {
> - module_t *cand = mods[i];
> - if (cand == NULL || module_get_score (cand) <= 0)
> - continue;
> -
> - int ret = module_load(log, cand, probe, false, args);
> - switch (ret)
> - {
> - case VLC_SUCCESS:
> - module = cand;
> - /* fall through */
> - case VLC_ETIMEOUT:
> - goto done;
> - }
> - }
> - }
> -done:
> va_end (args);
> - free(mods);
>
> - if (module != NULL)
> - vlc_debug(log, "using %s module \"%s\"", capability,
> - module_get_object (module));
> - else
> - vlc_debug(log, "no %s modules matched", capability);
> + if (module == NULL)
> +done: vlc_debug(log, "no %s modules matched", capability);
> +
> + free(mods);
> return module;
> }
>
> --
> 2.28.0.rc0
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
>
More information about the vlc-devel
mailing list