Re: [PATCH v2 4/7] merge-ort: switch our strmaps over to using memory pools
- From
Elijah Newren <newren@gmail.com>
- Date
- Jul 30, 2021, 02:30 UTC
- Message-ID
- <CABPp-BE8OEjcMrJO8uijLFsvvpQH9KA=a+p_6bH71Z6QxXLB6w@mail.gmail.com>
- In-Reply-To
- <YQMLBW6LAZmQ8nDz@coredump.intra.peff.net>
On Thu, Jul 29, 2021 at 2:09 PM Jeff King <peff@peff.net> wrote:
Show 30 quoted lines
>
> On Thu, Jul 29, 2021 at 12:37:52PM -0600, Elijah Newren wrote:
>
> > > Arguably, the existence of these function indirections is perhaps a sign
> > > that the strmap API should provide a version of the clear functions that
> > > takes "partial / not-partial" as a parameter.
> >
> > Are you suggesting a modification of str{map,intmap,set}_clear() to
> > take an extra parameter, or removing the
> > str{map,intmap,set}_partial_clear() functions and introducing new
> > functions that take a partial/not-partial parameter? I think you're
> > suggesting the latter, and that makes more sense to me...but I'm
> > drawing blanks trying to come up with a reasonable function name.
>
> It does seem a shame to add the "partial" parameter to strmap_clear(),
> just because most callers don't need it (so they end up with this
> inscrutable "0" parameter).
>
> What if there was a flags field? Then it could be combined with the
> free_values parameter. The result is kind of verbose in two ways:
>
> - now strset_clear(), etc, need a "flags" parameter, which they didn't
> before (and is just "0" most of the time!)
>
> - now "strmap_clear(foo, 1)" becomes "strmap_clear(foo, STRMAP_FREE_VALUES)".
> That's a lot longer, though arguably it's easier to understand since
> the boolean is explained.
>
> Having gone through the exercise, I am not sure it is actually making
> anything more readable (messy patch is below for reference).Thanks for diving in. Since it's not clear if it's helping, I'll just take your earlier suggestion to rename the "strmap_func" variable to "strmap_clear_func" instead.
Show 262 quoted lines
>
> diff --git a/builtin/shortlog.c b/builtin/shortlog.c
> index 3e7ab1ca82..dfbdba53da 100644
> --- a/builtin/shortlog.c
> +++ b/builtin/shortlog.c
> @@ -242,7 +242,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
> insert_records_from_trailers(log, &dups, commit, &ctx, oneline_str);
> }
>
> - strset_clear(&dups);
> + strset_clear(&dups, 0);
> strbuf_release(&ident);
> strbuf_release(&oneline);
> }
> diff --git a/diffcore-rename.c b/diffcore-rename.c
> index 7e6b3e1b14..0c960111d1 100644
> --- a/diffcore-rename.c
> +++ b/diffcore-rename.c
> @@ -665,9 +665,10 @@ void partial_clear_dir_rename_count(struct strmap *dir_rename_count)
>
> strmap_for_each_entry(dir_rename_count, &iter, entry) {
> struct strintmap *counts = entry->value;
> - strintmap_clear(counts);
> + strintmap_clear(counts, 0);
> }
> - strmap_partial_clear(dir_rename_count, 1);
> + strmap_clear(dir_rename_count,
> + STRMAP_FREE_VALUES | STRMAP_PARTIAL_CLEAR);
> }
>
> static void cleanup_dir_rename_info(struct dir_rename_info *info,
> @@ -683,15 +684,15 @@ static void cleanup_dir_rename_info(struct dir_rename_info *info,
> return;
>
> /* idx_map */
> - strintmap_clear(&info->idx_map);
> + strintmap_clear(&info->idx_map, 0);
>
> /* dir_rename_guess */
> - strmap_clear(&info->dir_rename_guess, 1);
> + strmap_clear(&info->dir_rename_guess, STRMAP_FREE_VALUES);
>
> /* relevant_source_dirs */
> if (info->relevant_source_dirs &&
> info->relevant_source_dirs != dirs_removed) {
> - strintmap_clear(info->relevant_source_dirs);
> + strintmap_clear(info->relevant_source_dirs, 0);
> FREE_AND_NULL(info->relevant_source_dirs);
> }
>
> @@ -716,7 +717,7 @@ static void cleanup_dir_rename_info(struct dir_rename_info *info,
>
> if (!strintmap_get(dirs_removed, source_dir)) {
> string_list_append(&to_remove, source_dir);
> - strintmap_clear(counts);
> + strintmap_clear(counts, 0);
> continue;
> }
>
> @@ -1045,8 +1046,8 @@ static int find_basename_matches(struct diff_options *options,
> }
> }
>
> - strintmap_clear(&sources);
> - strintmap_clear(&dests);
> + strintmap_clear(&sources, 0);
> + strintmap_clear(&dests, 0);
>
> return renames;
> }
> @@ -1700,7 +1701,7 @@ void diffcore_rename_extended(struct diff_options *options,
> FREE_AND_NULL(rename_src);
> rename_src_nr = rename_src_alloc = 0;
> if (break_idx) {
> - strintmap_clear(break_idx);
> + strintmap_clear(break_idx, 0);
> FREE_AND_NULL(break_idx);
> }
> trace2_region_leave("diff", "write back to queue", options->repo);
> diff --git a/merge-ort.c b/merge-ort.c
> index 0fb942692a..0765e23577 100644
> --- a/merge-ort.c
> +++ b/merge-ort.c
> @@ -532,15 +532,10 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
> {
> struct rename_info *renames = &opti->renames;
> int i;
> - void (*strmap_func)(struct strmap *, int) =
> - reinitialize ? strmap_partial_clear : strmap_clear;
> - void (*strintmap_func)(struct strintmap *) =
> - reinitialize ? strintmap_partial_clear : strintmap_clear;
> - void (*strset_func)(struct strset *) =
> - reinitialize ? strset_partial_clear : strset_clear;
> + unsigned flags = reinitialize ? STRMAP_PARTIAL_CLEAR : 0;
>
> if (opti->pool)
> - strmap_func(&opti->paths, 0);
> + strmap_clear(&opti->paths, flags);
> else {
> /*
> * We marked opti->paths with strdup_strings = 0, so that
> @@ -550,15 +545,15 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
> * to these strings, it is time to deallocate them.
> */
> free_strmap_strings(&opti->paths);
> - strmap_func(&opti->paths, 1);
> + strmap_clear(&opti->paths, flags | STRMAP_FREE_VALUES);
> }
>
> /*
> * All keys and values in opti->conflicted are a subset of those in
> * opti->paths. We don't want to deallocate anything twice, so we
> * don't free the keys and we pass 0 for free_values.
> */
> - strmap_func(&opti->conflicted, 0);
> + strmap_clear(&opti->conflicted, flags);
>
> if (!opti->pool) {
> /*
> @@ -579,24 +574,24 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
>
> /* Free memory used by various renames maps */
> for (i = MERGE_SIDE1; i <= MERGE_SIDE2; ++i) {
> - strintmap_func(&renames->dirs_removed[i]);
> - strmap_func(&renames->dir_renames[i], 0);
> - strintmap_func(&renames->relevant_sources[i]);
> + strintmap_clear(&renames->dirs_removed[i], flags);
> + strmap_clear(&renames->dir_renames[i], flags);
> + strintmap_clear(&renames->relevant_sources[i], flags);
> if (!reinitialize)
> assert(renames->cached_pairs_valid_side == 0);
> if (i != renames->cached_pairs_valid_side &&
> -1 != renames->cached_pairs_valid_side) {
> - strset_func(&renames->cached_target_names[i]);
> - strmap_func(&renames->cached_pairs[i], 1);
> - strset_func(&renames->cached_irrelevant[i]);
> + strset_clear(&renames->cached_target_names[i], flags);
> + strmap_clear(&renames->cached_pairs[i], flags | STRMAP_FREE_VALUES);
> + strset_clear(&renames->cached_irrelevant[i], flags);
> partial_clear_dir_rename_count(&renames->dir_rename_count[i]);
> if (!reinitialize)
> strmap_clear(&renames->dir_rename_count[i], 1);
> }
> }
> for (i = MERGE_SIDE1; i <= MERGE_SIDE2; ++i) {
> - strintmap_func(&renames->deferred[i].possible_trivial_merges);
> - strset_func(&renames->deferred[i].target_dirs);
> + strintmap_clear(&renames->deferred[i].possible_trivial_merges, flags);
> + strset_clear(&renames->deferred[i].target_dirs, flags);
> renames->deferred[i].trivial_merges_okay = 1; /* 1 == maybe */
> }
> renames->cached_pairs_valid_side = 0;
> @@ -1482,7 +1477,7 @@ static int handle_deferred_entries(struct merge_options *opt,
> if (ret < 0)
> return ret;
> }
> - strintmap_clear(©);
> + strintmap_clear(©, 0);
> strintmap_for_each_entry(&renames->deferred[side].possible_trivial_merges,
> &iter, entry) {
> const char *path = entry->key;
> diff --git a/strmap.c b/strmap.c
> index 4fb9f6100e..7343800df5 100644
> --- a/strmap.c
> +++ b/strmap.c
> @@ -37,10 +37,11 @@ void strmap_init_with_options(struct strmap *map,
> map->strdup_strings = strdup_strings;
> }
>
> -static void strmap_free_entries_(struct strmap *map, int free_values)
> +static void strmap_free_entries_(struct strmap *map, unsigned flags)
> {
> struct hashmap_iter iter;
> struct strmap_entry *e;
> + int free_values = flags & STRMAP_FREE_VALUES;
>
> if (!map)
> return;
> @@ -64,16 +65,13 @@ static void strmap_free_entries_(struct strmap *map, int free_values)
> }
> }
>
> -void strmap_clear(struct strmap *map, int free_values)
> +void strmap_clear(struct strmap *map, unsigned flags)
> {
> - strmap_free_entries_(map, free_values);
> - hashmap_clear(&map->map);
> -}
> -
> -void strmap_partial_clear(struct strmap *map, int free_values)
> -{
> - strmap_free_entries_(map, free_values);
> - hashmap_partial_clear(&map->map);
> + strmap_free_entries_(map, flags);
> + if (flags & STRMAP_PARTIAL_CLEAR)
> + hashmap_partial_clear(&map->map);
> + else
> + hashmap_clear(&map->map);
> }
>
> static struct strmap_entry *create_entry(struct strmap *map,
> diff --git a/strmap.h b/strmap.h
> index 1e152d832d..d03d451654 100644
> --- a/strmap.h
> +++ b/strmap.h
> @@ -46,16 +46,14 @@ void strmap_init_with_options(struct strmap *map,
> struct mem_pool *pool,
> int strdup_strings);
>
> -/*
> - * Remove all entries from the map, releasing any allocated resources.
> - */
> -void strmap_clear(struct strmap *map, int free_values);
> +#define STRMAP_FREE_VALUES 1 /* 1 for historical compat, but we should probably
> + update callers to use the correct name) */
> +#define STRMAP_PARTIAL_CLEAR 2
>
> /*
> - * Similar to strmap_clear() but leaves map->map->table allocated and
> - * pre-sized so that subsequent uses won't need as many rehashings.
> + * Remove all entries from the map, releasing any allocated resources.
> */
> -void strmap_partial_clear(struct strmap *map, int free_values);
> +void strmap_clear(struct strmap *map, unsigned flags);
>
> /*
> * Insert "str" into the map, pointing to "data".
> @@ -148,14 +146,10 @@ static inline void strintmap_init_with_options(struct strintmap *map,
> map->default_value = default_value;
> }
>
> -static inline void strintmap_clear(struct strintmap *map)
> -{
> - strmap_clear(&map->map, 0);
> -}
> -
> -static inline void strintmap_partial_clear(struct strintmap *map)
> +static inline void strintmap_clear(struct strintmap *map, unsigned flags)
> {
> - strmap_partial_clear(&map->map, 0);
> + /* maybe clear STRMAP_FREE_VALUES bit for extra protection */
> + strmap_clear(&map->map, flags);
> }
>
> static inline int strintmap_contains(struct strintmap *map, const char *str)
> @@ -232,14 +226,9 @@ static inline void strset_init_with_options(struct strset *set,
> strmap_init_with_options(&set->map, pool, strdup_strings);
> }
>
> -static inline void strset_clear(struct strset *set)
> -{
> - strmap_clear(&set->map, 0);
> -}
> -
> -static inline void strset_partial_clear(struct strset *set)
> +static inline void strset_clear(struct strset *set, unsigned flags)
> {
> - strmap_partial_clear(&set->map, 0);
> + strmap_clear(&set->map, flags);
> }
>
> static inline int strset_contains(struct strset *set, const char *str)