1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 12:21:25 -08:00

Need to check hash table for staleness when deleting a key.

Copied from Perforce
 Change: 180354
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2012-11-05 23:29:23 +00:00
parent 8870f3303c
commit 62ec3013e8
2 changed files with 43 additions and 6 deletions

View file

@ -993,7 +993,10 @@ static void table_delete(obj_t tbl, obj_t key)
{
struct bucket_s *b;
assert(TYPE(tbl) == TYPE_TABLE);
b = buckets_find(tbl, tbl->table.buckets, key, &tbl->table.ld);
b = buckets_find(tbl, tbl->table.buckets, key, NULL);
if ((b == NULL || b->key == NULL) && mps_ld_isstale(&tbl->table.ld, arena, key)) {
b = table_rehash(tbl, tbl->table.buckets->buckets.length, key);
}
if (b != NULL && b->key != NULL) {
b->key = obj_deleted;
++ tbl->table.buckets->buckets.deleted;

View file

@ -332,11 +332,6 @@ any of its keys.
looked up, when the staleness will be discovered. After all, it may
never be looked up.
.. note::
Don't forget that deleting a key from an address-based hash table
also results in a dependency on its location.
If you look up a key in an address-based hash table and fail to find it
there, that might be because the table's dependency on the location of
the key is stale: that is, if the garbage collector moved the key. The
@ -435,6 +430,45 @@ the location dependency becomes stale and the table has to be rehashed.
move in the collection, so it's not found in the table, and that
causes :c:func:`mps_ld_isstale` to be tested.
Don't forget to check the location dependency for staleness if you are
about to delete a key from a hash table but discover that it's not
there. In the toy Scheme interpreter, deletion looks like this:
.. code-block:: c
:emphasize-lines: 6
static void table_delete(obj_t tbl, obj_t key)
{
struct bucket_s *b;
assert(TYPE(tbl) == TYPE_TABLE);
b = buckets_find(tbl, tbl->table.buckets, key, NULL);
if ((b == NULL || b->key == NULL) && mps_ld_isstale(&tbl->table.ld, arena, key)) {
b = table_rehash(tbl, tbl->table.buckets->buckets.length, key);
}
if (b != NULL && b->key != NULL) {
b->key = obj_deleted;
++ tbl->table.buckets->buckets.deleted;
}
}
Again, by adding the line ``puts("stale!");`` after
:c:func:`mps_ld_isstale` returns true, it's possible to see when the
location dependency becomes stale and the table has to be rehashed:
.. code-block:: none
MPS Toy Scheme Example
13248, 0> (define ht (make-eq-hashtable))
ht
13624, 0> (hashtable-set! ht 'one 1)
13808, 0> (gc)
13832, 1> (hashtable-delete! ht 'one)
stale!
14112, 1> ht
#[hashtable]
.. topics::
:ref:`topic-location`.