weak hash tables: fix regression with gethash

while fixing problem in sethash I've introduced another one in
gethash. A comment is added to prevent such mistakes.
This commit is contained in:
Daniel Kochmański 2019-05-28 09:08:16 +02:00
parent 0c198105be
commit 58da0f8713
2 changed files with 48 additions and 10 deletions

View file

@ -605,7 +605,9 @@ normalize_weak_key_and_value_entry(struct ecl_hashtable_entry *e) {
static void *
normalize_weak_key_or_value_entry(struct ecl_hashtable_entry *e) {
if ((e->key = e->key->weak.value) || (e->value = e->value->weak.value))
e->key = e->key->weak.value;
e->value = e->value->weak.value;
if (e->key || e->value)
return (void*)e;
else
return 0;
@ -716,14 +718,10 @@ _ecl_gethash_weak(cl_object key, cl_object hashtable, cl_object def)
if (aux->key == OBJNULL) {
return def;
}
switch (hashtable->hash.weak) {
case ecl_htt_weak_value:
case ecl_htt_weak_key_or_value:
case ecl_htt_weak_key_and_value:
return si_weak_pointer_value(aux->value);
default:
return aux->value;
}
/* _ecl_weak_hash_loop "normalizes" entries. That means that
si_weak_pointer_value shouldn't be called because value is
already "unwrapped". -- jd 2019-05-28 */
return aux->value;
}
static cl_object

View file

@ -62,8 +62,48 @@
(is k 'random-state)
(is v 'random-state))))
;;; For some corner cases weak hash-tables returned unnormalized
;;; values. Then we had a regression in gethash which tried to
;;; normalize already normalized values. We clearly need a simple test
;;; whenever hash tables work correctly.
(test hash-tables.weak-faithful
(let ((hts (list (make-hash-table :weakness nil)
(make-hash-table :weakness :key)
(make-hash-table :weakness :value)
(make-hash-table :weakness :key-or-value)
(make-hash-table :weakness :key-and-value)))
(keys (list :a :b :c))
(vals (list :x :y :z)))
;; ensure basic set/get on null entries
(mapc (lambda (ht)
(mapc (lambda (k v)
(is (null (gethash k ht)))
(setf (gethash k ht) v)
(is (eql (gethash k ht) v)
"gethash ~s = ~s, should be ~s, weakness is ~s"
k (gethash k ht) v (ext:hash-table-weakness ht)))
keys vals))
hts)
;; ensure that values get updated for a known key
(mapc (lambda (ht)
(setf (gethash :c ht) :z-prim)
(is (eql (gethash :c ht) :z-prim)))
hts)
;; ensure maphash
(mapc (lambda (ht)
(let ((i 0))
(maphash (lambda (k v)
(incf i)
(is (eql v (ecase k
(:a :x)
(:b :y)
(:c :z-prim)))))
ht)
(is (= i 3))))
hts)))
(test hash-tables.weak-err
(signals simple-type-error (make-hash-table :weakness :whatever)))
(signals simple-type-error (make-hash-table :weakness :whatever)))
;;; Synchronization