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   53217 use strict;
  4         4  
  4         91  
3 4     4   10 use warnings;
  4         4  
  4         67  
4              
5 4     4   53 use 5.008;
  4         11  
6 4     4   1568 use Digest::CRC qw(crc8);
  4         6849  
  4         240  
7 4     4   1539 use IPC::SysV qw(IPC_PRIVATE IPC_CREAT IPC_NOWAIT S_IRUSR S_IWUSR);
  4         3016  
  4         406  
8 4     4   1643 use IPC::Semaphore;
  4         13431  
  4         94  
9 4     4   1280 use IPC::Semaphore::Set::Resource;
  4         5  
  4         2033  
10              
11             our $VERSION = 1.04;
12              
13             ############
14             ## Public ##
15             ############
16              
17             sub new
18             {
19 7     7 1 48 my $class = shift;
20 7 50       25 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     32 $args->{_resources} = delete($args->{resources}) || 1;
28 7   100     24 $args->{_value} = delete($args->{value}) || 1;
29 7   33     44 $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         200 my $self = bless($args, $class);
32 7 100       32 if (my $key = $self->{key}) {
    100          
33 1 50       4 if ($key =~ m/[^0-9]/) {
34 0         0 die "key [$key] was not numeric";
35             }
36 1         4 $self->{_pre_exist} = semget($key, 0, IPC_NOWAIT);
37 1         27 $self->{_key} = $key;
38 1         5 $self->{_semaphore} = IPC::Semaphore->new($key, $self->{_resources}, $self->{_flags});
39             } elsif (my $key_name = $self->{key_name}) {
40 5         6 $self->{_key_name} = $key_name;
41 5         15 $self->{_key} = crc8($key_name);
42 5         157 $self->{_pre_exist} = semget($self->{_key}, 0, IPC_NOWAIT);
43 5         73 $self->{_semaphore} = IPC::Semaphore->new($self->key, $self->{_resources}, $self->{_flags});
44             } else {
45 1         3 $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       118 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       14 if (!$self->{_pre_exist}) {
54 5         10 $self->semaphore->setall(($self->{_value}) x $self->{_resources});
55             }
56 7         145 return $self;
57             }
58              
59             sub resource
60             {
61 23     23 1 1003850 my $self = shift;
62 23 50       56 my $args = ref($_[0]) ? $_[0] : {@_};
63             # default to 0, the first resource in the set
64 23 100       50 $args->{number} = $args->{number} ? $args->{number} : 0;
65 23 100       73 if (!$self->{resources}{$args->{number}}) {
66 8 100       21 $args->{key} = $self->key ? $self->key : IPC_PRIVATE;
67 8         39 $args->{semaphore} = $self->semaphore;
68 8         31 $self->{resources}{$args->{number}} = IPC::Semaphore::Set::Resource->new($args);
69             }
70 23         81 return $self->{resources}{$args->{number}};
71             }
72              
73             sub resources
74             {
75 1     1 1 320 my $self = shift;
76 1         3 my $total = () = $self->semaphore->getall;
77 1         45 my @resources;
78 1         4 for (0..($total - 1)) {
79 3         7 push(@resources, $self->resource(number => $_));
80             }
81 1 50       4 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 62 sub key {return shift->{_key}}
90 0     0 1 0 sub keyName {return shift->{_key_name}}
91 4 50   4 1 434 sub remove {return shift->semaphore->remove ? 1 : 0}
92 26     26 1 384 sub semaphore {return shift->{_semaphore}}
93              
94             1;
95              
96             __END__