def snapshot(*args)
      sn = Snapshot.new self, *args
      if block_given?
        begin
          yield sn
        ensure
          sn.release
        end
      else
        sn
      end
    end
def snapshot(*args)
      sn = Snapshot.new self, *args
      if block_given?
        begin
          yield sn
        ensure
          sn.release
        end
      else
        sn
      end
    end
If called with a block, yields a snapshot to the caller, and the
 snapshot is released after the block finishes. Otherwise, returns a
 snapshot and caller must call #release on the snapshot.