[gambit-list] Do I understand weak references/tables properly?
feeley at iro.umontreal.ca
Mon Nov 14 09:35:25 EST 2011
On 2011-11-14, at 12:41 AM, Adrien Piérard wrote:
> I have the following code:
> ;; create a table with weak keys
> (define t (make-table weak-keys: #t))
> ;; create an element, and store it somewhere.
> (define v (vector (cons 42 42)))
> ;; Use that element as a key for a hash-table
> (table-set! t (vector-ref v 0) "quarante-deux")
> ;; make a will to be called when the object is to be garbage collected
> (make-will (vector-ref v 0)
> (lambda (x)
> (display `(deleting ,x))
> ;; show the associated value in the table
> (display (table-ref t (vector-ref v 0)))
> ;; delete the key
> (vector-set! v 0 #f)
> ;; call the GC
> ;; verify the table is empty
> (display (table->list t))
> The output puzzles me:
> (deleting (42 . 42))
> (((42 . 42) . quarante-deux))
> The action of the will is executed, so this means that my key has been GC'd.
> So, why does it still show up in my table? Isn't (##gc) supposed to
> remove the key/value from the table, now that the key is not strongly
> accessible any more?
You are being fooled by the message in the trace printed by the will's action procedure. It shouldn't say "(deleting (42 . 42))"; it should say "(the-gc-has-discovered-this-is-not-strongly-reachable (42 . 42))". After all, look at the signature of the action procedure... its only parameter is the object that has become not strongly reachable. Note that the action procedure is called immediately after the garbage-collection which detected that the object has become not strongly reachable. Note also that by calling the action procedure, the object becomes strongly reachable, after all you pass it to display (it could stay strongly reachable for a long time, but in this case it is only for the extent of the action procedure). As a consequence the garbage-collector can't reclaim the object right away. It must wait until the object is not strongly reachable *and* all of its wills have been executed. Typically this happens at the next garbage-collection. In your program, if you call (##gc) again, you will see that your table has been emptied. Also, if you don't call make-will on the object, the table will be empty after the first garbage-collection.
Was this passage of the documentation not clear?
"Note that the testator object will not be reclaimed during the garbage collection that determined executability of the will. It is only when an object is not reachable from the roots that it is reclaimed by the garbage collector."
More information about the Gambit-list