NAME

Tie::CopyOnWrite - copy-on-write semantics for Perl data structures using tie


SYNOPSIS

        use Tie::CopyOnWrite;
        
        $foo = "foo" x 10;
        copyonwrite $foo => $bar;
        # At this point, there is only one copy of the string in memory,
        # accessible through the tie'd variables $foo and $bar.
        print "$foo\n$bar\n" if tied $foo == tied $bar;
        
        # Only when one of them is modified do we actually copy the data:
        $bar .= "bar"; # $bar is untie'd at this point
        print "$foo\n$bar\n";


DESCRIPTION

If data is frequently copied but infrequently modified, it can make sense to defer the actual copy operation until such time as one of the "copies" is modified. Until that time, a data structure "copied" using one of the functions in this module is actually just a reference to the original data; that fact is hidden from its user however, who can access the data just as she would with an ordinary copy, thanks to Perl's tie feature.


FUNCTIONS

All six functions documented here are exported by default.

copyonwrite $original => $copy

Both $original and $copy become tied scalars referring to the value which was originally in the ordinary scalar $original. When (if) the value of one of these variables is changed, it will be demoted to an ordinary scalar; only then will the data actually be copied.

copyonwrite_array @original => @copy

Both @original and @copy become tied arrays referring to the list which was originally in the ordinary array @original. When (if) one of these variables is modified (by adding, removing or changing an array element), it will be demoted to an ordinary array; only then will the data actually be copied.

The actual elements in the array are not tied, so modifying a nested structure referred to by a reference contained in a tied array will cause the same modification in its "copy." If you want to avoid that, use deep_copyonwrite_array.

copyonwrite_hash %original => %copy

Both %original and %copy become tied hashes referring to the hash which was originally in the ordinary variable %original. When (if) one of these variables is modified (by adding, removing or changing a hash element), it will be demoted to an ordinary hash; only then will the data actually be copied.

The actual elements in the hash are not tied, so modifying a nested structure referred to by a reference contained in a tied hash will cause the same modification in its "copy." If you want to avoid that, use deep_copyonwrite_hash.

deep_copyonwrite_array @original => @copy

Both @original and @copy are ordinary arrays, and remain ordinary arrays after this function is called. Their scalar elements, on the other hand, become tied scalars referring to the scalar elements taken from the @original array.

Nested structures are handled properly, so @original could be an array of arrays, or an array of hashes, or an array of hashes of arrays, or whatever, and only the "leaves" of the "tree" will be tied. Any reference that is not to a scalar, array or hash will be copied in the normal way, resulting in an old-fashioned alias.

deep_copyonwrite_hash %original => %copy

Both %original and %copy are ordinary hashes, and remain ordinary hashes after this function is called. Their scalar elements, on the other hand, become tied scalars referring to the scalar elements taken from the %original hash.

Nested structures are handled properly, so %original could be a hash of arrays, or a hash of hashes, or a hash of hashes of arrays, or whatever, and only the "leaves" of the "tree" will be tied. Any reference that is not to a scalar, array or hash will be copied in the normal way, resulting in an old-fashioned alias.

deep_copyonwrite $original => $copy

This is a generalisation of deep_copyonwrite_array and deep_copyonwrite_hash which expects a reference to any supported type of structure.


CAVEATS

        $foo = "foo" x 100;
        copyonwrite $foo => $bar;
        $baz = $bar;

In the above code snippet, there are two real copies of the string in memory: the one tied to $foo and $bar, and the one in the ordinary variable $baz. The assignment operation has dropped the tie and resulted in a plain old copy, although $foo and $bar remain tied.

This actuality can express itself in more subtle ways:

        sub mycopy {
                copyonwrite $original => my $copy;
                return $copy; # doesn't do what you wanted
        }
        if (tied mycopy()) { print "this won't be printed" }

This can be worked around in several ways; for example:

        sub mycopy {
                copyonwrite $original => $_[0];
        }
        mycopy($copy);
        if (tied $copy) { print "this will be printed" }


BUGS

The deep-copy functions can not properly handle self-referential structures, or an original structure that contains references to the copy structure.


TODO

Possible future extensions:


AUTHOR

Copyright 2009 the Oktalist <mat@oktalist.com>


COPYING

This module is free software; you can redistribute in and/or modify it under the same terms as Perl itself.