summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-04-05 04:17:17 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-04-05 05:11:12 +0300
commit4a088f4b6168dd8ed8edc70e82bc695d3879abec (patch)
tree12d61bc3dcde58264edeccf4a5484f8466a2472c
parenta0d32991ed57ebbbb8c9207dab3223b12ca4aa44 (diff)
downloadmicropython-4a088f4b6168dd8ed8edc70e82bc695d3879abec.tar.gz
micropython-4a088f4b6168dd8ed8edc70e82bc695d3879abec.zip
map: When removing a key, don't NULL the entry, but mark as deleted.
When searching next time, such entry should be just skipped, not terminate the search. It's known that marking techique is not efficient at the presense of many removes, but namespace usage should not require many deletes, and as for user dictionaries - well, open addressing map table with linear rehashing and load factor of ~1 is not particularly efficient at all ;-). TODO: May consider "shift other entries in cluster" approach as an alternative.
-rw-r--r--py/map.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/py/map.c b/py/map.c
index 301ea51ae4..6411f8adea 100644
--- a/py/map.c
+++ b/py/map.c
@@ -127,17 +127,20 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
mp_map_rehash(map);
// restart the search for the new element
pos = hash % map->alloc;
+ continue;
} else {
map->used += 1;
elem->key = index;
+ elem->value = NULL;
if (!MP_OBJ_IS_QSTR(index)) {
map->all_keys_are_qstrs = 0;
}
return elem;
}
- } else {
+ } else if (elem->value == NULL) {
return NULL;
}
+ // Otherwise it's just entry marked as deleted, so continue with next one
} else if (elem->key == index || (!map->all_keys_are_qstrs && mp_obj_equal(elem->key, index))) {
// found it
/* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
@@ -152,14 +155,15 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
retval->key = elem->key;
retval->value = elem->value;
elem->key = NULL;
- elem->value = NULL;
+ // elem->key = NULL && elem->value != NULL means "marked deleted"
+ // assume value indeed never NULL
return retval;
}
return elem;
- } else {
- // not yet found, keep searching in this table
- pos = (pos + 1) % map->alloc;
}
+
+ // not yet found, keep searching in this table
+ pos = (pos + 1) % map->alloc;
}
}