1=head1 NAME
2
3Coro::Storable - offer a more fine-grained Storable interface
4
5=head1 SYNOPSIS
6
7 use Coro::Storable;
8
9=head1 DESCRIPTION
10
11This module implements a few functions from the Storable module in a way
12so that it cede's more often. Some applications (such as the Deliantra
13game server) sometimes need to load large Storable objects without
14blocking the server for a long time.
15
16This is being implemented by using a perlio layer that feeds only small
17amounts of data (4096 bytes per call) into Storable, and C<Coro::cede>'ing
18regularly (at most 100 times per second by default, though).
19
20As Storable is not reentrant, this module also wraps most functions of the
21Storable module so that only one freeze or thaw is done at any one moment
22(and recursive invocations are not currently supported).
23
24=head1 FUNCTIONS
25
26=over 4
27
28=item $ref = thaw $pst
29
30Retrieve an object from the given $pst, which must have been created with
31C<Coro::Storable::freeze> or C<Storable::store_fd>/C<Storable::store>
32(sorry, but Storable uses incompatible formats for disk/mem objects).
33
34This function will cede regularly.
35
36=item $pst = freeze $ref
37
38Freeze the given scalar into a Storable object. It uses the same format as
39C<Storable::store_fd>.
40
41This functino will cede regularly.
42
43=item $pst = nfreeze $ref
44
45Same as C<freeze> but is compatible to C<Storable::nstore_fd> (note the
46C<n>).
47
48=item $pst = blocking_freeze $ref
49
50Same as C<freeze> but is guaranteed to block. This is useful e.g. in
51C<Coro::Util::fork_eval> when you want to serialise a data structure
52for use with the C<thaw> function for this module. You cannot use
53C<Storable::freeze> for this as Storable uses incompatible formats for
54memory and file images, and this module uses file images.
55
56=item $pst = blocking_nfreeze $ref
57
58Same as C<blocking_freeze> but uses C<nfreeze> internally.
59
60=item $guard = guard
61
62Acquire the Storable lock, for when you want to call Storable yourself.
63
64Note that this module already wraps all Storable functions, so there is
65rarely the need to do this yourself.
66
67=back
68
69=cut
70
71package Coro::Storable;
72
73use common::sense;
74
75use Coro ();
76use Coro::Semaphore ();
77
78BEGIN {
79   # suppress warnings
80   local $^W = 0;
81   require Storable;
82}
83
84use Storable;
85use base "Exporter";
86
87our $VERSION = 6.57;
88our @EXPORT = qw(thaw freeze nfreeze blocking_thaw blocking_freeze blocking_nfreeze);
89
90our $GRANULARITY = 0.01;
91
92my $lock = new Coro::Semaphore;
93
94sub guard {
95   $lock->guard
96}
97
98# wrap xs functions
99for (qw(net_pstore pstore net_mstore mstore pretrieve mretrieve dclone)) {
100   my $orig = \&{"Storable::$_"};
101   *{"Storable::$_"} = eval 'sub (' . (prototype $orig) . ') {
102      my $guard = $lock->guard;
103      &$orig
104   }';
105   die if $@;
106}
107
108sub thaw($) {
109   open my $fh, "<:cede($GRANULARITY)", \$_[0]
110      or die "cannot open pst via PerlIO::cede: $!";
111   Storable::fd_retrieve $fh
112}
113
114sub freeze($) {
115   open my $fh, ">:cede($GRANULARITY)", \my $buf
116      or die "cannot open pst via PerlIO::cede: $!";
117   Storable::store_fd $_[0], $fh;
118   close $fh;
119
120   $buf
121}
122
123sub nfreeze($) {
124   open my $fh, ">:cede($GRANULARITY)", \my $buf
125      or die "cannot open pst via PerlIO::cede: $!";
126   Storable::nstore_fd $_[0], $fh;
127   close $fh;
128
129   $buf
130}
131
132sub blocking_thaw($) {
133   open my $fh, "<", \$_[0]
134      or die "cannot open pst: $!";
135   Storable::fd_retrieve $fh
136}
137
138sub blocking_freeze($) {
139   open my $fh, ">", \my $buf
140         or die "cannot open pst: $!";
141   Storable::store_fd $_[0], $fh;
142   close $fh;
143
144   $buf
145}
146
147sub blocking_nfreeze($) {
148   open my $fh, ">", \my $buf
149         or die "cannot open pst: $!";
150   Storable::nstore_fd $_[0], $fh;
151   close $fh;
152
153   $buf
154}
155
1561;
157
158=head1 AUTHOR/SUPPORT/CONTACT
159
160   Marc A. Lehmann <schmorp@schmorp.de>
161   http://software.schmorp.de/pkg/Coro.html
162
163=cut
164
165
166