This is a multi-part message in MIME format.

------extPart_000_005C_01C1C999.5667FF80
Content-Type: text/plain;
	charsetso-8859-1"
Content-Transfer-Encoding: quoted-printable

I've recently been working on a project that needs weak references, and I've noticed a few things I'd like to discuss with "the list".

First of all, glancing at the "weakref.rb" code, it seems that nothing ever gets deleted from the hashes ID_MAP and ID_REV_MAP. It looks to me like a memory leak. Instead of just assigning nil to no-longer-needed entries, they should be deleted.

Secondly, it's often necessary to "neutralize" a finalizer that has been installed. An example is implementing a "weak value hash". When a value is assigned to the hash, a finalizer is installed in the value to delete its entry from the hash. If that value's weak reference is removed from the hash (either deleted or assigned over), the finalizer should be "neutralized" since it is no longer appropriate to delete its foprmer key from the hash. It's possible (but inconvenient) to do this in Ruby by messing with the environment captured by the finalizer, but the "right" thing to do is to discard the finalizer. Currently the only option is to remove *all* finalizers from the object, not individual ones, but that is dangerous because the object might have other finalizers installed for other reasons. The only current choice is to neutralize but not remove the finalizer. An object could end up with lots of unnecessary finalizers.

A possible solution for the above is that ObjectSpace::define_finalizer could return a "finalizer ID". Then ObjectSpace::undefine_finalizer could take the ID as an argument and remove only that finalizer. Then a weak value hash could undefine its finalizer (and only its finalizer) if the value is removed.

I noticed that currently ObjectSpace::define_finalizer returns the proc installed, but that might not a good ID since the same proc could be used for several finalizers (as is currently done in the WeakRef module).

Here's another thought: A frequent need (a pattern) is to have a weak reference with an associated finalization action on its referent that must be cancelled at some point (such as in the weak value hash example above). Maybe WeakRef::new could take a second, optional argument, a finalizer proc for its object. Then calling something like WeakRef#cancel_finalizer could conveniently cancel that action. WeakRef#cancel_finalizer would automatically be called when the WeakRef itself is finalized. This is a "convenience" facility, since it is possible to accomplish this in other ways.

I've implemented my own experimental WeakRef that does what I've suggested (although I didn't implement the ObjectSpace ideas, which would be helpful). I'm also trying to implement a weak value hash, which is what brought some the these perceived shortcomings to my attention. By the way, since weak value hashes and weak key hashes are often needed and nontrivial to implement, they would be nice additions to the Ruby library (both Python and Java have them).

Just some random thoughts...


Bob
------extPart_000_005C_01C1C999.5667FF80
Content-Type: text/html;
	charsetso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 5.50.4913.1100" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial size=2>I've recently been working on a project hat&nbsp;needs weak references, and I've noticed a few things I'd like to 
discuss with "the list".</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>First of all, glancing at the "weakref.rb" code, it 
seems that nothing ever gets deleted from the hashes ID_MAP and ID_REV_MAP. It 
looks to me like a memory leak. Instead of just assigning nil to 
no-longer-needed entries, they should be deleted.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Secondly, it's often necessary to "neutralize" a 
finalizer that has been installed. An example is implementing a "weak value 
hash". When a value is assigned to the hash, a finalizer is installed in the 
value to delete its entry&nbsp;from the hash. If that value's weak reference is 
removed from the hash (either deleted or assigned over), the finalizer should be 
"neutralized" since it is no longer appropriate to delete its foprmer key from 
the hash. It's possible (but inconvenient) to do this in Ruby by messing with 
the environment captured by the finalizer, but the "right" thing to do is to 
discard the finalizer. Currently the only option is to remove *all* finalizers 
from the object, not individual ones, but that is dangerous because the object 
might have other finalizers installed for other reasons. The only current choice 
is to neutralize but not remove the finalizer. An object could end up with lots 
of unnecessary finalizers.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>A possible solution for the above is that 
ObjectSpace::define_finalizer could return a "finalizer ID". Then 
ObjectSpace::undefine_finalizer could take the ID as an argument and remove only 
that finalizer. Then a weak value hash could undefine its finalizer (and only 
its finalizer) if the value is removed.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>I noticed that currently 
ObjectSpace::define_finalizer returns the proc installed, but that&nbsp;might 
not&nbsp;a good ID since the same proc could be used for several finalizers (as 
is currently done in the WeakRef module).</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Here's another&nbsp;thought: A frequent need (a 
pattern) is to have a weak reference with an associated finalization action on 
its referent that must be cancelled at some point (such as in the weak value 
hash example above). Maybe WeakRef::new could take a second, optional argument, 
a finalizer proc for its object. Then calling something like 
WeakRef#cancel_finalizer could conveniently cancel that action. 
WeakRef#cancel_finalizer would automatically be called when the WeakRef itself 
is finalized. This is a "convenience" facility, since it is possible to 
accomplish this in other ways.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>I've implemented my own experimental WeakRef that 
does what I've suggested (although I didn't implement the ObjectSpace ideas, 
which would be helpful). I'm also trying to implement a weak value hash, hich&nbsp;is what&nbsp;brought some the these perceived shortcomings to my 
attention. By the way, since weak value hashes and weak key hashes are often 
needed and nontrivial to implement, they would be nice additions to the Ruby 
library (both Python and Java have them).</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Just some random thoughts...</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Bob</FONT></DIV></BODY></HTML>

------extPart_000_005C_01C1C999.5667FF80--