From: Eric Mahurin Date: 2005-06-20T00:30:59+09:00 Subject: Re: GC.disable not working? --- nobu.nokada@softhome.net wrote: > Finailizers don't run immediately after the corresponding > objects get collected. The `finalizer' runs at the process > termination. This is what the documentation says about define_finalizer: --- Adds aProc as a finalizer, to be called when obj is about to be destroyed. --- So, it should run the finalizer right before the object gets collected. Running the finalizer right after would also work fine for me. Running it an arbitrary time later doesn't seem very useful if you plan on using _id2ref. It definitely doesn't just run finalizers at process termination. I also tried using Thread.critical= to control the finalizer, but it doesn't seem to make a difference: --- #!/bin/env ruby def finalizer(id) print("<") critical = Thread.critical begin Thread.critical = true print(critical ? "F" : "f") GC.enable and printf("!GC disabled while finalizing %x!",id) @ids.delete(id) ensure Thread.critical = critical end print(">") end $stdout.sync=true @ids = {} 1000.times { |i| print("[") obj = "X"*i id = obj.object_id @ids[id] = true ObjectSpace.define_finalizer(obj,method(:finalizer)) GC.start GC.disable critical = Thread.critical begin Thread.critical = true print("{") @ids.each_key { |id| begin #finalizer will still run with this instead #obj2 = "xyzabc"*i ObjectSpace._id2ref(id).size rescue RangeError print(Thread.critical ? "E" : "e") end } print("}") ensure Thread.critical = critical end GC.enable print("]") } --- I catch the RangeError (recycled object) exceptions and Thread.critical is still true ("E" gets printed), but the finalizer still happily runs. I guess GC and the finalizer are still considered to be part of the same thread even though functionally it seems like a different one. I realize that catching RangeError's would fix 99% of the problems. But, I would still be concerned about the case where the object would be GCed and then the space reclaimed by an object that looks just like it. Is it guaranteed that finalizers of the orginal object be run before its space is reclaimed? My goal is for a certain set of objects to maintain which of those objects are alive. If there are no other references to them, I want them to be GCed. For the objects still alive I need to be able to operate on them (see if any are "open" and also be able to "close" them all). Does anybody have a better implementation than above? I'm not sure if the above really works because of the "reclaimed space" case discussed above. Using WeakRef's may be a solution too. I'm hesitant to trust much of this stuff until I understand: a. When are object finalizers called? The docs don't reflect the behavior. b. What does GC.disable do? c. Is GC and/or calling object finalizers considered another thread? It sure seems like they should. __________________________________ Yahoo! Mail Stay connected, organized, and protected. Take the tour: http://tour.mail.yahoo.com/mailtour.html