Skip to content

Commit c8e424c

Browse files
Eric Wonggitster
authored andcommitted
hashmap: introduce hashmap_free_entries
`hashmap_free_entries' behaves like `container_of' and passes the offset of the hashmap_entry struct to the internal `hashmap_free_' function, allowing the function to free any struct pointer regardless of where the hashmap_entry field is located. `hashmap_free' no longer takes any arguments aside from the hashmap itself. Signed-off-by: Eric Wong <[email protected]> Reviewed-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8a973d0 commit c8e424c

17 files changed

+52
-34
lines changed

blame.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ static void get_fingerprint(struct fingerprint *result,
433433

434434
static void free_fingerprint(struct fingerprint *f)
435435
{
436-
hashmap_free(&f->map, 0);
436+
hashmap_free(&f->map);
437437
free(f->entries);
438438
}
439439

builtin/fetch.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ static void find_non_local_tags(const struct ref *refs,
366366
item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid);
367367
string_list_insert(&remote_refs_list, ref->name);
368368
}
369-
hashmap_free(&existing_refs, 1);
369+
hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
370370

371371
/*
372372
* We may have a final lightweight tag that needs to be
@@ -401,7 +401,7 @@ static void find_non_local_tags(const struct ref *refs,
401401
**tail = rm;
402402
*tail = &rm->next;
403403
}
404-
hashmap_free(&remote_refs, 1);
404+
hashmap_free_entries(&remote_refs, struct refname_hash_entry, ent);
405405
string_list_clear(&remote_refs_list, 0);
406406
}
407407

@@ -530,7 +530,7 @@ static struct ref *get_ref_map(struct remote *remote,
530530
}
531531
}
532532
}
533-
hashmap_free(&existing_refs, 1);
533+
hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
534534

535535
return ref_map;
536536
}

config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1948,7 +1948,7 @@ void git_configset_clear(struct config_set *cs)
19481948
free(entry->key);
19491949
string_list_clear(&entry->value_list, 1);
19501950
}
1951-
hashmap_free(&cs->config_hash, 1);
1951+
hashmap_free_entries(&cs->config_hash, struct config_set_element, ent);
19521952
cs->hash_initialized = 0;
19531953
free(cs->list.items);
19541954
cs->list.nr = 0;

diff.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6236,8 +6236,10 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
62366236
if (o->color_moved == COLOR_MOVED_ZEBRA_DIM)
62376237
dim_moved_lines(o);
62386238

6239-
hashmap_free(&add_lines, 1);
6240-
hashmap_free(&del_lines, 1);
6239+
hashmap_free_entries(&add_lines, struct moved_entry,
6240+
ent);
6241+
hashmap_free_entries(&del_lines, struct moved_entry,
6242+
ent);
62416243
}
62426244

62436245
for (i = 0; i < esm.nr; i++)

diffcore-rename.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ static int find_exact_renames(struct diff_options *options)
358358
renames += find_identical_files(&file_table, i, options);
359359

360360
/* Free the hash data structure and entries */
361-
hashmap_free(&file_table, 1);
361+
hashmap_free_entries(&file_table, struct file_similarity, entry);
362362

363363
return renames;
364364
}

hashmap.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,21 @@ void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
171171
map->do_count_items = 1;
172172
}
173173

174-
void hashmap_free(struct hashmap *map, int free_entries)
174+
void hashmap_free_(struct hashmap *map, ssize_t entry_offset)
175175
{
176176
if (!map || !map->table)
177177
return;
178-
if (free_entries) {
178+
if (entry_offset >= 0) { /* called by hashmap_free_entries */
179179
struct hashmap_iter iter;
180180
struct hashmap_entry *e;
181+
181182
hashmap_iter_init(map, &iter);
182183
while ((e = hashmap_iter_next(&iter)))
183-
free(e);
184+
/*
185+
* like container_of, but using caller-calculated
186+
* offset (caller being hashmap_free_entries)
187+
*/
188+
free((char *)e - entry_offset);
184189
}
185190
free(map->table);
186191
memset(map, 0, sizeof(*map));

hashmap.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
* }
9797
*
9898
* if (!strcmp("end", action)) {
99-
* hashmap_free(&map, 1);
99+
* hashmap_free_entries(&map, struct long2string, ent);
100100
* break;
101101
* }
102102
* }
@@ -232,13 +232,20 @@ void hashmap_init(struct hashmap *map,
232232
const void *equals_function_data,
233233
size_t initial_size);
234234

235+
/* internal function for freeing hashmap */
236+
void hashmap_free_(struct hashmap *map, ssize_t offset);
237+
235238
/*
236-
* Frees a hashmap structure and allocated memory.
237-
*
238-
* If `free_entries` is true, each hashmap_entry in the map is freed as well
239-
* using stdlibs free().
239+
* Frees a hashmap structure and allocated memory, leaves entries undisturbed
240+
*/
241+
#define hashmap_free(map) hashmap_free_(map, -1)
242+
243+
/*
244+
* Frees @map and all entries. @type is the struct type of the entry
245+
* where @member is the hashmap_entry struct used to associate with @map
240246
*/
241-
void hashmap_free(struct hashmap *map, int free_entries);
247+
#define hashmap_free_entries(map, type, member) \
248+
hashmap_free_(map, offsetof(type, member));
242249

243250
/* hashmap_entry functions */
244251

merge-recursive.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,7 +2633,7 @@ static struct string_list *get_renames(struct merge_options *opt,
26332633
free(e->target_file);
26342634
string_list_clear(&e->source_files, 0);
26352635
}
2636-
hashmap_free(&collisions, 1);
2636+
hashmap_free_entries(&collisions, struct collision_entry, ent);
26372637
return renames;
26382638
}
26392639

@@ -2853,7 +2853,7 @@ static void initial_cleanup_rename(struct diff_queue_struct *pairs,
28532853
strbuf_release(&e->new_dir);
28542854
/* possible_new_dirs already cleared in get_directory_renames */
28552855
}
2856-
hashmap_free(dir_renames, 1);
2856+
hashmap_free_entries(dir_renames, struct dir_rename_entry, ent);
28572857
free(dir_renames);
28582858

28592859
free(pairs->queue);
@@ -3482,7 +3482,8 @@ int merge_trees(struct merge_options *opt,
34823482
string_list_clear(entries, 1);
34833483
free(entries);
34843484

3485-
hashmap_free(&opt->current_file_dir_set, 1);
3485+
hashmap_free_entries(&opt->current_file_dir_set,
3486+
struct path_hashmap_entry, e);
34863487

34873488
if (clean < 0) {
34883489
unpack_trees_finish(opt);

name-hash.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,6 @@ void free_name_hash(struct index_state *istate)
728728
return;
729729
istate->name_hash_initialized = 0;
730730

731-
hashmap_free(&istate->name_hash, 0);
732-
hashmap_free(&istate->dir_hash, 1);
731+
hashmap_free(&istate->name_hash);
732+
hashmap_free_entries(&istate->dir_hash, struct dir_entry, ent);
733733
}

oidmap.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ void oidmap_free(struct oidmap *map, int free_entries)
2525
{
2626
if (!map)
2727
return;
28-
hashmap_free(&map->map, free_entries);
28+
29+
/* TODO: make oidmap itself not depend on struct layouts */
30+
hashmap_free_(&map->map, free_entries ? 0 : -1);
2931
}
3032

3133
void *oidmap_get(const struct oidmap *map, const struct object_id *key)

0 commit comments

Comments
 (0)