diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-07-20 23:17:59 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-07-20 23:17:59 -0700 |
commit | a6f0c72306da0c628be9e180288f79fbf29bfa57 (patch) | |
tree | c47d4f40f9d3624f28277db5017db526178feef4 | |
parent | 5e6dca52d383e649bc6e39de26ffa2474a2b9814 (diff) | |
download | txr-a6f0c72306da0c628be9e180288f79fbf29bfa57.tar.gz txr-a6f0c72306da0c628be9e180288f79fbf29bfa57.tar.bz2 txr-a6f0c72306da0c628be9e180288f79fbf29bfa57.zip |
hash: change semantics of weak-both hash tables.
From now on, hash tables with both weak keys and values have
dijunctive retention semantics. If either the key or value of
an entry is reachable, then the entry stays. This is subject
to compatibility.
* hash.c (do_weak_tables): Expire an entry if neither the key
nor the value is reachable. In 266 or lower compatibility
mode, expire an entry if either the key or value is
unreachable, like before.
* txr.1: Document the change, with compat notes. Add a
cautionary note about the referencing issue which defeats weak
key or weak value tables.
-rw-r--r-- | hash.c | 56 | ||||
-rw-r--r-- | txr.1 | 20 |
2 files changed, 57 insertions, 19 deletions
@@ -1274,24 +1274,48 @@ static void do_weak_tables(void) case hash_weak_both: /* Sweep through all entries. Delete any which have keys or values that are garbage. */ - for (i = 0; i < h->modulus; i++) { - val *pchain = &h->table->v.vec[i]; - val *iter; - - for (iter = pchain; *iter; ) { - val entry = us_car(*iter); - if (!gc_is_reachable(us_car(entry)) || !gc_is_reachable(us_cdr(entry))) - { - *iter = us_cdr(*iter); + if (opt_compat && opt_compat <= 266) { + for (i = 0; i < h->modulus; i++) { + val *pchain = &h->table->v.vec[i]; + val *iter; + + for (iter = pchain; *iter; ) { + val entry = us_car(*iter); + if (!gc_is_reachable(us_car(entry)) || !gc_is_reachable(us_cdr(entry))) + { + *iter = us_cdr(*iter); #if CONFIG_EXTRA_DEBUGGING - if (!gc_is_reachable(us_car(entry)) && us_car(entry) == break_obj) - breakpt(); - if (!gc_is_reachable(us_cdr(entry)) && us_cdr(entry) == break_obj) - breakpt(); + if (!gc_is_reachable(us_car(entry)) && us_car(entry) == break_obj) + breakpt(); + if (!gc_is_reachable(us_cdr(entry)) && us_cdr(entry) == break_obj) + breakpt(); #endif - } else { - iter = us_cdr_p(*iter); - c++; + } else { + iter = us_cdr_p(*iter); + c++; + } + } + } + } else { + for (i = 0; i < h->modulus; i++) { + val *pchain = &h->table->v.vec[i]; + val *iter; + + for (iter = pchain; *iter; ) { + val entry = us_car(*iter); + if (!gc_is_reachable(us_car(entry)) && !gc_is_reachable(us_cdr(entry))) + { + *iter = us_cdr(*iter); +#if CONFIG_EXTRA_DEBUGGING + if (!gc_is_reachable(us_car(entry)) && us_car(entry) == break_obj) + breakpt(); + if (!gc_is_reachable(us_cdr(entry)) && us_cdr(entry) == break_obj) + breakpt(); +#endif + } else { + iter = us_cdr_p(*iter); + c++; + } } } } @@ -51063,9 +51063,16 @@ 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. 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. +reachable. When a hash table has both weak keys and weak values, then an +entry is removed when neither its key nor its value is reachable. In other +words, if either the key or value is reachable, the entry is retained. +Note: this behavior differed in \*(TX 266 and earlier versions. + +If the keys of a weak-key hash table are reachable from the values, or if the +values of a weak-key hash table are reachable from the keys, then the weak +semantics is defeated for the affected entries: the hash table retains those +entries as if it were an ordinary table. A hash table with both weak keys and +values does not have this issue. An open traversal of a hash table is performed by the .code maphash @@ -83081,6 +83088,13 @@ of these version values, the described behaviors are provided if is given an argument which is equal or lower. For instance .code "-C 103" selects the behaviors described below for version 105, but not those for 102. +.IP 266 +Until \*(TX 266, hash tables with both weak values and keys are subject to +a conjunctive rule for entry retention: entries are retained if both the +key and value are reachable objects. If either the key or value is unreachable, +the entry is eligible for removal. The behavior changed in favor of a disjunctive +rule: the hash entry is retained if either the key or value is reachable. +A compatibility option value of 266 or lower restores the old behavior. .IP 265 Until \*(TX 265, the .code with-resources |