From: Paul Brannan Date: 2002-05-11T01:06:57+09:00 Subject: freeze and exception safety I have a class that overrides freeze: class Foo def initialize @x = Container.new end def freeze @x.each { |x| x.freeze } @x.freeze super end end However, it's possible that any of the calls to freeze, or even the call to each(), could throw an exception. In that case, I don't want to leave my object in a half-frozen state. So I do this: class Foo def freeze undo = [] begin @x.each do |x| if not x.frozen? then x.freeze undo.push proc { x.unfreeze } end end if not @x.frozen? then @x.freeze undo.push proc { @x.unfreeze } end super rescue Exception undo.each { |u| u.call } raise $!, $!.message, $!.backtrace end end end (It's actually a little more complicated than this, since I have to make sure objects get properly unfrozen even when undo.push fails). I have implemented a simple unfreeze in an extension. The problem, though, as someone pointed out to me recently, is that unfreeze is not safe, particularly on strings. The likelihood of Ruby making a copy of one of the frozen objects in @x while I'm freezing is low, but it could happen. So this is not a good solution. Is there an exception-safe way that I can freeze sub-objects? Paul