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