JarrettBillingsley/Croc — Issue #27: Revisit table-weakref interaction
Author: JarrettBillingsley
Created: 2011-11-08 06:13:44+00:00
State: open

Tables are defined to interact with weakrefs in a certain way: if a table key-value pair has a weakref as either the key or the value, and that weakref goes null, then that key-value pair is removed from the table. This behavior was easy to implement with the old tracing collector which looked at every key-value pair in every table in existence every cycle. But the new collector won't even look at tables unless they're modified by the mutator since the last collection. This makes it more difficult to keep track of which tables need to be normalized (have their null weak entries removed). This has made me reconsider the way tables and weakrefs interact.

There are a number of suboptimal problems with it:

* It incurs a performance penalty on EVERY table. In order to keep track of which tables need to be tracked for weak entries, every assignment to a table slot has to be checked for weakref objects. This is an unacceptable penalty since most tables don't need this behavior.
* In virtually every case, you won't mix weak key-value pairs with non-weak ones. You want ALL the keys or ALL the values or ALL of both to be weak. Forgetting to weakref an item on insertion leads to annoying bugs.
* Related to the above point, it's annoying to have to put weakref() around every key/value/both, or having to deref() when accessing. More tedium, boilerplate, and bugs.

I considered getting rid of weakref objects entirely and switching to weak tables like Lua has, but there are actual legitimate uses for lone weakref objects, especially since the new GC performs worse with cyclic data, and using weakrefs to reduce cycles (such as using them for child-to-parent pointers) can improve performance. Requiring the use of a table object to keep a single weak reference would be silly.

So I think there should be weakrefs AND weak tables. Weak tables could be created with functions like `hash.weakKeyTable()` and similar; table objects would have bits indicating whether they had weak keys, values, or both, and could be kept in an internal (weak, haha) hash to make sure they could be normalized after GC. They could internally use weakref objects to simplify implementation, and automatically wrap/unwrap them upon access.