summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hash.c42
-rw-r--r--txr.112
2 files changed, 34 insertions, 20 deletions
diff --git a/hash.c b/hash.c
index f900806e..b1d4f748 100644
--- a/hash.c
+++ b/hash.c
@@ -601,30 +601,46 @@ static void hash_mark(val hash)
gc_mark(h->userdata);
+ if (h->count == 0) {
+ gc_mark(h->table);
+ return;
+ }
+
/* Use counts will be re-calculated by a scan of the
hash iterators which are still reachable. */
h->usecount = 0;
switch (h->flags) {
+ cnum i;
+ val iter;
case hash_weak_none:
- /* If the hash is not weak, we can simply mark the table
- vector and we are done. */
gc_mark(h->table);
- break;
+ return;
case hash_weak_keys:
+ /* Mark values only. Don't mark the table. */
+ for (i = 0; i < h->modulus; i++) {
+ for (iter = h->table->v.vec[i]; iter; iter = us_cdr(iter)) {
+ val entry = us_car(iter);
+ gc_mark(us_cdr(entry));
+ }
+ }
+ break;
case hash_weak_vals:
- case hash_weak_both:
- /* If the hash is weak, we don't touch it at this time,
- but add it to the list of reachable weak hashes,
- unless it is empty. */
- if (h->count > 0) {
- h->next = reachable_weak_hashes;
- reachable_weak_hashes = h;
- } else {
- gc_mark(h->table);
- break;
+ /* Mark keys only. Don't mark the table. */
+ for (i = 0; i < h->modulus; i++) {
+ for (iter = h->table->v.vec[i]; iter; iter = us_cdr(iter)) {
+ val entry = us_car(iter);
+ gc_mark(us_car(entry));
+ }
}
+ break;
+ case hash_weak_both:
+ /* mark nothing */
+ break;
}
+
+ h->next = reachable_weak_hashes;
+ reachable_weak_hashes = h;
}
static struct cobj_ops hash_ops = cobj_ops_init(hash_equal_op,
diff --git a/txr.1 b/txr.1
index 9c475232..e4c55f60 100644
--- a/txr.1
+++ b/txr.1
@@ -51061,13 +51061,11 @@ the weak references "lapse" in some way, which depends on what kind they are.
Hash-table weak references lapse by entry removal. When an object used
as a key in in one or more weak-key hash tables becomes unreachable, those hash
entries disappear. This happens even if the values are themselves reachable.
-That is what it means that.
-Vice versa, when an object appearing as a value in
-one or more hash-table entries in weak-value hash tables becomes unreachable,
-those entries disappear, even if the keys are reachable. When a hash table has
-both weak keys and weak values, then its entries are removed when either keys
-or values become unreachable. In other words, both the key and value must be
-reachable in order to retain the entry.
+Vice versa, when an object appearing as a value in one or more weak-value hash
+tables becomes unreachable, those entries disappear, even if the keys are
+reachable. When a hash table has both weak keys and weak values, then its
+entries are removed when either keys or values become unreachable. In other
+words, both the key and value must be reachable in order to retain the entry.
An open traversal of a hash table is performed by the
.code maphash