]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/hashmap.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / basic / hashmap.c
index 5a676eeb61a74d4761f7c644e37656507122ce58..24bdc33cec6f7692905ca5b97e74802e817f191a 100644 (file)
@@ -276,7 +276,7 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
 };
 
 #if VALGRIND
-__attribute__((destructor)) static void cleanup_pools(void) {
+_destructor_ static void cleanup_pools(void) {
         _cleanup_free_ char *t = NULL;
         int r;
 
@@ -345,7 +345,7 @@ static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
 }
 #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))
@@ -779,7 +779,7 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
 
         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;
@@ -882,17 +882,22 @@ void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_f
         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);
                 }
         }
 
@@ -1475,8 +1480,8 @@ int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_
         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)
@@ -1487,8 +1492,8 @@ void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
         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);
@@ -1511,8 +1516,11 @@ void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **r
         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;
@@ -1528,7 +1536,6 @@ void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **r
 }
 
 unsigned internal_hashmap_size(HashmapBase *h) {
-
         if (!h)
                 return 0;
 
@@ -1536,7 +1543,6 @@ unsigned internal_hashmap_size(HashmapBase *h) {
 }
 
 unsigned internal_hashmap_buckets(HashmapBase *h) {
-
         if (!h)
                 return 0;
 
@@ -1896,8 +1902,7 @@ IteratedCache *iterated_cache_free(IteratedCache *cache) {
         if (cache) {
                 free(cache->keys.ptr);
                 free(cache->values.ptr);
-                free(cache);
         }
 
-        return NULL;
+        return mfree(cache);
 }