This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Run vms/vms_yfix.pl, should have done that after changing
[perl5.git] / ext / Storable / Storable.pm
CommitLineData
9e21b3d0 1;# $Id: Storable.pm,v 1.0 2000/09/01 19:40:41 ram Exp $
7a6a85bf
RG
2;#
3;# Copyright (c) 1995-2000, Raphael Manfredi
4;#
9e21b3d0
JH
5;# You may redistribute only under the same terms as Perl 5, as specified
6;# in the README file that comes with the distribution.
7a6a85bf
RG
7;#
8;# $Log: Storable.pm,v $
9e21b3d0
JH
9;# Revision 1.0 2000/09/01 19:40:41 ram
10;# Baseline for first official release.
7a6a85bf
RG
11;#
12
13require DynaLoader;
14require Exporter;
15package Storable; @ISA = qw(Exporter DynaLoader);
16
17@EXPORT = qw(store retrieve);
18@EXPORT_OK = qw(
9e21b3d0 19 nstore store_fd nstore_fd fd_retrieve
7a6a85bf
RG
20 freeze nfreeze thaw
21 dclone
9e21b3d0 22 retrieve_fd
dd19458b 23 lock_store lock_nstore lock_retrieve
7a6a85bf
RG
24);
25
26use AutoLoader;
27use vars qw($forgive_me $VERSION);
28
dd19458b 29$VERSION = '1.003';
7a6a85bf
RG
30*AUTOLOAD = \&AutoLoader::AUTOLOAD; # Grrr...
31
32#
33# Use of Log::Agent is optional
34#
35
36eval "use Log::Agent";
37
38unless (defined @Log::Agent::EXPORT) {
39 eval q{
40 sub logcroak {
41 require Carp;
42 Carp::croak(@_);
43 }
44 };
45}
46
dd19458b
JH
47#
48# They might miss :flock in Fcntl
49#
50
51BEGIN {
52 require Fcntl;
53 if (exists $Fcntl::EXPORT_TAGS{'flock'}) {
54 Fcntl->import(':flock');
55 } else {
56 eval q{
57 sub LOCK_SH () {1}
58 sub LOCK_EX () {2}
59 };
60 }
61}
62
7a6a85bf
RG
63sub logcroak;
64
9e21b3d0 65sub retrieve_fd { &fd_retrieve } # Backward compatibility
cb3d9de5 66
7a6a85bf
RG
67bootstrap Storable;
681;
69__END__
70
71#
72# store
73#
74# Store target object hierarchy, identified by a reference to its root.
75# The stored object tree may later be retrieved to memory via retrieve.
76# Returns undef if an I/O error occurred, in which case the file is
77# removed.
78#
79sub store {
dd19458b 80 return _store(\&pstore, @_, 0);
7a6a85bf
RG
81}
82
83#
84# nstore
85#
86# Same as store, but in network order.
87#
88sub nstore {
dd19458b
JH
89 return _store(\&net_pstore, @_, 0);
90}
91
92#
93# lock_store
94#
95# Same as store, but flock the file first (advisory locking).
96#
97sub lock_store {
98 return _store(\&pstore, @_, 1);
99}
100
101#
102# lock_nstore
103#
104# Same as nstore, but flock the file first (advisory locking).
105#
106sub lock_nstore {
107 return _store(\&net_pstore, @_, 1);
7a6a85bf
RG
108}
109
110# Internal store to file routine
111sub _store {
112 my $xsptr = shift;
113 my $self = shift;
dd19458b 114 my ($file, $use_locking) = @_;
7a6a85bf 115 logcroak "not a reference" unless ref($self);
dd19458b 116 logcroak "too many arguments" unless @_ == 2; # No @foo in arglist
7a6a85bf
RG
117 local *FILE;
118 open(FILE, ">$file") || logcroak "can't create $file: $!";
119 binmode FILE; # Archaic systems...
dd19458b 120 if ($use_locking) {
f567092b
PFI
121 if ($^O eq 'dos') {
122 require Carp;
123 Carp::carp "Storable::lock_store: fcntl/flock emulation broken on $^O\n";
124 return undef;
125 }
dd19458b
JH
126 flock(FILE, LOCK_EX) ||
127 logcroak "can't get exclusive lock on $file: $!";
128 truncate FILE, 0;
129 # Unlocking will happen when FILE is closed
130 }
7a6a85bf
RG
131 my $da = $@; # Don't mess if called from exception handler
132 my $ret;
133 # Call C routine nstore or pstore, depending on network order
134 eval { $ret = &$xsptr(*FILE, $self) };
135 close(FILE) or $ret = undef;
136 unlink($file) or warn "Can't unlink $file: $!\n" if $@ || !defined $ret;
137 logcroak $@ if $@ =~ s/\.?\n$/,/;
138 $@ = $da;
139 return $ret ? $ret : undef;
140}
141
142#
143# store_fd
144#
145# Same as store, but perform on an already opened file descriptor instead.
146# Returns undef if an I/O error occurred.
147#
148sub store_fd {
149 return _store_fd(\&pstore, @_);
150}
151
152#
153# nstore_fd
154#
155# Same as store_fd, but in network order.
156#
157sub nstore_fd {
158 my ($self, $file) = @_;
159 return _store_fd(\&net_pstore, @_);
160}
161
162# Internal store routine on opened file descriptor
163sub _store_fd {
164 my $xsptr = shift;
165 my $self = shift;
166 my ($file) = @_;
167 logcroak "not a reference" unless ref($self);
168 logcroak "too many arguments" unless @_ == 1; # No @foo in arglist
169 my $fd = fileno($file);
170 logcroak "not a valid file descriptor" unless defined $fd;
171 my $da = $@; # Don't mess if called from exception handler
172 my $ret;
173 # Call C routine nstore or pstore, depending on network order
174 eval { $ret = &$xsptr($file, $self) };
175 logcroak $@ if $@ =~ s/\.?\n$/,/;
176 $@ = $da;
177 return $ret ? $ret : undef;
178}
179
180#
181# freeze
182#
183# Store oject and its hierarchy in memory and return a scalar
184# containing the result.
185#
186sub freeze {
187 _freeze(\&mstore, @_);
188}
189
190#
191# nfreeze
192#
193# Same as freeze but in network order.
194#
195sub nfreeze {
196 _freeze(\&net_mstore, @_);
197}
198
199# Internal freeze routine
200sub _freeze {
201 my $xsptr = shift;
202 my $self = shift;
203 logcroak "not a reference" unless ref($self);
204 logcroak "too many arguments" unless @_ == 0; # No @foo in arglist
205 my $da = $@; # Don't mess if called from exception handler
206 my $ret;
207 # Call C routine mstore or net_mstore, depending on network order
208 eval { $ret = &$xsptr($self) };
209 logcroak $@ if $@ =~ s/\.?\n$/,/;
210 $@ = $da;
211 return $ret ? $ret : undef;
212}
213
214#
215# retrieve
216#
217# Retrieve object hierarchy from disk, returning a reference to the root
218# object of that tree.
219#
220sub retrieve {
dd19458b
JH
221 _retrieve($_[0], 0);
222}
223
224#
225# lock_retrieve
226#
227# Same as retrieve, but with advisory locking.
228#
229sub lock_retrieve {
230 _retrieve($_[0], 1);
231}
232
233# Internal retrieve routine
234sub _retrieve {
235 my ($file, $use_locking) = @_;
7a6a85bf 236 local *FILE;
dd19458b 237 open(FILE, $file) || logcroak "can't open $file: $!";
7a6a85bf
RG
238 binmode FILE; # Archaic systems...
239 my $self;
240 my $da = $@; # Could be from exception handler
dd19458b 241 if ($use_locking) {
f567092b
PFI
242 if ($^O eq 'dos') {
243 require Carp;
244 Carp::carp "Storable::lock_retrieve: fcntl/flock emulation broken on $^O\n";
245 return undef;
246 }
247 flock(FILE, LOCK_SH) ||
248 logcroak "can't get shared lock on $file: $!";
dd19458b
JH
249 # Unlocking will happen when FILE is closed
250 }
7a6a85bf
RG
251 eval { $self = pretrieve(*FILE) }; # Call C routine
252 close(FILE);
253 logcroak $@ if $@ =~ s/\.?\n$/,/;
254 $@ = $da;
255 return $self;
256}
257
258#
9e21b3d0 259# fd_retrieve
7a6a85bf
RG
260#
261# Same as retrieve, but perform from an already opened file descriptor instead.
262#
9e21b3d0 263sub fd_retrieve {
7a6a85bf
RG
264 my ($file) = @_;
265 my $fd = fileno($file);
266 logcroak "not a valid file descriptor" unless defined $fd;
267 my $self;
268 my $da = $@; # Could be from exception handler
269 eval { $self = pretrieve($file) }; # Call C routine
270 logcroak $@ if $@ =~ s/\.?\n$/,/;
271 $@ = $da;
272 return $self;
273}
274
275#
276# thaw
277#
278# Recreate objects in memory from an existing frozen image created
279# by freeze. If the frozen image passed is undef, return undef.
280#
281sub thaw {
282 my ($frozen) = @_;
283 return undef unless defined $frozen;
284 my $self;
285 my $da = $@; # Could be from exception handler
286 eval { $self = mretrieve($frozen) }; # Call C routine
287 logcroak $@ if $@ =~ s/\.?\n$/,/;
288 $@ = $da;
289 return $self;
290}
291
292=head1 NAME
293
294Storable - persistency for perl data structures
295
296=head1 SYNOPSIS
297
298 use Storable;
299 store \%table, 'file';
300 $hashref = retrieve('file');
301
302 use Storable qw(nstore store_fd nstore_fd freeze thaw dclone);
303
304 # Network order
305 nstore \%table, 'file';
306 $hashref = retrieve('file'); # There is NO nretrieve()
307
308 # Storing to and retrieving from an already opened file
309 store_fd \@array, \*STDOUT;
310 nstore_fd \%table, \*STDOUT;
9e21b3d0
JH
311 $aryref = fd_retrieve(\*SOCKET);
312 $hashref = fd_retrieve(\*SOCKET);
7a6a85bf
RG
313
314 # Serializing to memory
315 $serialized = freeze \%table;
316 %table_clone = %{ thaw($serialized) };
317
318 # Deep (recursive) cloning
319 $cloneref = dclone($ref);
320
dd19458b
JH
321 # Advisory locking
322 use Storable qw(lock_store lock_nstore lock_retrieve)
323 lock_store \%table, 'file';
324 lock_nstore \%table, 'file';
325 $hashref = lock_retrieve('file');
326
7a6a85bf
RG
327=head1 DESCRIPTION
328
329The Storable package brings persistency to your perl data structures
330containing SCALAR, ARRAY, HASH or REF objects, i.e. anything that can be
331convenientely stored to disk and retrieved at a later time.
332
333It can be used in the regular procedural way by calling C<store> with
334a reference to the object to be stored, along with the file name where
335the image should be written.
336The routine returns C<undef> for I/O problems or other internal error,
337a true value otherwise. Serious errors are propagated as a C<die> exception.
338
339To retrieve data stored to disk, use C<retrieve> with a file name,
340and the objects stored into that file are recreated into memory for you,
341a I<reference> to the root object being returned. In case an I/O error
342occurs while reading, C<undef> is returned instead. Other serious
343errors are propagated via C<die>.
344
345Since storage is performed recursively, you might want to stuff references
346to objects that share a lot of common data into a single array or hash
347table, and then store that object. That way, when you retrieve back the
348whole thing, the objects will continue to share what they originally shared.
349
350At the cost of a slight header overhead, you may store to an already
351opened file descriptor using the C<store_fd> routine, and retrieve
9e21b3d0 352from a file via C<fd_retrieve>. Those names aren't imported by default,
7a6a85bf
RG
353so you will have to do that explicitely if you need those routines.
354The file descriptor you supply must be already opened, for read
355if you're going to retrieve and for write if you wish to store.
356
357 store_fd(\%table, *STDOUT) || die "can't store to stdout\n";
9e21b3d0 358 $hashref = fd_retrieve(*STDIN);
7a6a85bf
RG
359
360You can also store data in network order to allow easy sharing across
361multiple platforms, or when storing on a socket known to be remotely
362connected. The routines to call have an initial C<n> prefix for I<network>,
363as in C<nstore> and C<nstore_fd>. At retrieval time, your data will be
364correctly restored so you don't have to know whether you're restoring
dd19458b
JH
365from native or network ordered data. Double values are stored stringified
366to ensure portability as well, at the slight risk of loosing some precision
367in the last decimals.
7a6a85bf 368
9e21b3d0 369When using C<fd_retrieve>, objects are retrieved in sequence, one
7a6a85bf
RG
370object (i.e. one recursive tree) per associated C<store_fd>.
371
372If you're more from the object-oriented camp, you can inherit from
373Storable and directly store your objects by invoking C<store> as
374a method. The fact that the root of the to-be-stored tree is a
375blessed reference (i.e. an object) is special-cased so that the
376retrieve does not provide a reference to that object but rather the
377blessed object reference itself. (Otherwise, you'd get a reference
378to that blessed object).
379
380=head1 MEMORY STORE
381
382The Storable engine can also store data into a Perl scalar instead, to
383later retrieve them. This is mainly used to freeze a complex structure in
384some safe compact memory place (where it can possibly be sent to another
385process via some IPC, since freezing the structure also serializes it in
386effect). Later on, and maybe somewhere else, you can thaw the Perl scalar
387out and recreate the original complex structure in memory.
388
389Surprisingly, the routines to be called are named C<freeze> and C<thaw>.
390If you wish to send out the frozen scalar to another machine, use
391C<nfreeze> instead to get a portable image.
392
393Note that freezing an object structure and immediately thawing it
394actually achieves a deep cloning of that structure:
395
396 dclone(.) = thaw(freeze(.))
397
398Storable provides you with a C<dclone> interface which does not create
399that intermediary scalar but instead freezes the structure in some
400internal memory space and then immediatly thaws it out.
401
dd19458b
JH
402=head1 ADVISORY LOCKING
403
404The C<lock_store> and C<lock_nstore> routine are equivalent to C<store>
405and C<nstore>, only they get an exclusive lock on the file before
406writing. Likewise, C<lock_retrieve> performs as C<retrieve>, but also
407gets a shared lock on the file before reading.
408
409Like with any advisory locking scheme, the protection only works if
410you systematically use C<lock_store> and C<lock_retrieve>. If one
411side of your application uses C<store> whilst the other uses C<lock_retrieve>,
412you will get no protection at all.
413
414The internal advisory locking is implemented using Perl's flock() routine.
415If your system does not support any form of flock(), or if you share
416your files across NFS, you might wish to use other forms of locking by
417using modules like LockFile::Simple which lock a file using a filesystem
418entry, instead of locking the file descriptor.
419
7a6a85bf
RG
420=head1 SPEED
421
422The heart of Storable is written in C for decent speed. Extra low-level
423optimization have been made when manipulating perl internals, to
424sacrifice encapsulation for the benefit of a greater speed.
425
426=head1 CANONICAL REPRESENTATION
427
428Normally Storable stores elements of hashes in the order they are
429stored internally by Perl, i.e. pseudo-randomly. If you set
430C<$Storable::canonical> to some C<TRUE> value, Storable will store
431hashes with the elements sorted by their key. This allows you to
432compare data structures by comparing their frozen representations (or
433even the compressed frozen representations), which can be useful for
434creating lookup tables for complicated queries.
435
436Canonical order does not imply network order, those are two orthogonal
437settings.
438
439=head1 ERROR REPORTING
440
441Storable uses the "exception" paradigm, in that it does not try to workaround
442failures: if something bad happens, an exception is generated from the
443caller's perspective (see L<Carp> and C<croak()>). Use eval {} to trap
444those exceptions.
445
446When Storable croaks, it tries to report the error via the C<logcroak()>
447routine from the C<Log::Agent> package, if it is available.
448
449=head1 WIZARDS ONLY
450
451=head2 Hooks
452
453Any class may define hooks that will be called during the serialization
454and deserialization process on objects that are instances of that class.
455Those hooks can redefine the way serialization is performed (and therefore,
456how the symetrical deserialization should be conducted).
457
458Since we said earlier:
459
460 dclone(.) = thaw(freeze(.))
461
462everything we say about hooks should also hold for deep cloning. However,
463hooks get to know whether the operation is a mere serialization, or a cloning.
464
465Therefore, when serializing hooks are involved,
466
467 dclone(.) <> thaw(freeze(.))
468
469Well, you could keep them in sync, but there's no guarantee it will always
470hold on classes somebody else wrote. Besides, there is little to gain in
471doing so: a serializing hook could only keep one attribute of an object,
472which is probably not what should happen during a deep cloning of that
473same object.
474
475Here is the hooking interface:
476
477=over
478
479=item C<STORABLE_freeze> I<obj>, I<cloning>
480
481The serializing hook, called on the object during serialization. It can be
482inherited, or defined in the class itself, like any other method.
483
484Arguments: I<obj> is the object to serialize, I<cloning> is a flag indicating
485whether we're in a dclone() or a regular serialization via store() or freeze().
486
487Returned value: A LIST C<($serialized, $ref1, $ref2, ...)> where $serialized
488is the serialized form to be used, and the optional $ref1, $ref2, etc... are
489extra references that you wish to let the Storable engine serialize.
490
491At deserialization time, you will be given back the same LIST, but all the
492extra references will be pointing into the deserialized structure.
493
494The B<first time> the hook is hit in a serialization flow, you may have it
495return an empty list. That will signal the Storable engine to further
496discard that hook for this class and to therefore revert to the default
497serialization of the underlying Perl data. The hook will again be normally
498processed in the next serialization.
499
500Unless you know better, serializing hook should always say:
501
502 sub STORABLE_freeze {
503 my ($self, $cloning) = @_;
504 return if $cloning; # Regular default serialization
505 ....
506 }
507
508in order to keep reasonable dclone() semantics.
509
510=item C<STORABLE_thaw> I<obj>, I<cloning>, I<serialized>, ...
511
512The deserializing hook called on the object during deserialization.
513But wait. If we're deserializing, there's no object yet... right?
514
515Wrong: the Storable engine creates an empty one for you. If you know Eiffel,
516you can view C<STORABLE_thaw> as an alternate creation routine.
517
518This means the hook can be inherited like any other method, and that
519I<obj> is your blessed reference for this particular instance.
520
521The other arguments should look familiar if you know C<STORABLE_freeze>:
522I<cloning> is true when we're part of a deep clone operation, I<serialized>
523is the serialized string you returned to the engine in C<STORABLE_freeze>,
524and there may be an optional list of references, in the same order you gave
525them at serialization time, pointing to the deserialized objects (which
526have been processed courtesy of the Storable engine).
527
528It is up to you to use these information to populate I<obj> the way you want.
529
530Returned value: none.
531
532=back
533
534=head2 Predicates
535
536Predicates are not exportable. They must be called by explicitely prefixing
537them with the Storable package name.
538
539=over
540
541=item C<Storable::last_op_in_netorder>
542
543The C<Storable::last_op_in_netorder()> predicate will tell you whether
544network order was used in the last store or retrieve operation. If you
545don't know how to use this, just forget about it.
546
547=item C<Storable::is_storing>
548
549Returns true if within a store operation (via STORABLE_freeze hook).
550
551=item C<Storable::is_retrieving>
552
553Returns true if within a retrieve operation, (via STORABLE_thaw hook).
554
555=back
556
557=head2 Recursion
558
559With hooks comes the ability to recurse back to the Storable engine. Indeed,
560hooks are regular Perl code, and Storable is convenient when it comes to
561serialize and deserialize things, so why not use it to handle the
562serialization string?
563
564There are a few things you need to know however:
565
566=over
567
568=item *
569
570You can create endless loops if the things you serialize via freeze()
571(for instance) point back to the object we're trying to serialize in the hook.
572
573=item *
574
575Shared references among objects will not stay shared: if we're serializing
576the list of object [A, C] where both object A and C refer to the SAME object
577B, and if there is a serializing hook in A that says freeze(B), then when
578deserializing, we'll get [A', C'] where A' refers to B', but C' refers to D,
579a deep clone of B'. The topology was not preserved.
580
581=back
582
583That's why C<STORABLE_freeze> lets you provide a list of references
584to serialize. The engine guarantees that those will be serialized in the
585same context as the other objects, and therefore that shared objects will
586stay shared.
587
588In the above [A, C] example, the C<STORABLE_freeze> hook could return:
589
590 ("something", $self->{B})
591
592and the B part would be serialized by the engine. In C<STORABLE_thaw>, you
593would get back the reference to the B' object, deserialized for you.
594
595Therefore, recursion should normally be avoided, but is nonetheless supported.
596
597=head2 Deep Cloning
598
599There is a new Clone module available on CPAN which implements deep cloning
600natively, i.e. without freezing to memory and thawing the result. It is
601aimed to replace Storable's dclone() some day. However, it does not currently
602support Storable hooks to redefine the way deep cloning is performed.
603
604=head1 EXAMPLES
605
606Here are some code samples showing a possible usage of Storable:
607
608 use Storable qw(store retrieve freeze thaw dclone);
609
610 %color = ('Blue' => 0.1, 'Red' => 0.8, 'Black' => 0, 'White' => 1);
611
612 store(\%color, '/tmp/colors') or die "Can't store %a in /tmp/colors!\n";
613
614 $colref = retrieve('/tmp/colors');
615 die "Unable to retrieve from /tmp/colors!\n" unless defined $colref;
616 printf "Blue is still %lf\n", $colref->{'Blue'};
617
618 $colref2 = dclone(\%color);
619
620 $str = freeze(\%color);
621 printf "Serialization of %%color is %d bytes long.\n", length($str);
622 $colref3 = thaw($str);
623
624which prints (on my machine):
625
626 Blue is still 0.100000
627 Serialization of %color is 102 bytes long.
628
629=head1 WARNING
630
631If you're using references as keys within your hash tables, you're bound
632to disapointment when retrieving your data. Indeed, Perl stringifies
633references used as hash table keys. If you later wish to access the
634items via another reference stringification (i.e. using the same
635reference that was used for the key originally to record the value into
636the hash table), it will work because both references stringify to the
637same string.
638
639It won't work across a C<store> and C<retrieve> operations however, because
640the addresses in the retrieved objects, which are part of the stringified
641references, will probably differ from the original addresses. The
642topology of your structure is preserved, but not hidden semantics
643like those.
644
645On platforms where it matters, be sure to call C<binmode()> on the
646descriptors that you pass to Storable functions.
647
648Storing data canonically that contains large hashes can be
649significantly slower than storing the same data normally, as
650temprorary arrays to hold the keys for each hash have to be allocated,
651populated, sorted and freed. Some tests have shown a halving of the
652speed of storing -- the exact penalty will depend on the complexity of
653your data. There is no slowdown on retrieval.
654
655=head1 BUGS
656
657You can't store GLOB, CODE, FORMLINE, etc... If you can define
658semantics for those operations, feel free to enhance Storable so that
659it can deal with them.
660
661The store functions will C<croak> if they run into such references
662unless you set C<$Storable::forgive_me> to some C<TRUE> value. In that
663case, the fatal message is turned in a warning and some
664meaningless string is stored instead.
665
666Setting C<$Storable::canonical> may not yield frozen strings that
667compare equal due to possible stringification of numbers. When the
668string version of a scalar exists, it is the form stored, therefore
669if you happen to use your numbers as strings between two freezing
670operations on the same data structures, you will get different
671results.
672
dd19458b
JH
673When storing doubles in network order, their value is stored as text.
674However, you should also not expect non-numeric floating-point values
675such as infinity and "not a number" to pass successfully through a
676nstore()/retrieve() pair.
677
678As Storable neither knows nor cares about character sets (although it
679does know that characters may be more than eight bits wide), any difference
680in the interpretation of character codes between a host and a target
681system is your problem. In particular, if host and target use different
682code points to represent the characters used in the text representation
683of floating-point numbers, you will not be able be able to exchange
684floating-point data, even with nstore().
685
7a6a85bf
RG
686=head1 CREDITS
687
688Thank you to (in chronological order):
689
690 Jarkko Hietaniemi <jhi@iki.fi>
691 Ulrich Pfeifer <pfeifer@charly.informatik.uni-dortmund.de>
692 Benjamin A. Holzman <bah@ecnvantage.com>
693 Andrew Ford <A.Ford@ford-mason.co.uk>
694 Gisle Aas <gisle@aas.no>
695 Jeff Gresham <gresham_jeffrey@jpmorgan.com>
696 Murray Nesbitt <murray@activestate.com>
697 Marc Lehmann <pcg@opengroup.org>
9e21b3d0
JH
698 Justin Banks <justinb@wamnet.com>
699 Jarkko Hietaniemi <jhi@iki.fi> (AGAIN, as perl 5.7.0 Pumpkin!)
dd19458b
JH
700 Salvador Ortiz Garcia <sog@msg.com.mx>
701 Dominic Dunlop <domo@computer.org>
702 Erik Haugan <erik@solbors.no>
7a6a85bf
RG
703
704for their bug reports, suggestions and contributions.
705
706Benjamin Holzman contributed the tied variable support, Andrew Ford
707contributed the canonical order for hashes, and Gisle Aas fixed
708a few misunderstandings of mine regarding the Perl internals,
709and optimized the emission of "tags" in the output streams by
710simply counting the objects instead of tagging them (leading to
711a binary incompatibility for the Storable image starting at version
7120.6--older images are of course still properly understood).
713Murray Nesbitt made Storable thread-safe. Marc Lehmann added overloading
714and reference to tied items support.
715
716=head1 TRANSLATIONS
717
718There is a Japanese translation of this man page available at
719http://member.nifty.ne.jp/hippo2000/perltips/storable.htm ,
720courtesy of Kawai, Takanori <kawai@nippon-rad.co.jp>.
721
722=head1 AUTHOR
723
724Raphael Manfredi F<E<lt>Raphael_Manfredi@pobox.comE<gt>>
725
726=head1 SEE ALSO
727
728Clone(3).
729
730=cut
731