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:
parent
8870f3303c
commit
62ec3013e8
2 changed files with 43 additions and 6 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue