ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Storable.pm
Revision: 1.28
Committed: Wed Sep 24 21:20:05 2008 UTC (15 years, 9 months ago) by root
Branch: MAIN
Changes since 1.27: +8 -51 lines
Log Message:
*** empty log message ***

File Contents

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