mirror of
https://github.com/linux-msm/qrtr.git
synced 2025-12-24 22:19:15 +01:00
map: Fix removal of entries from the table
Removing entries from an open addressed hash table creates holes in the collision chains, preventing previous colliding entries to be found. By inserting tombstones, rather than clearing deleted entries makes it possible to distinguish the end of a chain from a hole. Reviewed-by: Arun Kumar Neelakantam <aneela@codeaurora.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
27
src/map.c
27
src/map.c
@@ -31,6 +31,9 @@ struct map_entry {
|
||||
struct map_item *item;
|
||||
};
|
||||
|
||||
/* Marker for deleted items */
|
||||
static struct map_item deleted;
|
||||
|
||||
void map_destroy(struct map *map)
|
||||
{
|
||||
free(map->data);
|
||||
@@ -43,7 +46,8 @@ void map_clear(struct map *map, void (*release)(struct map_item *))
|
||||
for (i = 0; i < map->size; ++i){
|
||||
if (!map->data[i].item)
|
||||
continue;
|
||||
(* release)(map->data[i].item);
|
||||
if (map->data[i].item != &deleted)
|
||||
(* release)(map->data[i].item);
|
||||
map->data[i].item = NULL;
|
||||
}
|
||||
map->count = 0;
|
||||
@@ -69,7 +73,7 @@ static int map_hash(struct map *map, unsigned int key)
|
||||
|
||||
for (i = 0; i < map->size; ++i) {
|
||||
e = &map->data[idx];
|
||||
if (!e->item) {
|
||||
if (!e->item || e->item == &deleted) {
|
||||
++map->count;
|
||||
return idx;
|
||||
}
|
||||
@@ -94,8 +98,12 @@ int map_reput(struct map *map, unsigned int key, struct map_item *value,
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (old)
|
||||
*old = map->data[rc].item;
|
||||
if (old) {
|
||||
if (map->data[rc].item == &deleted)
|
||||
*old = NULL;
|
||||
else
|
||||
*old = map->data[rc].item;
|
||||
}
|
||||
map->data[rc].item = value;
|
||||
if (value)
|
||||
map->data[rc].item->key = key;
|
||||
@@ -126,7 +134,7 @@ static int map_rehash(struct map *map)
|
||||
map->count = 0;
|
||||
|
||||
for (i = 0; i < o_size; ++i){
|
||||
if (!oldt[i].item)
|
||||
if (!oldt[i].item || oldt[i].item == &deleted)
|
||||
continue;
|
||||
rc = map_put(map, oldt[i].item->key, oldt[i].item);
|
||||
if (rc < 0)
|
||||
@@ -150,11 +158,14 @@ static struct map_entry *map_find(const struct map *map, unsigned int key)
|
||||
|
||||
for (i = 0; i < map->size; ++i) {
|
||||
e = &map->data[idx];
|
||||
idx = (idx + 1) % map->size;
|
||||
|
||||
if (!e->item)
|
||||
break;
|
||||
if (e->item == &deleted)
|
||||
continue;
|
||||
if (e->item->key == key)
|
||||
return e;
|
||||
idx = (idx + 1) % map->size;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -180,7 +191,7 @@ int map_remove(struct map *map, unsigned int key)
|
||||
|
||||
e = map_find(map, key);
|
||||
if (e) {
|
||||
e->item = NULL;
|
||||
e->item = &deleted;
|
||||
--map->count;
|
||||
}
|
||||
return !e;
|
||||
@@ -196,7 +207,7 @@ static struct map_entry *map_iter_from(const struct map *map, unsigned int start
|
||||
unsigned int i = start;
|
||||
|
||||
for (; i < map->size; ++i) {
|
||||
if (map->data[i].item)
|
||||
if (map->data[i].item && map->data[i].item != &deleted)
|
||||
return &map->data[i];
|
||||
}
|
||||
return NULL;
|
||||
|
||||
Reference in New Issue
Block a user