Copy-on-write in Ruby

Hello,

I’ve got a big object that holds references to other objects which,
in turn, hold references to other objects, which…

Now I change this object, but need a possibility to revert the change. This could be
achieved by deep-copying the object, but that’s too expensive (changes
are mostly minor and 99% copy operations will be redundant).

Is there any simple solution to this, employing the copy-on-write
principle?

···


be9

I’ve got a big object that holds references to other objects which,
in turn, hold references to other objects, which…

Now I change this object, but need a possibility to revert the change. This
could be achieved by deep-copying the object, but that’s too expensive
(changes are mostly minor and 99% copy operations will be redundant).
From your description it’s not really clear what the class is doing(does it
has methods to perform operations, or it provide access to the other objects
via attributes?).

In anycase, what you can possibly do is to define some sort of "transaction"
flag, so when raised, the object’s method will create copies of the relevant
objects on-demand(and keep references to the old ones).

Then either you commit the transaction, or rollback to the previous state.

I realise you want to avoid deep-copying, but I don’t really see a clean way
of doing it without. I have released a library that simplifies such
transactional operations, Transaction::Simple.

http://raa.ruby-lang.org/list.rhtml?name=trans-simple

I’m using this on a PDF creation library written entirely in Ruby, and it
works fast with 1.8, requiring about 180k for the first transaction level.
Other levels require more.

-austin

···

On Tue, 2 Sep 2003 17:21:31 +0900, oleg dashevskii wrote:

I’ve got a big object that holds references to other objects which, in
turn, hold references to other objects, which…

Now I change this object, but need a possibility to revert the change.
This could be achieved by deep-copying the object, but that’s too
expensive (changes are mostly minor and 99% copy operations will be
redundant).

Is there any simple solution to this, employing the copy-on-write
principle?


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.09.02
* 12.35.02

I don’t know what your object looks like exactly, but you might want to
look a little at Purely Functional
Data Structures by Chris Okasaki (should be available online if you do
search google).

For example, when you make a binary search tree structure in a
functional manner, to insert, you have to
duplicate the path to the newly inserted node. This doesn’t require
cloning the whole tree, though, so you
only need to clone log n objects.

Seems like this strategy would work for your object (and I believe there
are other examples in the book of
similar operations). You probably need a similar algorithm.

  • Dan

P.S.: a little Ruby to get the ideas flowing (written in a more
functional style out of ease)

class Node
attr_reader :v, :l, :r
def initialize(v, l, r)
@value = v
@l = l
@r = r
end
end

def insert(value, tree)
if tree.nil?
new Node value, nil, nil
elsif value < tree.v
Node.new(tree.v, insert value tree.l, tree.r)
else
Node.new(tree.v, tree.l, insert value tree.r)
end
end

The command pattern. This is used by Java’s Swing to
implement undo/redo. More details here:

Related to the Command pattern is the Memento pattern:
http://sern.ucalgary.ca/courses/SENG/443/W02/assignments/Memento/

— Idan Sofer idan@idanso.dyndns.org wrote: > >
I’ve got a big object that holds references to

···

other objects which,

in turn, hold references to other objects,
which…

Now I change this object, but need a possibility
to revert the change. This
could be achieved by deep-copying the object, but
that’s too expensive
(changes are mostly minor and 99% copy operations
will be redundant).


Want to chat instantly with your online friends? Get the FREE Yahoo!
Messenger http://uk.messenger.yahoo.com/