From: Jim Weirich Date: 2002-02-24T10:56:04+09:00 Subject: Re: Object/Memory Management >>>>> "Sean" == Sean O'Dell writes: Sean> I considered using "yield" to wrap things up (using Sean> block_given? to enforce using blocks, throwing an exception Sean> when a block wasn't provided) to ensure this happens, but Sean> that got really messy fast in one of my apps. I had about I was going to suggest a pooled resource manager, but Dave beat me to it. And his code was cleaner and tighter than mine (as usual :-). But, on the topic of finalizers ... Sean> [...] I don't know...I just know that being able to call a Sean> finalize method *before* the object is one of the great Sean> things about OOP. You can encapsulate activities inside an Sean> object without the outside world knowing everything going on Sean> inside, and they can use it safely. Finalization is can still encapulated within the class without the outside world knowing or caring. For example, in the following code, only FinalizingObject knows that it needs to close the SillyResource when it is collected. class SillyResource def close puts "Closing a resource" end end class FinalizingObject def initialize @res = SillyResource.new ObjectSpace.define_finalizer(self, FinalizingObject.make_finalizer(@res)) end def FinalizingObject.make_finalizer(res) proc { res.close } end end def create_an_object FinalizingObject.new nil end create_an_object # Create an object and forget about it puts "Starting GC" ObjectSpace.garbage_collect # Attempt to collect (and finalize) it puts "Done with GC" gets # Pause for effect :-) One thing to remember ... finalization is run under the control of the garbage collector, not the user. Finalization should be used as a last ditch effort to make sure precious resources are *eventually* cleaned up, with emphasis on the word eventually. Sean> [...] I do come from a primarily C++ background. [...] As do I. I just realized that perhaps you are thinking of finalizers in the same way as destructors in C++. This is the wrong way to think of them. Destructors are deterministic and under the control of the programmer. Finalizers are non-deterministic (as far as when they are run) and under the control of the run time. (In fact, some languages don't even guarantee that finalizers will *ever* be run, I don't recall the exact semantics of Ruby finalizers). Use the block idiom for fine control of your resources. -- -- Jim Weirich jweirich@one.net http://w3.one.net/~jweirich --------------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)