File Coverage

blib/lib/IPC/Semaphore/Set.pm
Criterion Covered Total %
statement 57 61 93.4
branch 18 24 75.0
condition 5 7 71.4
subroutine 13 15 86.6
pod 8 8 100.0
total 101 115 87.8


line stmt bran cond sub pod time code
1             package IPC::Semaphore::Set;
2 4     4   67378 use strict;
  4         9  
  4         120  
3 4     4   14 use warnings;
  4         6  
  4         94  
4              
5 4     4   74 use 5.008;
  4         12  
6 4     4   1984 use Digest::CRC qw(crc8);
  4         8249  
  4         347  
7 4     4   1995 use IPC::SysV qw(IPC_PRIVATE IPC_CREAT IPC_NOWAIT S_IRUSR S_IWUSR);
  4         4054  
  4         711  
8 4     4   2282 use IPC::Semaphore;
  4         17845  
  4         143  
9 4     4   2078 use IPC::Semaphore::Set::Resource;
  4         7  
  4         2588  
10              
11             our $VERSION = 1.20;
12              
13             ############
14             ## Public ##
15             ############
16              
17             sub new
18             {
19 7     7 1 71 my $class = shift;
20 7 50       45 my $args = ref($_[0]) ? $_[0] : {@_};
21             # set some sane defaults: we want at least one resource (semaphore in the set),
22             # and for each semaphore we want it to have a value of at least one, and
23             # when working on the semaphore by default we want to use IPC_CREAT to create
24             # the semaphore if it didn't already exist, and S_IRUSR & S_IWUSR to give the
25             # semaphore read and write permissions for the current perl user which you could
26             # see by getting and viewing the results of the perl function getlogin()
27 7   100     44 $args->{_resources} = delete($args->{resources}) || 1;
28 7   100     34 $args->{_value} = delete($args->{value}) || 1;
29 7   33     66 $args->{_flags} = delete($args->{flags}) || S_IRUSR | S_IWUSR | IPC_CREAT;
30             # determine if we're using a key_name, key, or private semaphore set
31 7         284 my $self = bless($args, $class);
32 7 100       41 if (my $key = $self->{key}) {
    100          
33 1 50       7 if ($key =~ m/[^0-9]/) {
34 0         0 die "key [$key] was not numeric";
35             }
36 1         7 $self->{_pre_exist} = semget($key, 0, IPC_NOWAIT);
37 1         95 $self->{_key} = $key;
38 1         11 $self->{_semaphore} = IPC::Semaphore->new($key, $self->{_resources}, $self->{_flags});
39             } elsif (my $key_name = $self->{key_name}) {
40 5         11 $self->{_key_name} = $key_name;
41 5         44 $self->{_key} = crc8($key_name);
42 5         187 $self->{_pre_exist} = semget($self->{_key}, 0, IPC_NOWAIT);
43 5         86 $self->{_semaphore} = IPC::Semaphore->new($self->key, $self->{_resources}, $self->{_flags});
44             } else {
45 1         5 $self->{_semaphore} = IPC::Semaphore->new(IPC_PRIVATE, $self->{_resources}, $self->{_flags});
46             }
47             # bail out if we didn't get an IPC::Semaphore
48 7 50       158 if (ref($self->semaphore) ne 'IPC::Semaphore') {
49 0         0 die 'could not get a semaphore with ' . $self->key . ": $!";
50             }
51             # if we created this semaphore, allow use of 'available' but if we didn't, don't clobber what
52             # the semaphore resources were already set to
53 7 100       22 if (!$self->{_pre_exist}) {
54 5         11 $self->semaphore->setall(($self->{_value}) x $self->{_resources});
55             }
56 7         192 return $self;
57             }
58              
59             sub resource
60             {
61 23     23 1 1006814 my $self = shift;
62 23 50       80 my $args = ref($_[0]) ? $_[0] : {@_};
63             # default to 0, the first resource in the set
64 23 100       72 $args->{number} = $args->{number} ? $args->{number} : 0;
65 23 100       96 if (!$self->{resources}{$args->{number}}) {
66 8 100       65 $args->{key} = $self->key ? $self->key : IPC_PRIVATE;
67 8         20 $args->{semaphore} = $self->semaphore;
68 8         48 $self->{resources}{$args->{number}} = IPC::Semaphore::Set::Resource->new($args);
69             }
70 23         109 return $self->{resources}{$args->{number}};
71             }
72              
73             sub resources
74             {
75 1     1 1 503 my $self = shift;
76 1         4 my $total = () = $self->semaphore->getall;
77 1         51 my @resources;
78 1         5 for (0..($total - 1)) {
79 3         8 push(@resources, $self->resource(number => $_));
80             }
81 1 50       7 return wantarray ? @resources : \@resources;
82             }
83              
84             ############
85             ## Helper ##
86             ############
87              
88 0     0 1 0 sub id {return shift->sem->id}
89 21     21 1 77 sub key {return shift->{_key}}
90 0     0 1 0 sub keyName {return shift->{_key_name}}
91 4 50   4 1 967 sub remove {return shift->semaphore->remove ? 1 : 0}
92 26     26 1 730 sub semaphore {return shift->{_semaphore}}
93              
94             1;
95              
96             __END__