};
#if VALGRIND
-__attribute__((destructor)) static void cleanup_pools(void) {
+_destructor_ static void cleanup_pools(void) {
_cleanup_free_ char *t = NULL;
int r;
}
#define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p)
-static inline void base_set_dirty(HashmapBase *h) {
+static void base_set_dirty(HashmapBase *h) {
h->dirty = true;
}
#define hashmap_set_dirty(h) base_set_dirty(HASHMAP_BASE(h))
h->type = type;
h->from_pool = up;
- h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
+ h->hash_ops = hash_ops ?: &trivial_hash_ops;
if (type == HASHMAP_TYPE_ORDERED) {
OrderedHashmap *lh = (OrderedHashmap*)h;
free_value = h->hash_ops->free_value ?: default_free_value;
if (free_key || free_value) {
- unsigned idx;
- for (idx = skip_free_buckets(h, 0); idx != IDX_NIL;
- idx = skip_free_buckets(h, idx + 1)) {
- struct hashmap_base_entry *e = bucket_at(h, idx);
+ /* 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
+ * themselves from our hash table a second time, the entry is already gone. */
+
+ while (internal_hashmap_size(h) > 0) {
+ void *k = NULL;
+ void *v;
+
+ v = internal_hashmap_first_key_and_value(h, true, &k);
if (free_key)
- free_key((void *) e->key);
+ free_key(k);
if (free_value)
- free_value(entry_value(h, e));
+ free_value(v);
}
}
return 0;
}
-void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
- struct plain_hashmap_entry *e;
+void *internal_hashmap_remove_value(HashmapBase *h, const void *key, void *value) {
+ struct hashmap_base_entry *e;
unsigned hash, idx;
if (!h)
if (idx == IDX_NIL)
return NULL;
- e = plain_bucket_at(h, idx);
- if (e->value != value)
+ e = bucket_at(h, idx);
+ if (entry_value(h, e) != value)
return NULL;
remove_entry(h, idx);
unsigned idx;
idx = find_first_entry(h);
- if (idx == IDX_NIL)
+ if (idx == IDX_NIL) {
+ if (ret_key)
+ *ret_key = NULL;
return NULL;
+ }
e = bucket_at(h, idx);
key = (void*) e->key;
}
unsigned internal_hashmap_size(HashmapBase *h) {
-
if (!h)
return 0;
}
unsigned internal_hashmap_buckets(HashmapBase *h) {
-
if (!h)
return 0;
if (cache) {
free(cache->keys.ptr);
free(cache->values.ptr);
- free(cache);
}
- return NULL;
+ return mfree(cache);
}