提交 7428746c authored 作者: Anthony Minessale's avatar Anthony Minessale

FS-6453 --resolve

上级 7e9c3505
...@@ -119,7 +119,8 @@ switch_create_hashtable(switch_hashtable_t **hp, unsigned int minsize, ...@@ -119,7 +119,8 @@ switch_create_hashtable(switch_hashtable_t **hp, unsigned int minsize,
typedef enum { typedef enum {
HASHTABLE_FLAG_NONE = 0, HASHTABLE_FLAG_NONE = 0,
HASHTABLE_FLAG_FREE_KEY = (1 << 0), HASHTABLE_FLAG_FREE_KEY = (1 << 0),
HASHTABLE_FLAG_FREE_VALUE = (1 << 1) HASHTABLE_FLAG_FREE_VALUE = (1 << 1),
HASHTABLE_DUP_CHECK = (1 << 2)
} hashtable_flag_t; } hashtable_flag_t;
SWITCH_DECLARE(int) SWITCH_DECLARE(int)
......
...@@ -57,7 +57,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_destroy(switch_hash_t **hash) ...@@ -57,7 +57,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_destroy(switch_hash_t **hash)
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_destructor(switch_hash_t *hash, const char *key, const void *data, hashtable_destructor_t destructor) SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_destructor(switch_hash_t *hash, const char *key, const void *data, hashtable_destructor_t destructor)
{ {
switch_hashtable_insert_destructor(hash, strdup(key), (void *)data, HASHTABLE_FLAG_FREE_KEY, destructor); switch_hashtable_insert_destructor(hash, strdup(key), (void *)data, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_DUP_CHECK, destructor);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
......
...@@ -153,13 +153,54 @@ switch_hashtable_count(switch_hashtable_t *h) ...@@ -153,13 +153,54 @@ switch_hashtable_count(switch_hashtable_t *h)
return h->entrycount; return h->entrycount;
} }
static void * _switch_hashtable_remove(switch_hashtable_t *h, void *k, unsigned int hashvalue, unsigned int index) {
/* TODO: consider compacting the table when the load factor drops enough,
* or provide a 'compact' method. */
struct entry *e;
struct entry **pE;
void *v;
pE = &(h->table[index]);
e = *pE;
while (NULL != e) {
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
*pE = e->next;
h->entrycount--;
v = e->v;
if (e->flags & HASHTABLE_FLAG_FREE_KEY) {
freekey(e->k);
}
if (e->flags & HASHTABLE_FLAG_FREE_VALUE) {
switch_safe_free(e->v);
v = NULL;
} else if (e->destructor) {
e->destructor(e->v);
v = e->v = NULL;
}
switch_safe_free(e);
return v;
}
pE = &(e->next);
e = e->next;
}
return NULL;
}
/*****************************************************************************/ /*****************************************************************************/
SWITCH_DECLARE(int) SWITCH_DECLARE(int)
switch_hashtable_insert_destructor(switch_hashtable_t *h, void *k, void *v, hashtable_flag_t flags, hashtable_destructor_t destructor) switch_hashtable_insert_destructor(switch_hashtable_t *h, void *k, void *v, hashtable_flag_t flags, hashtable_destructor_t destructor)
{ {
/* This method allows duplicate keys - but they shouldn't be used */
unsigned int index;
struct entry *e; struct entry *e;
unsigned int hashvalue = hash(h, k);
unsigned index = indexFor(h->tablelength, hashvalue);
if (flags & HASHTABLE_DUP_CHECK) {
_switch_hashtable_remove(h, k, hashvalue, index);
}
if (++(h->entrycount) > h->loadlimit) if (++(h->entrycount) > h->loadlimit)
{ {
/* Ignore the return value. If expand fails, we should /* Ignore the return value. If expand fails, we should
...@@ -167,11 +208,11 @@ switch_hashtable_insert_destructor(switch_hashtable_t *h, void *k, void *v, hash ...@@ -167,11 +208,11 @@ switch_hashtable_insert_destructor(switch_hashtable_t *h, void *k, void *v, hash
* -- we may not have memory for a larger table, but one more * -- we may not have memory for a larger table, but one more
* element may be ok. Next time we insert, we'll try expanding again.*/ * element may be ok. Next time we insert, we'll try expanding again.*/
hashtable_expand(h); hashtable_expand(h);
index = indexFor(h->tablelength, hashvalue);
} }
e = (struct entry *)malloc(sizeof(struct entry)); e = (struct entry *)malloc(sizeof(struct entry));
if (NULL == e) { --(h->entrycount); return 0; } /*oom*/ if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
e->h = hash(h,k); e->h = hashvalue;
index = indexFor(h->tablelength,e->h);
e->k = k; e->k = k;
e->v = v; e->v = v;
e->flags = flags; e->flags = flags;
...@@ -202,40 +243,8 @@ switch_hashtable_search(switch_hashtable_t *h, void *k) ...@@ -202,40 +243,8 @@ switch_hashtable_search(switch_hashtable_t *h, void *k)
SWITCH_DECLARE(void *) /* returns value associated with key */ SWITCH_DECLARE(void *) /* returns value associated with key */
switch_hashtable_remove(switch_hashtable_t *h, void *k) switch_hashtable_remove(switch_hashtable_t *h, void *k)
{ {
/* TODO: consider compacting the table when the load factor drops enough, unsigned int hashvalue = hash(h,k);
* or provide a 'compact' method. */ return _switch_hashtable_remove(h, k, hashvalue, indexFor(h->tablelength,hashvalue));
struct entry *e;
struct entry **pE;
void *v;
unsigned int hashvalue, index;
hashvalue = hash(h,k);
index = indexFor(h->tablelength,hashvalue);
pE = &(h->table[index]);
e = *pE;
while (NULL != e) {
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
*pE = e->next;
h->entrycount--;
v = e->v;
if (e->flags & HASHTABLE_FLAG_FREE_KEY) {
freekey(e->k);
}
if (e->flags & HASHTABLE_FLAG_FREE_VALUE) {
switch_safe_free(e->v);
} else if (e->destructor) {
e->destructor(e->v);
e->v = NULL;
}
switch_safe_free(e);
return v;
}
pE = &(e->next);
e = e->next;
}
return NULL;
} }
/*****************************************************************************/ /*****************************************************************************/
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论