File Coverage

IPC/Shm/Segment.pm
Criterion Covered Total %
statement 78 119 65.5
branch 26 64 40.6
condition 4 7 57.1
subroutine 15 16 93.7
pod 11 11 100.0
total 134 217 61.7


line stmt bran cond sub pod time code
1             package IPC::Shm::Segment;
2 6     6   33 use warnings;
  6         10  
  6         199  
3 6     6   31 use strict;
  6         12  
  6         215  
4 6     6   47 use Carp;
  6         18  
  6         777  
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::Segment
16              
17             =head1 SYNOPSIS
18              
19             This class is part of the IPC::Shm implementation. You should probably
20             not be using it directly.
21              
22             =head1 CONSTRUCTORS
23              
24             =head2 $class->named( $varname )
25              
26             Attach to a named variable's segment, creating if necessary. The contents
27             of the varname string are just how the variable is typed in perl code.
28              
29             =head2 $class->anonymous
30              
31             Create a new anonymous segment.
32              
33             =head2 $class->anonymous( $cookie )
34              
35             Attach to an existing anonymous segment using a cookie value.
36             Those cookies might be retrieved with the varanon method,
37             or might be stored in a standin. See below.
38              
39             =head1 ATTRIBUTES
40              
41             =head2 $this->varname
42              
43             Returns the variable's name, if any.
44              
45             =head2 $this->varname( $varname );
46              
47             Sets the variable's name.
48              
49             =head2 $this->varanon
50              
51             Returns the anonymous variable identifier cookie, if any.
52              
53             =head2 $this->varanon( $cookie )
54              
55             Sets the anonymous variable identifier cookie.
56              
57             =head2 $this->vartype
58              
59             Returns 'HASH', 'ARRAY', or 'SCALAR'.
60              
61             =head2 $this->vartype( $vartype )
62              
63             Stores the variable type. Only meaningful for anonymous segments.
64              
65             =head2 $this->varid
66              
67             Retrieves a human-redable string identifying the variable.
68              
69             =head1 OVERRIDDES
70              
71             =head2 $this->remove
72              
73             Overridden from IPC::Shm::Simple to remove table entries for named variables.
74              
75             =head2 $this->DETACH
76              
77             Called by IPC::Shm::Simple when the last in-process instance
78             is being DESTROYed.
79              
80             =head1 STAND-IN REFERENCES
81              
82             =head2 $this->standin
83              
84             This is a shared memory analogue of a reference. It is stored in the
85             shared memory variable that holds the reference.
86              
87             Returns a reference to an anonymous hash containing suitable identifiers.
88              
89             =head2 $class->standin_type( $standin )
90              
91             Returns the variable type that the standin points to.
92              
93             =head2 $class->standin_shmid( $standin )
94              
95             Returns the shmid where the standin points to.
96              
97             =head2 $class->standin_restand( $standin )
98              
99             Returns the original object that generated the standin, or
100             an exactly equal copy of that object.
101              
102             =head2 $class->standin_discard( $standin )
103              
104             Indicates that the standin reference is going away.
105              
106             Returns the original object as C.
107              
108             =cut
109              
110             ###############################################################################
111             # library dependencies
112              
113 6     6   102 use base 'IPC::Shm::Simple';
  6         10  
  6         6508  
114              
115 6     6   156337 use Digest::SHA1 qw( sha1_hex );
  6         4697  
  6         9783  
116              
117              
118             ###############################################################################
119             # package variables
120              
121             my $IPCKEY = 0xdeadbeef;
122              
123             our %Attrib = (
124             varname => undef,
125             varanon => undef
126             );
127              
128              
129             ###############################################################################
130             ###############################################################################
131              
132             ###############################################################################
133             # get the segment for a variable (by symbol), creating if needed
134              
135             sub named {
136 25     25 1 48 my ( $class, $sym ) = @_;
137 25         23 my ( $rv );
138              
139 25 50       60 unless ( $sym ) {
140 0         0 carp __PACKAGE__ . ' cannot cope with a null symbol name';
141 0         0 return;
142             }
143              
144 25 100       116 if ( $sym eq '%IPC::Shm::NAMEVARS' ) {
    100          
145 6 50       57 unless ( $rv = $class->bind( $IPCKEY ) ) {
146 0         0 carp "shmbind failed: $!";
147 0         0 return;
148             }
149             }
150              
151             elsif ( my $shmid = $IPC::Shm::NAMEVARS{$sym} ) {
152 11 50       53 unless ( $rv = $class->shmat( $shmid ) ) {
153 0         0 carp "shmattach failed: $!";
154 0         0 return;
155             }
156             }
157              
158             else {
159 8 50       45 unless ( $rv = $class->create ) {
160 0         0 carp "shmcreate failed: $!";
161 0         0 return;
162             }
163 8         3247 $rv->incref;
164 8         66 $rv->unlock;
165 8         148 $IPC::Shm::NAMEVARS{$sym} = $rv->shmid;
166             }
167              
168 25         2141 $rv->varname( $sym );
169              
170 25         1120 return $rv;
171             }
172              
173              
174             ###############################################################################
175             # attach to an anonymous segment by cookie, or create a new one
176              
177             sub anonymous {
178 6     6 1 12 my ( $class, $aname ) = @_;
179 6         11 my ( $rv, $shmid );
180              
181 6 50       28 if ( defined $aname ) {
182              
183 0 0       0 unless ( $shmid = $IPC::Shm::ANONVARS{$aname} ) {
184 0         0 carp "no such anonymous segment $aname";
185 0         0 return;
186             }
187              
188 0 0       0 unless ( $rv = $class->shmat( $shmid ) ) {
189 0         0 carp "failed to attach to shmid $shmid: $!";
190 0         0 return;
191             }
192              
193             }
194              
195             else {
196 6 50       45 unless ( $rv = $class->create ) {
197 0         0 carp "shmcreate failed: $!";
198 0         0 return;
199             }
200              
201 6         1811 $rv->unlock;
202 6         467 $aname = sha1_hex( rand( 10000 ) . ' ' . $$ );
203 6         41 $IPC::Shm::ANONVARS{$aname} = $rv->shmid;
204              
205             }
206              
207 6         30 $rv->varanon( $aname );
208              
209 6         145 return $rv;
210             }
211              
212              
213             ###############################################################################
214             ###############################################################################
215              
216             ###############################################################################
217             # produce a human-readable identifier for the variable
218              
219             sub varid {
220 0     0 1 0 my ( $this ) = @_;
221              
222 0 0       0 if ( my $vname = $this->varname ) {
223 0         0 return 'NAME=' . $vname;
224             }
225              
226 0 0       0 if ( my $vanon = $this->varanon ) {
227 0         0 return 'ANON=' . $vanon;
228             }
229              
230 0         0 return "UNKNOWN!";
231             }
232              
233             ###############################################################################
234             # determine the variable type based on its name or cookie
235              
236             sub vartype {
237 2     2 1 3 my ( $this ) = @_;
238              
239 2 50       8 if ( my $vanon = $this->varanon ) {
240 2   50     45 return $IPC::Shm::ANONTYPE{$vanon} || 'INVALID';
241             }
242              
243 0         0 my $vname = $this->varname;
244              
245 0 0       0 return 'HASH' if $vname =~ /^%/;
246 0 0       0 return 'ARRAY' if $vname =~ /^@/;
247 0 0       0 return 'SCALAR' if $vname =~ /^\$/;
248              
249 0         0 return 'INVALID';
250             }
251              
252              
253             ###############################################################################
254             # deliberate removal override
255              
256             sub remove {
257 12     12 1 2423 my ( $this ) = @_;
258              
259 12 100       48 if ( my $vname = $this->varname ) {
260 5         133 delete $IPC::Shm::NAMEVARS{$vname};
261 5         42 $this->decref;
262 5         58 $this->CLEAR;
263             }
264              
265 12         430 return $this->SUPER::remove();
266             }
267              
268              
269             ###############################################################################
270             # disconnect-time cleanups
271              
272             sub DETACH {
273 12     12 1 56 my ( $this ) = @_;
274              
275 12 100 66     80 unless ( $this->nrefs or $this->varname ) {
276              
277 4         458 my $vanon = $this->varanon;
278              
279 4         83 $this->writelock;
280              
281 4 50       107 if ( $this->nconns == 1 ) {
282              
283 4         51 $this->CLEAR;
284 4         26 $this->SUPER::remove;
285              
286 4         56 delete $IPC::Shm::ANONVARS{$vanon};
287 4         21 delete $IPC::Shm::ANONTYPE{$vanon};
288              
289             }
290              
291             }
292              
293 12         202 $this->SUPER::DETACH();
294              
295             }
296              
297              
298             ###############################################################################
299             ###############################################################################
300              
301             ###############################################################################
302             # generate a stand-in hashref containing one identifier or another
303              
304             sub standin {
305 5     5 1 9 my ( $this ) = @_;
306              
307 5 50       30 if ( my $vname = $this->varname ) {
    50          
308 0         0 return { varname => $vname };
309             }
310              
311             elsif ( my $vanon = $this->varanon ) {
312 5         561 return { varanon => $vanon };
313             }
314              
315             else {
316 0         0 carp __PACKAGE__ . ' object has no identifier';
317 0         0 return;
318             }
319              
320             }
321              
322              
323             ###############################################################################
324             # determine the standin variable type based on its name or cookie
325              
326             sub standin_type {
327 5     5 1 11 my ( $callclass, $standin ) = @_;
328              
329 5 50       21 if ( my $vanon = $standin->{varanon} ) {
330 5   50     22 return $IPC::Shm::ANONTYPE{$vanon} || 'INVALID';
331             }
332              
333 0         0 my $vname = $standin->{varname};
334              
335 0 0       0 return 'HASH' if $vname =~ /^%/;
336 0 0       0 return 'ARRAY' if $vname =~ /^@/;
337 0 0       0 return 'SCALAR' if $vname =~ /^\$/;
338              
339 0         0 return 'INVALID';
340             }
341              
342              
343             ###############################################################################
344             # get back the shared memory id given a standin from above
345              
346             sub standin_shmid {
347 18     18 1 30 my ( $callclass, $standin ) = @_;
348              
349 18 50       47 if ( my $vname = $standin->{varname} ) {
350 0         0 return $IPC::Shm::NAMEVARS{$vname};
351             }
352              
353 18 50       50 if ( my $vanon = $standin->{varanon} ) {
354 18         95 return $IPC::Shm::ANONVARS{$vanon};
355             }
356              
357 0         0 return 0;
358             }
359              
360              
361             ###############################################################################
362             # get back the object given a standin from above
363              
364             sub standin_restand {
365 5     5 1 10 my ( $callclass, $standin ) = @_;
366              
367 5         24 my $shmid = $callclass->standin_shmid( $standin );
368              
369 5 50       22 unless ( $shmid ) {
370 0         0 carp "could not get shmid for standin";
371 0         0 return;
372             }
373              
374 5         37 my $class = 'IPC::Shm::Tied::' . $callclass->standin_type( $standin );
375              
376 5         60 my $rv = $class->shmat( $shmid );
377              
378 5 50       243 unless ( $rv ) {
379 0         0 carp "restand_obj shmat failed: $!\n";
380 0         0 return;
381             }
382              
383 5 50       40 $rv->varname( $standin->{varname} ) if $standin->{varname};
384 5 50       47 $rv->varanon( $standin->{varanon} ) if $standin->{varanon};
385              
386 5         115 return $rv;
387             }
388              
389              
390             ###############################################################################
391             # indicate a standin is being thrown away, and return the object
392              
393             sub standin_discard {
394 3     3 1 8 my ( $callclass, $standin ) = @_;
395              
396 3 50       21 my $rv = $callclass->standin_restand( $standin )
397             or return;
398              
399 3         27 $rv->decref;
400              
401 3         53 return $rv;
402             }
403              
404              
405             ###############################################################################
406             ###############################################################################
407              
408             =head1 AUTHOR
409              
410             Kevin Cody-Little
411              
412             =cut
413              
414             1;