version 1.1.1.1, 2012/02/21 17:26:12
|
version 1.1.1.2, 2016/11/02 10:09:11
|
Line 31 hash_create_size (unsigned int size, unsigned int (*ha
|
Line 31 hash_create_size (unsigned int size, unsigned int (*ha
|
{ |
{ |
struct hash *hash; |
struct hash *hash; |
|
|
|
assert ((size & (size-1)) == 0); |
hash = XMALLOC (MTYPE_HASH, sizeof (struct hash)); |
hash = XMALLOC (MTYPE_HASH, sizeof (struct hash)); |
hash->index = XCALLOC (MTYPE_HASH_INDEX, |
hash->index = XCALLOC (MTYPE_HASH_INDEX, |
sizeof (struct hash_backet *) * size); |
sizeof (struct hash_backet *) * size); |
hash->size = size; |
hash->size = size; |
|
hash->no_expand = 0; |
hash->hash_key = hash_key; |
hash->hash_key = hash_key; |
hash->hash_cmp = hash_cmp; |
hash->hash_cmp = hash_cmp; |
hash->count = 0; |
hash->count = 0; |
Line 47 struct hash *
|
Line 49 struct hash *
|
hash_create (unsigned int (*hash_key) (void *), |
hash_create (unsigned int (*hash_key) (void *), |
int (*hash_cmp) (const void *, const void *)) |
int (*hash_cmp) (const void *, const void *)) |
{ |
{ |
return hash_create_size (HASHTABSIZE, hash_key, hash_cmp); | return hash_create_size (HASH_INITIAL_SIZE, hash_key, hash_cmp); |
} |
} |
|
|
/* Utility function for hash_get(). When this function is specified |
/* Utility function for hash_get(). When this function is specified |
Line 59 hash_alloc_intern (void *arg)
|
Line 61 hash_alloc_intern (void *arg)
|
return arg; |
return arg; |
} |
} |
|
|
|
/* Expand hash if the chain length exceeds the threshold. */ |
|
static void hash_expand (struct hash *hash) |
|
{ |
|
unsigned int i, new_size, losers; |
|
struct hash_backet *hb, *hbnext, **new_index; |
|
|
|
new_size = hash->size * 2; |
|
new_index = XCALLOC(MTYPE_HASH_INDEX, sizeof(struct hash_backet *) * new_size); |
|
if (new_index == NULL) |
|
return; |
|
|
|
for (i = 0; i < hash->size; i++) |
|
for (hb = hash->index[i]; hb; hb = hbnext) |
|
{ |
|
unsigned int h = hb->key & (new_size - 1); |
|
|
|
hbnext = hb->next; |
|
hb->next = new_index[h]; |
|
new_index[h] = hb; |
|
} |
|
|
|
/* Switch to new table */ |
|
XFREE(MTYPE_HASH_INDEX, hash->index); |
|
hash->size = new_size; |
|
hash->index = new_index; |
|
|
|
/* Ideally, new index should have chains half as long as the original. |
|
If expansion didn't help, then not worth expanding again, |
|
the problem is the hash function. */ |
|
losers = 0; |
|
for (i = 0; i < hash->size; i++) |
|
{ |
|
unsigned int len = 0; |
|
for (hb = hash->index[i]; hb; hb = hb->next) |
|
{ |
|
if (++len > HASH_THRESHOLD/2) |
|
++losers; |
|
if (len >= HASH_THRESHOLD) |
|
hash->no_expand = 1; |
|
} |
|
} |
|
|
|
if (losers > hash->count / 2) |
|
hash->no_expand = 1; |
|
} |
|
|
/* Lookup and return hash backet in hash. If there is no |
/* Lookup and return hash backet in hash. If there is no |
corresponding hash backet and alloc_func is specified, create new |
corresponding hash backet and alloc_func is specified, create new |
hash backet. */ |
hash backet. */ |
Line 68 hash_get (struct hash *hash, void *data, void * (*allo
|
Line 116 hash_get (struct hash *hash, void *data, void * (*allo
|
unsigned int key; |
unsigned int key; |
unsigned int index; |
unsigned int index; |
void *newdata; |
void *newdata; |
|
unsigned int len; |
struct hash_backet *backet; |
struct hash_backet *backet; |
|
|
key = (*hash->hash_key) (data); |
key = (*hash->hash_key) (data); |
index = key % hash->size; | index = key & (hash->size - 1); |
| len = 0; |
|
|
for (backet = hash->index[index]; backet != NULL; backet = backet->next) | for (backet = hash->index[index]; backet != NULL; backet = backet->next) |
if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) | { |
return backet->data; | if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) |
| return backet->data; |
| ++len; |
| } |
|
|
if (alloc_func) |
if (alloc_func) |
{ |
{ |
Line 83 hash_get (struct hash *hash, void *data, void * (*allo
|
Line 136 hash_get (struct hash *hash, void *data, void * (*allo
|
if (newdata == NULL) |
if (newdata == NULL) |
return NULL; |
return NULL; |
|
|
|
if (len > HASH_THRESHOLD && !hash->no_expand) |
|
{ |
|
hash_expand (hash); |
|
index = key & (hash->size - 1); |
|
} |
|
|
backet = XMALLOC (MTYPE_HASH_BACKET, sizeof (struct hash_backet)); |
backet = XMALLOC (MTYPE_HASH_BACKET, sizeof (struct hash_backet)); |
backet->data = newdata; |
backet->data = newdata; |
backet->key = key; |
backet->key = key; |
Line 125 hash_release (struct hash *hash, void *data)
|
Line 184 hash_release (struct hash *hash, void *data)
|
struct hash_backet *pp; |
struct hash_backet *pp; |
|
|
key = (*hash->hash_key) (data); |
key = (*hash->hash_key) (data); |
index = key % hash->size; | index = key & (hash->size - 1); |
|
|
for (backet = pp = hash->index[index]; backet; backet = backet->next) |
for (backet = pp = hash->index[index]; backet; backet = backet->next) |
{ |
{ |