git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/6] hashmap: Add disallow_rehash setting

From
Ggit@jeffhostetler.com <git@jeffhostetler.com>
Date
Mar 22, 2017, 17:14 UTC
Message-ID
<1490202865-31325-4-git-send-email-git@jeffhostetler.com>
In-Reply-To
<1490202865-31325-1-git-send-email-git@jeffhostetler.com>
From: Jeff Hostetler <jeffhost@microsoft.com>

Teach hashmap to allow rehashes to be suppressed. This is useful when hashmaps are accessed by multiple threads. It still requires the caller to properly manage their locking. This just prevents unexpected rehashing during inserts and deletes.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
---
 hashmap.c | 12 +++++++++++-
 hashmap.h | 24 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/hashmap.c b/hashmap.c
index 505e63f..37dfc37 100644
--- a/hashmap.c
+++ b/hashmap.c
@@ -104,11 +104,19 @@ static inline unsigned int bucket(const struct hashmap *map,
 	return key->hash & (map->tablesize - 1);
 }
 
+int hashmap_bucket(const struct hashmap *map, unsigned int hash)
+{
+	return hash & (map->tablesize - 1);
+}
+
 static void rehash(struct hashmap *map, unsigned int newsize)
 {
 	unsigned int i, oldsize = map->tablesize;
 	struct hashmap_entry **oldtable = map->table;
 
+	if (map->disallow_rehash)
+		return;
+
 	alloc_table(map, newsize);
 	for (i = 0; i < oldsize; i++) {
 		struct hashmap_entry *e = oldtable[i];
@@ -141,7 +149,9 @@ void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
 		size_t initial_size)
 {
 	unsigned int size = HASHMAP_INITIAL_SIZE;
-	map->size = 0;
+
+	memset(map, 0, sizeof(*map));
+
 	map->cmpfn = equals_function ? equals_function : always_equal;
 
 	/* calculate initial table size and allocate the table */
diff --git a/hashmap.h b/hashmap.h
index 45eda69..de6022a 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -39,6 +39,7 @@ struct hashmap {
 	struct hashmap_entry **table;
 	hashmap_cmp_fn cmpfn;
 	unsigned int size, tablesize, grow_at, shrink_at;
+	unsigned disallow_rehash : 1;
 };
 
 struct hashmap_iter {
@@ -77,6 +78,29 @@ static inline void *hashmap_get_from_hash(const struct hashmap *map,
 	return hashmap_get(map, &key, keydata);
 }
 
+int hashmap_bucket(const struct hashmap *map, unsigned int hash);
+
+/*
+ * Disallow/allow rehashing of the hashmap.
+ * This is useful if the caller knows that the hashmap
+ * needs multi-threaded access.  The caller is still
+ * required to guard/lock searches and inserts in a
+ * manner appropriate to their usage.  This simply
+ * prevents the table from being unexpectedly re-mapped.
+ *
+ * If is up to the caller to ensure that the hashmap is
+ * initialized to a reasonable size to prevent poor
+ * performance.
+ *
+ * When value=1, prevent future rehashes on adds and deleted.
+ * When value=0, allow future rehahses.  This DOES NOT force
+ * a rehash now.
+ */
+static inline void hashmap_disallow_rehash(struct hashmap *map, unsigned value)
+{
+	map->disallow_rehash = value;
+}
+
 /* hashmap_iter functions */
 
 extern void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter);
-- 
2.7.4
Previous: git@jeffhostetler.comNext: git@jeffhostetler.com
Message 2 of 14 in “thread lazy_init_name_hash”
  1. 0/6 thread lazy_init_name_hashgit@jeffhostetler.com, Mar 22, 2017
  2. 3/6 hashmap: Add disallow_rehash settinggit@jeffhostetler.com, Mar 22, 2017
  3. 4/6 name-hash: perf improvement for lazy_init_name_hashgit@jeffhostetler.com, Mar 22, 2017
  4. 1/6 name-hash: specify initial size for istate.dir_hash tablegit@jeffhostetler.com, Mar 22, 2017
  5. 2/6 hashmap: allow memihash computation to be continuedgit@jeffhostetler.com, Mar 22, 2017
  6. 6/6 name-hash: add perf test for lazy_init_name_hashgit@jeffhostetler.com, Mar 22, 2017
  7. 5/6 name-hash: add test-lazy-init-name-hashgit@jeffhostetler.com, Mar 22, 2017
  8. Stefan BellerMar 22, 2017
  9. Jeff HostetlerMar 22, 2017
  10. Junio C HamanoMar 22, 2017
  11. Junio C HamanoMar 22, 2017
  12. Jeff HostetlerMar 22, 2017
  13. Junio C HamanoMar 22, 2017
  14. Junio C HamanoMar 22, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.