chiark / gitweb /
hashmap: fix iterators to not skip entries
[elogind.git] / src / shared / hashmap.h
index 9c6e0cab186a746de3203c05e9567f9fad0f6e9c..5723f09ca9134c117652439d92426ccf8b5efadc 100644 (file)
@@ -32,7 +32,7 @@
  * will be treated as empty hashmap for all read operations. That way it is not
  * necessary to instantiate an object for each Hashmap use.
  *
- * If ENABLE_HASHMAP_DEBUG is defined (by configuring with --enable-hashmap-debug),
+ * If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap),
  * the implemention will:
  * - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py)
  * - perform extra checks for invalid use of iterators
@@ -43,7 +43,7 @@
 /* The base type for all hashmap and set types. Many functions in the
  * implementation take (HashmapBase*) parameters and are run-time polymorphic,
  * though the API is not meant to be polymorphic (do not call functions
- * prefixed with two underscores directly). */
+ * internal_*() directly). */
 typedef struct HashmapBase HashmapBase;
 
 /* Specific hashmap/set types */
@@ -57,7 +57,7 @@ typedef struct Set Set;                       /* Stores just keys */
 typedef struct {
         unsigned idx;         /* index of an entry to be iterated next */
         const void *next_key; /* expected value of that entry's key pointer */
-#ifdef ENABLE_HASHMAP_DEBUG
+#ifdef ENABLE_DEBUG_HASHMAP
         unsigned put_count;   /* hashmap's put_count recorded at start of iteration */
         unsigned rem_count;   /* hashmap's rem_count in previous iteration */
         unsigned prev_idx;    /* idx in previous iteration */
@@ -65,6 +65,7 @@ typedef struct {
 } Iterator;
 
 #define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
+#define _IDX_ITERATOR_NIL (UINT_MAX)
 #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
 
 typedef unsigned long (*hash_func_t)(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]);
@@ -129,7 +130,7 @@ extern const struct hash_ops devt_hash_ops = {
                 (Hashmap*)(h), \
                 (void)0)
 
-#ifdef ENABLE_HASHMAP_DEBUG
+#ifdef ENABLE_DEBUG_HASHMAP
 # define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line
 # define HASHMAP_DEBUG_SRC_ARGS   , __func__, __FILE__, __LINE__
 # define HASHMAP_DEBUG_PASS_ARGS   , func, file, line
@@ -144,25 +145,25 @@ OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops  HA
 #define hashmap_new(ops) internal_hashmap_new(ops  HASHMAP_DEBUG_SRC_ARGS)
 #define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops  HASHMAP_DEBUG_SRC_ARGS)
 
-void internal_hashmap_free(HashmapBase *h);
-static inline void hashmap_free(Hashmap *h) {
-        internal_hashmap_free(HASHMAP_BASE(h));
+HashmapBase *internal_hashmap_free(HashmapBase *h);
+static inline Hashmap *hashmap_free(Hashmap *h) {
+        return (void*)internal_hashmap_free(HASHMAP_BASE(h));
 }
-static inline void ordered_hashmap_free(OrderedHashmap *h) {
-        internal_hashmap_free(HASHMAP_BASE(h));
+static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) {
+        return (void*)internal_hashmap_free(HASHMAP_BASE(h));
 }
 
-void internal_hashmap_free_free(HashmapBase *h);
-static inline void hashmap_free_free(Hashmap *h) {
-        internal_hashmap_free_free(HASHMAP_BASE(h));
+HashmapBase *internal_hashmap_free_free(HashmapBase *h);
+static inline Hashmap *hashmap_free_free(Hashmap *h) {
+        return (void*)internal_hashmap_free_free(HASHMAP_BASE(h));
 }
-static inline void ordered_hashmap_free_free(OrderedHashmap *h) {
-        internal_hashmap_free_free(HASHMAP_BASE(h));
+static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) {
+        return (void*)internal_hashmap_free_free(HASHMAP_BASE(h));
 }
 
-void hashmap_free_free_free(Hashmap *h);
-static inline void ordered_hashmap_free_free_free(OrderedHashmap *h) {
-        hashmap_free_free_free(PLAIN_HASHMAP(h));
+Hashmap *hashmap_free_free_free(Hashmap *h);
+static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) {
+        return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h));
 }
 
 HashmapBase *internal_hashmap_copy(HashmapBase *h);
@@ -296,12 +297,12 @@ static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) {
         return internal_hashmap_buckets(HASHMAP_BASE(h));
 }
 
-void *internal_hashmap_iterate(HashmapBase *h, Iterator *i, const void **key);
-static inline void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key) {
-        return internal_hashmap_iterate(HASHMAP_BASE(h), i, key);
+bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key);
+static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) {
+        return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
 }
-static inline void *ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, const void **key) {
-        return internal_hashmap_iterate(HASHMAP_BASE(h), i, key);
+static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) {
+        return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
 }
 
 void internal_hashmap_clear(HashmapBase *h);
@@ -386,24 +387,16 @@ static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
  * It is safe to remove the current entry.
  */
 #define HASHMAP_FOREACH(e, h, i) \
-        for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), NULL); \
-             (e); \
-             (e) = hashmap_iterate((h), &(i), NULL))
+        for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); )
 
 #define ORDERED_HASHMAP_FOREACH(e, h, i) \
-        for ((i) = ITERATOR_FIRST, (e) = ordered_hashmap_iterate((h), &(i), NULL); \
-             (e); \
-             (e) = ordered_hashmap_iterate((h), &(i), NULL))
+        for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); )
 
 #define HASHMAP_FOREACH_KEY(e, k, h, i) \
-        for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), (const void**) &(k)); \
-             (e); \
-             (e) = hashmap_iterate((h), &(i), (const void**) &(k)))
+        for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
 
 #define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \
-        for ((i) = ITERATOR_FIRST, (e) = ordered_hashmap_iterate((h), &(i), (const void**) &(k)); \
-             (e); \
-             (e) = ordered_hashmap_iterate((h), &(i), (const void**) &(k)))
+        for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free);
 DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free);