From: Charles Oliver Nutter Date: 2011-01-25T16:40:43+09:00 Subject: [ruby-core:34847] Re: [Ruby 1.9-Bug#4168] WeakRef is unsafe to use in Ruby 1.9 On Mon, Jan 24, 2011 at 11:44 PM, Kurt Stephens wrote: > * Support for multiple Reference subclass instance caches. > * Working WeakReference, SoftReference and ReferenceQueue in ext/reference/reference.c > * SoftReference responds to new GC heap allocations as "memory pressure" by globally reducing all SoftReference#_mri_gc_left counts. Can you provide a short description of the complete "soft" heuristic as of this commit? Even on JVM, it's unspecified, but each JVM does spell out what constitutes a "soft" reference for them. > * Sample WeakKeyHash class using WeakReference and ReferenceQueue. > * Support for JRuby-compatible WeakReference.new(object, reference_queue) protocol. > * Removed ReferenceQueue#monitor method which cannot be supported in JRuby. > * Renamed MRI-specific methods to _mri_*. > * Optimized gc_api.c callback lists. > * Clean up the C stack after gc_api.c callbacks to avoid conservative GC pinning (might be overkill). > * Removed the ugly (and stupid) flags hacks. > * Added some basic RDOC-style comments. It's looking pretty clean. The look-alike API in JRuby will be a thin, direct layer over Java's reference logic, similar to that found in weakling. > Charles: > > ��I'm caching live Reference instances to minimize the number of References objects that must be scanned before the sweep phase. As far as I know, JVMs do not cache weak/soft references internally. The GC impact of having many weak references around is a frequent but accepted problem. > ��I'd either need to keep a doubly-linked list of References or scan all the GC heap for References (which I did not want to expose from gc.c). ��Using a lookup table (st_table in MRI) to track of live References was not much more work than a doubly-linked list and it collapses Reference.new(object) requests into a single instance. ��This is beneficial for other reasons: it reduces the total number of References to common objects and keeps the Reference#== operator simple for live instances (it's simply Reference#object_id#==). In MRI, where an object can be uniquely identified, I suppose this is fine. I'm not familiar with how other conservative GCs implement efficient weak/soft reference logic, so I'll defer. > �� Once Reference#object is sweeped, all the References to #object are no longer "live"; and are removed from cache and scheduled for ReferenceQueues after GC. ��References to immediates are never cached. ��Dead References will probably will be removed from collections or instance variables shortly thereafter (i.e.: > ��via ReferenceQueues). > > ��Why would a user want to insure that Reference.new(object) always returns a new instance, since References are/should be immutable? ��JRuby and other Rubies do not need to implement the Reference cache. Provided that there's no specified requirement that the same object get the same Reference, and as many users as want to can have their own separate reference queues receive a reference for the same object, I have no objection. > Aside: > > ��Q: Should we have a trivial HardReference class that always keeps its #object pinned, just for API consistency? I always thought this was a gap in java.lang.ref; there's an abstract Reference class, but anyone who wants to mix hard and soft references in a collection must always write their own HardReference subclass. I wanted several times for there to just be a built in HardReference I could use as a one-element indirection mechanism alongside weak, soft, and phantom references. But that's Java with static types, where I wanted to commingle weak and non-weak references in the same logic. Would this be a useful thing to have in Ruby? I don't know. When you think your tests are stabilizing, I will implement the same API in JRuby and we'll see how it looks. - Charlie