ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Storable.pm
(Generate patch)

Comparing Coro/Coro/Storable.pm (file contents):
Revision 1.1 by root, Fri Apr 13 03:57:15 2007 UTC vs.
Revision 1.91 by root, Sat Jul 11 01:59:05 2015 UTC

7 use Coro::Storable; 7 use Coro::Storable;
8 8
9=head1 DESCRIPTION 9=head1 DESCRIPTION
10 10
11This module implements a few functions from the Storable module in a way 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 Crossfire 12so that it cede's more often. Some applications (such as the Deliantra
13game server) sometimes need to load large Storable objects without 13game server) sometimes need to load large Storable objects without
14blocking the server for a long time. 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).
15 23
16=head1 FUNCTIONS 24=head1 FUNCTIONS
17 25
18=over 4 26=over 4
19 27
21 29
22Retrieve an object from the given $pst, which must have been created with 30Retrieve an object from the given $pst, which must have been created with
23C<Coro::Storable::freeze> or C<Storable::store_fd>/C<Storable::store> 31C<Coro::Storable::freeze> or C<Storable::store_fd>/C<Storable::store>
24(sorry, but Storable uses incompatible formats for disk/mem objects). 32(sorry, but Storable uses incompatible formats for disk/mem objects).
25 33
26This works by calling C<Coro::cede> for every 512 bytes read in. 34This function will cede regularly.
27 35
28=item $pst = freeze $ref 36=item $pst = freeze $ref
29 37
30Freeze the given scalar into a Storable object. It uses the same format as 38Freeze the given scalar into a Storable object. It uses the same format as
31C<Storable::nstore_fd> (note the C<n>). 39C<Storable::store_fd>.
32 40
33This works by calling C<Coro::cede> for every write that Storable 41This functino will cede regularly.
34issues. Unfortunately, Storable often makes many very small writes, so it 42
35is rather inefficient. But it does keep the latency low. 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.
36 66
37=back 67=back
38 68
39=cut 69=cut
40 70
41package Coro::Storable; 71package Coro::Storable;
42 72
43use strict; 73use common::sense;
44 74
45use Coro (); 75use Coro ();
76use Coro::Semaphore ();
77
78BEGIN {
79 # suppress warnings
80 local $^W = 0;
81 require Storable;
82}
46 83
47use Storable; 84use Storable;
48use base "Exporter"; 85use base "Exporter";
49 86
50our $VERSION = '0.1'; 87our $VERSION = 6.47;
51our @EXPORT = qw(freeze thaw); 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}
52 113
53sub freeze($) { 114sub freeze($) {
54 open my $fh, ">:via(CoroCede)", \my $buf 115 open my $fh, ">:cede($GRANULARITY)", \my $buf
55 or die "cannot open pst via CoroCede: $!"; 116 or die "cannot open pst via PerlIO::cede: $!";
56 Storable::nstore_fd $_[0], $fh; 117 Storable::store_fd $_[0], $fh;
118 close $fh;
119
57 $buf 120 $buf
58} 121}
59 122
60sub thaw($) { 123sub nfreeze($) {
61 open my $fh, "<:via(CoroCede)", \$_[0] 124 open my $fh, ">:cede($GRANULARITY)", \my $buf
62 or die "cannot open pst via CoroCede: $!"; 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: $!";
63 Storable::fd_retrieve $fh 135 Storable::fd_retrieve $fh
64} 136}
65 137
66package PerlIO::via::CoroCede; 138sub blocking_freeze($) {
139 open my $fh, ">", \my $buf
140 or die "cannot open pst: $!";
141 Storable::store_fd $_[0], $fh;
142 close $fh;
67 143
68# generic cede-on-read/write filtering layer
69
70sub PUSHED {
71 __PACKAGE__
72}
73
74sub FILL {
75 Coro::cede;
76 read $_[1], my $buf, 512;
77 $buf 144 $buf
78} 145}
79 146
80sub WRITE { 147sub blocking_nfreeze($) {
81 Coro::cede; 148 open my $fh, ">", \my $buf
82 (print {$_[2]} $_[1]) ? length $_[1] : -1 149 or die "cannot open pst: $!";
150 Storable::nstore_fd $_[0], $fh;
151 close $fh;
152
153 $buf
83} 154}
84 155
851; 1561;
86 157
87=head1 AUTHOR 158=head1 AUTHOR/SUPPORT/CONTACT
88 159
89 Marc Lehmann <schmorp@schmorp.de> 160 Marc A. Lehmann <schmorp@schmorp.de>
90 http://home.schmorp.de/ 161 http://software.schmorp.de/pkg/Coro.html
91 162
92=cut 163=cut
93 164
94 165

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines