mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
![Jeff Hostetler](/assets/img/avatar_default.png)
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
124 lines
3.4 KiB
C
124 lines
3.4 KiB
C
#ifndef HASHMAP_H
|
|
#define HASHMAP_H
|
|
|
|
/*
|
|
* Generic implementation of hash-based key-value mappings.
|
|
* See Documentation/technical/api-hashmap.txt.
|
|
*/
|
|
|
|
/* FNV-1 functions */
|
|
|
|
extern unsigned int strhash(const char *buf);
|
|
extern unsigned int strihash(const char *buf);
|
|
extern unsigned int memhash(const void *buf, size_t len);
|
|
extern unsigned int memihash(const void *buf, size_t len);
|
|
extern unsigned int memihash_cont(unsigned int hash_seed, const void *buf, size_t len);
|
|
|
|
static inline unsigned int sha1hash(const unsigned char *sha1)
|
|
{
|
|
/*
|
|
* Equivalent to 'return *(unsigned int *)sha1;', but safe on
|
|
* platforms that don't support unaligned reads.
|
|
*/
|
|
unsigned int hash;
|
|
memcpy(&hash, sha1, sizeof(hash));
|
|
return hash;
|
|
}
|
|
|
|
/* data structures */
|
|
|
|
struct hashmap_entry {
|
|
struct hashmap_entry *next;
|
|
unsigned int hash;
|
|
};
|
|
|
|
typedef int (*hashmap_cmp_fn)(const void *entry, const void *entry_or_key,
|
|
const void *keydata);
|
|
|
|
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 {
|
|
struct hashmap *map;
|
|
struct hashmap_entry *next;
|
|
unsigned int tablepos;
|
|
};
|
|
|
|
/* hashmap functions */
|
|
|
|
extern void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
|
|
size_t initial_size);
|
|
extern void hashmap_free(struct hashmap *map, int free_entries);
|
|
|
|
/* hashmap_entry functions */
|
|
|
|
static inline void hashmap_entry_init(void *entry, unsigned int hash)
|
|
{
|
|
struct hashmap_entry *e = entry;
|
|
e->hash = hash;
|
|
e->next = NULL;
|
|
}
|
|
extern void *hashmap_get(const struct hashmap *map, const void *key,
|
|
const void *keydata);
|
|
extern void *hashmap_get_next(const struct hashmap *map, const void *entry);
|
|
extern void hashmap_add(struct hashmap *map, void *entry);
|
|
extern void *hashmap_put(struct hashmap *map, void *entry);
|
|
extern void *hashmap_remove(struct hashmap *map, const void *key,
|
|
const void *keydata);
|
|
|
|
static inline void *hashmap_get_from_hash(const struct hashmap *map,
|
|
unsigned int hash, const void *keydata)
|
|
{
|
|
struct hashmap_entry key;
|
|
hashmap_entry_init(&key, hash);
|
|
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);
|
|
extern void *hashmap_iter_next(struct hashmap_iter *iter);
|
|
static inline void *hashmap_iter_first(struct hashmap *map,
|
|
struct hashmap_iter *iter)
|
|
{
|
|
hashmap_iter_init(map, iter);
|
|
return hashmap_iter_next(iter);
|
|
}
|
|
|
|
/* string interning */
|
|
|
|
extern const void *memintern(const void *data, size_t len);
|
|
static inline const char *strintern(const char *string)
|
|
{
|
|
return memintern(string, strlen(string));
|
|
}
|
|
|
|
#endif
|