hashmap: kill hashmap_free_with_destructor() and friends (#37111)
Now destructor is always set in hash_ops when necessary. Hence, hashmap_free_with_destructor() and friends are not necessary anymore. Let's kill them.
This commit is contained in:
+9
-13
@@ -912,24 +912,20 @@ static void hashmap_free_no_clear(HashmapBase *h) {
|
||||
free(h);
|
||||
}
|
||||
|
||||
HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
|
||||
HashmapBase* _hashmap_free(HashmapBase *h) {
|
||||
if (h) {
|
||||
_hashmap_clear(h, default_free_key, default_free_value);
|
||||
_hashmap_clear(h);
|
||||
hashmap_free_no_clear(h);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
|
||||
free_func_t free_key, free_value;
|
||||
void _hashmap_clear(HashmapBase *h) {
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
free_key = h->hash_ops->free_key ?: default_free_key;
|
||||
free_value = h->hash_ops->free_value ?: default_free_value;
|
||||
|
||||
if (free_key || free_value) {
|
||||
if (h->hash_ops->free_key || h->hash_ops->free_value) {
|
||||
|
||||
/* If destructor calls are defined, let's destroy things defensively: let's take the item out of the
|
||||
* hash table, and only then call the destructor functions. If these destructors then try to unregister
|
||||
@@ -941,11 +937,11 @@ void _hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t de
|
||||
|
||||
v = _hashmap_first_key_and_value(h, true, &k);
|
||||
|
||||
if (free_key)
|
||||
free_key(k);
|
||||
if (h->hash_ops->free_key)
|
||||
h->hash_ops->free_key(k);
|
||||
|
||||
if (free_value)
|
||||
free_value(v);
|
||||
if (h->hash_ops->free_value)
|
||||
h->hash_ops->free_value(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1780,7 +1776,7 @@ HashmapBase* _hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) {
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return _hashmap_free(copy, NULL, NULL);
|
||||
return _hashmap_free(copy);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
+6
-27
@@ -93,12 +93,12 @@ OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE
|
||||
#define ordered_hashmap_free_and_replace(a, b) \
|
||||
free_and_replace_full(a, b, ordered_hashmap_free)
|
||||
|
||||
HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
|
||||
HashmapBase* _hashmap_free(HashmapBase *h);
|
||||
static inline Hashmap* hashmap_free(Hashmap *h) {
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h));
|
||||
}
|
||||
static inline OrderedHashmap* ordered_hashmap_free(OrderedHashmap *h) {
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h));
|
||||
}
|
||||
|
||||
IteratedCache* iterated_cache_free(IteratedCache *cache);
|
||||
@@ -266,12 +266,12 @@ static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void
|
||||
return _hashmap_iterate(HASHMAP_BASE(h), i, value, key);
|
||||
}
|
||||
|
||||
void _hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
|
||||
void _hashmap_clear(HashmapBase *h);
|
||||
static inline void hashmap_clear(Hashmap *h) {
|
||||
_hashmap_clear(HASHMAP_BASE(h), NULL, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(h));
|
||||
}
|
||||
static inline void ordered_hashmap_clear(OrderedHashmap *h) {
|
||||
_hashmap_clear(HASHMAP_BASE(h), NULL, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(h));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -331,27 +331,6 @@ static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
|
||||
return _hashmap_first_key(HASHMAP_BASE(h), false);
|
||||
}
|
||||
|
||||
#define hashmap_clear_with_destructor(h, f) \
|
||||
({ \
|
||||
Hashmap *_h = (h); \
|
||||
void *_item; \
|
||||
while ((_item = hashmap_steal_first(_h))) \
|
||||
f(_item); \
|
||||
_h; \
|
||||
})
|
||||
#define hashmap_free_with_destructor(h, f) \
|
||||
hashmap_free(hashmap_clear_with_destructor(h, f))
|
||||
#define ordered_hashmap_clear_with_destructor(h, f) \
|
||||
({ \
|
||||
OrderedHashmap *_h = (h); \
|
||||
void *_item; \
|
||||
while ((_item = ordered_hashmap_steal_first(_h))) \
|
||||
f(_item); \
|
||||
_h; \
|
||||
})
|
||||
#define ordered_hashmap_free_with_destructor(h, f) \
|
||||
ordered_hashmap_free(ordered_hashmap_clear_with_destructor(h, f))
|
||||
|
||||
/* no hashmap_next */
|
||||
void* ordered_hashmap_next(OrderedHashmap *h, const void *key);
|
||||
|
||||
|
||||
@@ -83,17 +83,6 @@ void ordered_set_print(FILE *f, const char *field, OrderedSet *s);
|
||||
#define ORDERED_SET_FOREACH(e, s) \
|
||||
_ORDERED_SET_FOREACH(e, s, UNIQ_T(i, UNIQ))
|
||||
|
||||
#define ordered_set_clear_with_destructor(s, f) \
|
||||
({ \
|
||||
OrderedSet *_s = (s); \
|
||||
void *_item; \
|
||||
while ((_item = ordered_set_steal_first(_s))) \
|
||||
f(_item); \
|
||||
_s; \
|
||||
})
|
||||
#define ordered_set_free_with_destructor(s, f) \
|
||||
ordered_set_free(ordered_set_clear_with_destructor(s, f))
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
|
||||
|
||||
#define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep)
|
||||
|
||||
+2
-27
@@ -12,15 +12,9 @@ Set* _set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
static inline Set* set_free(Set *s) {
|
||||
return (Set*) _hashmap_free(HASHMAP_BASE(s), NULL, NULL);
|
||||
return (Set*) _hashmap_free(HASHMAP_BASE(s));
|
||||
}
|
||||
|
||||
static inline Set* set_free_free(Set *s) {
|
||||
return (Set*) _hashmap_free(HASHMAP_BASE(s), free, NULL);
|
||||
}
|
||||
|
||||
/* no set_free_free_free */
|
||||
|
||||
#define set_copy(s) ((Set*) _hashmap_copy(HASHMAP_BASE(s) HASHMAP_DEBUG_SRC_ARGS))
|
||||
|
||||
int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
@@ -77,30 +71,13 @@ static inline bool set_iterate(const Set *s, Iterator *i, void **value) {
|
||||
}
|
||||
|
||||
static inline void set_clear(Set *s) {
|
||||
_hashmap_clear(HASHMAP_BASE(s), NULL, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(s));
|
||||
}
|
||||
|
||||
static inline void set_clear_free(Set *s) {
|
||||
_hashmap_clear(HASHMAP_BASE(s), free, NULL);
|
||||
}
|
||||
|
||||
/* no set_clear_free_free */
|
||||
|
||||
static inline void *set_steal_first(Set *s) {
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(s), true, NULL);
|
||||
}
|
||||
|
||||
#define set_clear_with_destructor(s, f) \
|
||||
({ \
|
||||
Set *_s = (s); \
|
||||
void *_item; \
|
||||
while ((_item = set_steal_first(_s))) \
|
||||
f(_item); \
|
||||
_s; \
|
||||
})
|
||||
#define set_free_with_destructor(s, f) \
|
||||
set_free(set_clear_with_destructor(s, f))
|
||||
|
||||
/* no set_steal_first_key */
|
||||
/* no set_first_key */
|
||||
|
||||
@@ -145,10 +122,8 @@ int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags
|
||||
for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); )
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
|
||||
|
||||
#define _cleanup_set_free_ _cleanup_(set_freep)
|
||||
#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
|
||||
|
||||
int set_strjoin(Set *s, const char *separator, bool wrap_with_separator, char **ret);
|
||||
|
||||
|
||||
@@ -1163,8 +1163,7 @@ int netdev_reload(Manager *manager) {
|
||||
}
|
||||
|
||||
/* Detach old NetDev objects from Manager.
|
||||
* Note, the same object may be registered with multiple names, and netdev_detach() may drop multiple
|
||||
* entries. Hence, hashmap_free_with_destructor() cannot be used. */
|
||||
* The same object may be registered with multiple names, and netdev_detach() may drop multiple entries. */
|
||||
for (NetDev *n; (n = hashmap_first(manager->netdevs)); )
|
||||
netdev_detach(n);
|
||||
|
||||
|
||||
@@ -683,8 +683,7 @@ Manager* manager_free(Manager *m) {
|
||||
m->dhcp_pd_subnet_ids = set_free(m->dhcp_pd_subnet_ids);
|
||||
m->networks = ordered_hashmap_free(m->networks);
|
||||
|
||||
/* The same object may be registered with multiple names, and netdev_detach() may drop multiple
|
||||
* entries. Hence, hashmap_free_with_destructor() cannot be used. */
|
||||
/* The same object may be registered with multiple names, and netdev_detach() may drop multiple entries. */
|
||||
for (NetDev *n; (n = hashmap_first(m->netdevs)); )
|
||||
netdev_detach(n);
|
||||
m->netdevs = hashmap_free(m->netdevs);
|
||||
|
||||
@@ -764,29 +764,6 @@ TEST(hashmap_free) {
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct Item {
|
||||
int seen;
|
||||
} Item;
|
||||
static void item_seen(Item *item) {
|
||||
item->seen++;
|
||||
}
|
||||
|
||||
TEST(hashmap_free_with_destructor) {
|
||||
Hashmap *m;
|
||||
struct Item items[4] = {};
|
||||
unsigned i;
|
||||
|
||||
assert_se(m = hashmap_new(NULL));
|
||||
for (i = 0; i < ELEMENTSOF(items) - 1; i++)
|
||||
assert_se(hashmap_put(m, INT_TO_PTR(i), items + i) == 1);
|
||||
|
||||
m = hashmap_free_with_destructor(m, item_seen);
|
||||
assert_se(items[0].seen == 1);
|
||||
assert_se(items[1].seen == 1);
|
||||
assert_se(items[2].seen == 1);
|
||||
assert_se(items[3].seen == 0);
|
||||
}
|
||||
|
||||
TEST(hashmap_first) {
|
||||
_cleanup_hashmap_free_ Hashmap *m = NULL;
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ TEST(strv_make_nulstr) {
|
||||
}
|
||||
|
||||
TEST(set_make_nulstr) {
|
||||
_cleanup_set_free_free_ Set *set = NULL;
|
||||
_cleanup_set_free_ Set *set = NULL;
|
||||
size_t len = 0;
|
||||
int r;
|
||||
|
||||
@@ -130,7 +130,7 @@ TEST(set_make_nulstr) {
|
||||
static const char expect[] = { 0x00, 0x00 };
|
||||
_cleanup_free_ char *nulstr = NULL;
|
||||
|
||||
set = set_new(NULL);
|
||||
set = set_new(&string_hash_ops_free);
|
||||
assert_se(set);
|
||||
|
||||
r = set_make_nulstr(set, &nulstr, &len);
|
||||
|
||||
@@ -227,14 +227,14 @@ TEST(serialize_item_base64mem) {
|
||||
TEST(serialize_string_set) {
|
||||
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_set_free_free_ Set *s = NULL;
|
||||
_cleanup_set_free_ Set *s = NULL;
|
||||
_cleanup_free_ char *line1 = NULL, *line2 = NULL;
|
||||
char *p, *q;
|
||||
|
||||
assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
|
||||
log_info("/* %s (%s) */", __func__, fn);
|
||||
|
||||
assert_se(set_ensure_allocated(&s, &string_hash_ops) >= 0);
|
||||
assert_se(set_ensure_allocated(&s, &string_hash_ops_free) >= 0);
|
||||
|
||||
assert_se(serialize_string_set(f, "a", s) == 0);
|
||||
|
||||
|
||||
+2
-18
@@ -32,21 +32,6 @@ static void item_seen(Item *item) {
|
||||
item->seen++;
|
||||
}
|
||||
|
||||
TEST(set_free_with_destructor) {
|
||||
Set *m;
|
||||
struct Item items[4] = {};
|
||||
|
||||
assert_se(m = set_new(NULL));
|
||||
FOREACH_ARRAY(item, items, ELEMENTSOF(items) - 1)
|
||||
assert_se(set_put(m, item) == 1);
|
||||
|
||||
m = set_free_with_destructor(m, item_seen);
|
||||
assert_se(items[0].seen == 1);
|
||||
assert_se(items[1].seen == 1);
|
||||
assert_se(items[2].seen == 1);
|
||||
assert_se(items[3].seen == 0);
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_hash_ops, void, trivial_hash_func, trivial_compare_func, Item, item_seen);
|
||||
|
||||
TEST(set_free_with_hash_ops) {
|
||||
@@ -145,9 +130,8 @@ TEST(set_ensure_allocated) {
|
||||
}
|
||||
|
||||
TEST(set_copy) {
|
||||
_cleanup_set_free_ Set *s = NULL;
|
||||
_cleanup_set_free_free_ Set *copy = NULL;
|
||||
char *key1, *key2, *key3, *key4;
|
||||
_cleanup_set_free_ Set *s = NULL, *copy = NULL;
|
||||
_cleanup_free_ char *key1 = NULL, *key2 = NULL, *key3 = NULL, *key4 = NULL;
|
||||
|
||||
key1 = strdup("key1");
|
||||
assert_se(key1);
|
||||
|
||||
Reference in New Issue
Block a user