File Coverage

IPC/Shm/Tied.pm
Criterion Covered Total %
statement 92 100 92.0
branch 22 32 68.7
condition 6 12 50.0
subroutine 22 23 95.6
pod 11 11 100.0
total 153 178 85.9


line stmt bran cond sub pod time code
1             package IPC::Shm::Tied;
2 6     6   35 use warnings;
  6         13  
  6         225  
3 6     6   29 use strict;
  6         15  
  6         176  
4 6     6   29 use Carp;
  6         12  
  6         972  
5             #
6             # Copyright (c) 2014 by Kevin Cody-Little
7             #
8             # This code may be modified or redistributed under the terms
9             # of either the Artistic or GNU General Public licenses, at
10             # the modifier or redistributor's discretion.
11             #
12              
13             =head1 NAME
14              
15             IPC::Shm::Tied
16              
17             =head1 SYNOPSIS
18              
19             This class is part of the IPC::Shm implementation.
20              
21             use IPC::Shm;
22             my $obj = tie my %foo, 'IPC::Shm::Tied';
23             $obj->tiedref( \%foo );
24              
25             You may use this module to tie lexicals as above, but if used on
26             a package variable, it will behave as a lexical and be destroyed
27             when all connections are closed.
28              
29             If the call to $obj->tiedref is omitted, another tied reference
30             will be created when another shared variable's reference to this
31             one is dereferenced. This is not desirable behavior.
32              
33             Optionally takes an IPC::Shm::Segment object as an argument. If
34             none is supplied, Canonymous> is called.
35              
36             It is simpler to use the C<: shm> interface. See C.
37              
38             =head1 SUPERCLASS
39              
40             This class is a derivative of IPC::Shm::Segment, which in turn
41             is a derivative of IPC::Shm::Simple.
42              
43             =head1 CONSTRUCTORS
44              
45             =head2 TIEHASH, TIEARRAY, TIESCALAR
46              
47             This package supports the tie() call.
48              
49             =head2 $this->retie
50              
51             When an anonymous variable is dereferenced, and in some other
52             circumstances, it has to be tied to a variable so it can be
53             accessed normally.
54              
55             =head1 DESTRUCTOR
56              
57             =head2 $this->DETACH
58              
59             Called from IPC::Shm::Simple when the last in-process instance
60             of this same segment is being DESTROYed.
61              
62             =head1 TIED REFERENCE RETRIEVAL
63              
64             =head2 $this->tiedref
65              
66             Retrieves a reference to the object's associated
67             tied variable. Calls retie() when necessary.
68              
69             =head2 $this->tiedref( $reference )
70              
71             Stores a reference to the object's associated tied variable.
72             This allows retie() to be avoided most of the time.
73              
74             =head2 $this->tiedref_clean
75              
76             Removes the object's tied reference from the cache.
77              
78             =head2 $this->standin_tiedref( $standin )
79              
80             Returns a reference to the tied variable, given a standin hash.
81             See IPC::Shm::Segment for more about standins.
82              
83             =head2 $this->reftype( $reftype )
84              
85             Stores the type of object the associated reference
86             points to. This makes the retie() method possible
87             for anonymous segments.
88              
89             Valid values are 'HASH', 'ARRAY', and 'SCALAR'.
90              
91             =head2 $this->reftype
92              
93             Retrieves the reference type stored above.
94              
95             =head1 VALUE CACHE METHODS
96              
97             =head2 $this->vcache
98              
99             Retrieves the cached copy of the deserializer's last run.
100              
101             =head2 $this->vcache( $newvalue )
102              
103             Stores a new cached value, discarding the old. The Storable
104             module expects this to be a reference (no raw strings).
105              
106             =head2 $this->vcache_clean
107              
108             Removes the object's value cache from in-process memory.
109              
110             =head2 $class->EMPTY
111              
112             Returns a reference to an empty object, compatible with
113             the vcache method above. This is an abstract method and
114             must be implemented by inheriting classes.
115              
116             =head1 SERIALIZE/DESERIALIZE
117              
118             =head2 $this->FRESH
119              
120             Called by IPC::Shm::Simple->fetch when a new value is
121             actually read in from shared memory. The deserializing
122             step happens here.
123              
124             =head2 $this->flush
125              
126             Serializes and writes the contents of the value cache to shared memory.
127              
128              
129             =cut
130              
131             ###############################################################################
132             # dependencies
133              
134 6     6   48 use base 'IPC::Shm::Segment';
  6         12  
  6         903  
135              
136 6     6   6149 use IPC::Shm::Tied::HASH;
  6         28  
  6         127  
137 6     6   5386 use IPC::Shm::Tied::ARRAY;
  6         18  
  6         84  
138 6     6   4931 use IPC::Shm::Tied::SCALAR;
  6         27  
  6         80  
139              
140 6     6   199 use Scalar::Util qw( weaken );
  6         10  
  6         702  
141 6     6   33 use Storable qw( freeze thaw );
  6         8  
  6         5992  
142              
143              
144             ###############################################################################
145             # tie constructors
146              
147             sub TIEHASH {
148 24     24   31 shift; # discard class we were called as
149 24   66     93 $_[0] ||= IPC::Shm::Segment->anonymous;
150 24         143 return IPC::Shm::Tied::HASH->TIEHASH( @_ );
151             }
152              
153             sub TIEARRAY {
154 1     1   2 shift; # discard class we were called as
155 1   33     4 $_[0] ||= IPC::Shm::Segment->anonymous;
156 1         17 return IPC::Shm::Tied::ARRAY->TIEARRAY( @_ );
157             }
158              
159             sub TIESCALAR {
160 8     8   12 shift; # discard class we were called as
161 8   33     27 $_[0] ||= IPC::Shm::Segment->anonymous;
162 8         92 return IPC::Shm::Tied::SCALAR->TIESCALAR( @_ );
163             }
164              
165              
166             ###############################################################################
167             # reconstructor - dynamically create a tied reference
168              
169             sub retie {
170 2     2 1 4 my ( $this ) = @_;
171 2         3 my ( $rv );
172              
173 2         15 my $type = $this->vartype;
174              
175 2 100       14 if ( $type eq 'HASH' ) {
    50          
    50          
176 1         6 tie my %tmp, 'IPC::Shm::Tied', $this;
177 1         7 $this->tiedref( $rv = \%tmp );
178             }
179              
180             elsif ( $type eq 'ARRAY' ) {
181 0         0 tie my @tmp, 'IPC::Shm::Tied', $this;
182 0         0 $this->tiedref( $rv = \@tmp );
183             }
184              
185             elsif ( $type eq 'SCALAR' ) {
186 1         5 tie my $tmp, 'IPC::Shm::Tied', $this;
187 1         4 $this->tiedref( $rv = \$tmp );
188             }
189              
190             else {
191 0         0 confess "unknown reference type";
192             }
193              
194 2         5 return $rv;
195             }
196              
197              
198             ###############################################################################
199             # destructor - called when the last in-process instance is DESTROYed
200              
201             sub DETACH {
202 9     9 1 2740 my ( $this ) = @_;
203              
204 9         56 $this->SUPER::DETACH;
205 9         676 $this->vcache_clean;
206 9         47 $this->tiedref_clean;
207              
208 9         21 return;
209             }
210              
211              
212             ###############################################################################
213             # store the tied reference so we can get it back from the object later
214              
215             { # BEGIN private lexicals
216             my %TiedRef = ();
217              
218             sub tiedref {
219 35     35 1 53 my $this = shift;
220              
221 35         193 my $shmid = $this->{shmid};
222              
223 35 100       89 if ( my $newval = shift ) {
224              
225 33 50       96 unless ( defined $newval ) {
226 0         0 delete $TiedRef{$shmid};
227 0         0 return;
228             }
229              
230 33 50       106 confess __PACKAGE__ . "->tiedref() expects a reference"
231             unless my $reftype = ref( $newval );
232              
233 33         143 $this->reftype( $reftype );
234              
235 33         3264 $TiedRef{$shmid} = $newval;
236 33         109 weaken $TiedRef{$shmid};
237              
238 33         65 return $newval;
239             }
240              
241 2         4 my $tv; # silence perlcritic by declaring before conditional
242              
243             # keep a temporary reference to the end of this sub
244 2 50       19 $tv = $this->retie unless defined $TiedRef{$shmid};
245              
246 2         26 return $TiedRef{$shmid};
247             }
248              
249             sub tiedref_clean {
250 9     9 1 25 delete $TiedRef{shift->{shmid}};
251 9         14 return;
252             }
253              
254             sub standin_tiedref {
255 13     13 1 22 my ( $callclass, $standin ) = @_;
256              
257 13         51 my $shmid = $callclass->standin_shmid( $standin );
258              
259 13 100       106 return $TiedRef{$shmid} if defined $TiedRef{$shmid};
260              
261 2         11 my $this = $callclass->standin_restand( $standin );
262              
263 2         11 return $this->tiedref;
264             }
265              
266             } # END private lexicals
267              
268             sub reftype {
269 33     33 1 46 my $this = shift;
270              
271 33 50       69 return $this->{reftype} unless my $newval = shift;
272              
273             # avoid unnecessary shared memory access
274 33 50       73 if ( $this->{reftype} ) {
275 0 0       0 return $newval if $newval eq $this->{reftype};
276             }
277              
278             # we only care about anonymous segments
279 33 100       217 return $this->{reftype} unless my $vanon = $this->varanon;
280              
281 8         169 my $value = $IPC::Shm::ANONTYPE{$vanon};
282              
283             # and we want to avoid unnecessary shared memory writes
284 8 100 66     43 unless ( $value and $value eq $newval ) {
285 6         31 $IPC::Shm::ANONTYPE{$vanon} = $newval;
286             }
287              
288 8         30 return $this->{reftype} = $newval;
289             }
290              
291              
292             ###############################################################################
293             # value cache, for the unserialized in-memory state
294              
295             { # BEGIN private lexicals
296             my %ValCache = ();
297              
298             sub vcache {
299 306     306 1 9332 my $this = shift;
300              
301 306         464 my $shmid = $this->{shmid};
302              
303 306 100       724 if ( my $newval = shift ) {
304 55         282 return $ValCache{$shmid} = $newval;
305             }
306              
307 251 50       538 unless ( defined $ValCache{$shmid} ) {
308 0         0 $ValCache{$shmid} = $this->EMPTY;
309             }
310              
311 251         848 return $ValCache{$shmid};
312             }
313              
314             sub vcache_clean {
315 9     9 1 138 delete $ValCache{shift->{shmid}};
316 9         15 return;
317             }
318              
319             } # END private lexicals
320              
321              
322             ###############################################################################
323             # abstract empty value representation
324              
325             sub EMPTY {
326 0     0 1 0 croak "Abstract EMPTY() invocation";
327             }
328              
329              
330             ###############################################################################
331             # serialize and deserialize routines
332              
333             # reads from scache, writes to vcache
334             # called by IPC::Shm::Simple::fetch
335             sub FRESH {
336 29     29 1 1133 my ( $this ) = @_;
337              
338 29         52 my $thawed = eval { thaw( ${$this->scache} ) };
  29         39  
  29         164  
339 29 100       7737 $this->vcache( $thawed ? $thawed : $this->EMPTY );
340              
341             }
342              
343             # reads from vcache, calls store
344             sub flush {
345 68     68 1 101 my ( $this ) = @_;
346              
347 68         134 $this->store( freeze( $this->vcache ) );
348            
349             }
350              
351              
352             ###############################################################################
353             ###############################################################################
354              
355             =head1 AUTHOR
356              
357             Kevin Cody-Little
358              
359             =cut
360              
361             1;