Browse Source

htable: HTABLE_INITIALIZER() for static initialization.

Unfortunately it's a bit of a pain to use for typed hashtables, but it
works.
Rusty Russell 14 years ago
parent
commit
60cc720d07
3 changed files with 29 additions and 15 deletions
  1. 2 10
      ccan/htable/htable.c
  2. 24 5
      ccan/htable/htable.h
  3. 3 0
      ccan/htable/htable_type.h

+ 2 - 10
ccan/htable/htable.c

@@ -45,18 +45,10 @@ static inline uintptr_t get_hash_ptr_bits(const struct htable *ht,
 void htable_init(struct htable *ht,
 		 size_t (*rehash)(const void *elem, void *priv), void *priv)
 {
-	ht->bits = 0;
+	struct htable empty = HTABLE_INITIALIZER(empty, NULL, NULL);
+	*ht = empty;
 	ht->rehash = rehash;
 	ht->priv = priv;
-	ht->elems = 0;
-	ht->deleted = 0;
-	ht->max = 0;
-	ht->max_with_deleted = 0;
-	/* This guarantees we enter update_common first add. */
-	ht->common_mask = -1;
-	ht->common_bits = 0;
-	ht->perfect_bit = 0;
-	/* Dummy table until first insert. */
 	ht->table = &ht->perfect_bit;
 }
 

+ 24 - 5
ccan/htable/htable.h

@@ -24,7 +24,26 @@ struct htable {
 };
 
 /**
- * htable_init - initialize an empty hash tree.
+ * HTABLE_INITIALIZER - static initialization for a hash table.
+ * @name: name of this htable.
+ * @rehash: hash function to use for rehashing.
+ * @priv: private argument to @rehash function.
+ *
+ * This is useful for setting up static and global hash tables.
+ *
+ * Example:
+ *	// For simplicity's sake, say hash value is contents of elem.
+ *	static size_t rehash(const void *elem, void *unused)
+ *	{
+ *		return *(size_t *)elem;
+ *	}
+ *	static struct htable ht = HTABLE_INITIALIZER(ht, rehash, NULL);
+ */
+#define HTABLE_INITIALIZER(name, rehash, priv)				\
+	{ rehash, priv, 0, 0, 0, 0, 0, -1, 0, 0, &name.perfect_bit }
+
+/**
+ * htable_init - initialize an empty hash table.
  * @ht: the hash table to initialize
  * @rehash: hash function to use for rehashing.
  * @priv: private argument to @rehash function.
@@ -33,7 +52,7 @@ void htable_init(struct htable *ht,
 		 size_t (*rehash)(const void *elem, void *priv), void *priv);
 
 /**
- * htable_clear - empty a hash tree.
+ * htable_clear - empty a hash table.
  * @ht: the hash table to clear
  *
  * This doesn't do anything to any pointers left in it.
@@ -48,7 +67,7 @@ void htable_clear(struct htable *ht);
 size_t htable_rehash(const void *elem);
 
 /**
- * htable_add - add a pointer into a hash tree.
+ * htable_add - add a pointer into a hash table.
  * @ht: the htable
  * @hash: the hash value of the object
  * @p: the non-NULL pointer
@@ -59,7 +78,7 @@ size_t htable_rehash(const void *elem);
 bool htable_add(struct htable *ht, size_t hash, const void *p);
 
 /**
- * htable_del - remove a pointer from a hash tree
+ * htable_del - remove a pointer from a hash table
  * @ht: the htable
  * @hash: the hash value of the object
  * @p: the pointer
@@ -145,7 +164,7 @@ void *htable_first(const struct htable *htable, struct htable_iter *i);
 void *htable_next(const struct htable *htable, struct htable_iter *i);
 
 /**
- * htable_delval - remove an iterated pointer from a hash tree
+ * htable_delval - remove an iterated pointer from a hash table
  * @ht: the htable
  * @i: the htable_iter
  *

+ 3 - 0
ccan/htable/htable_type.h

@@ -38,6 +38,9 @@
  *
  * It's currently safe to iterate over a changing hashtable, but you might
  * miss an element.  Iteration isn't very efficient, either.
+ *
+ * You can use HTABLE_INITIALIZER like so:
+ *	struct <name> ht = { HTABLE_INITIALIZER(ht.raw, <name>_hash, NULL) };
  */
 #define HTABLE_DEFINE_TYPE(type, keyof, hashfn, eqfn, name)		\
 	struct name { struct htable raw; };				\