File Coverage

blib/lib/IPC/Semaphore/Set/Resource.pm
Criterion Covered Total %
statement 66 79 83.5
branch 24 36 66.6
condition 2 4 50.0
subroutine 18 19 94.7
pod 0 10 0.0
total 110 148 74.3


line stmt bran cond sub pod time code
1             package IPC::Semaphore::Set::Resource;
2 4     4   21 use strict;
  4         8  
  4         147  
3 4     4   22 use warnings;
  4         7  
  4         136  
4              
5 4     4   92 use 5.008;
  4         13  
6 4     4   23 use IPC::SysV qw(SEM_UNDO IPC_NOWAIT);
  4         6  
  4         3697  
7              
8             our $VERSION = 1.20;
9              
10             ############
11             ## Public ##
12             ############
13              
14             sub new
15             {
16 8     8 0 12 my $class = shift;
17 8 50       26 my $args = ref($_[0]) ? $_[0] : {@_};
18             # check for required arguments.
19 8 50       19 die "'key' is required" unless defined($args->{key});
20 8 50       20 die "'number' is required" unless defined($args->{number});
21 8 50       23 die "'semaphore' is required" unless (ref($args->{semaphore}) eq 'IPC::Semaphore');
22             # 'cleanup_object' determines whether or not we'll be cleaning up in DESTROY
23 8 100       20 if (!defined($args->{cleanup_object})) {
24 6         10 $args->{cleanup_object} = 1;
25             }
26 8         13 my $self = bless($args, $class);
27             # blow up if the system doesn't have this resource in the set
28 8 50       19 if (!defined($self->value)) {
29 0         0 my $total = () = $self->semaphore->getall;
30             die $self->{number} . ' is not a valid resource for semaphore [' . $self->{key}
31 0         0 . "] which only has [$total] total resources. The resources start at 0.";
32             }
33 8         206 return bless($args, $class);
34             }
35              
36             sub lockOrDie {
37 2     2 0 4 my $self = shift;
38 2 100       9 if ($self->_lock(IPC_NOWAIT)) {
39 1         3 return 1;
40             } else {
41 1         12 die "could not lock on semaphore [$self->{key}] resource number [$self->{number}]";
42             }
43             }
44              
45             sub lockWaitTimeout
46             {
47 1     1 0 2 my $self = shift;
48 1   50     8 my $timeout = shift || 3;
49 1         1 my $lock;
50 1         2 eval {
51 1     0   10 local $SIG{ALRM} = sub { die "alarm\n" };
  0         0  
52 1         5 alarm $timeout;
53 1         4 $lock = $self->_lock;
54 1         7 alarm 0;
55             };
56 1 50       4 if (!$lock) {
57 0         0 return 0;
58             }
59 1         3 return 1;
60             }
61              
62             sub lockWaitTimeoutDie
63             {
64 1     1 0 3 my $self = shift;
65 1   50     5 my $timeout = shift || 3;
66 1         2 my $lock;
67 1         2 eval {
68 1     1   17 local $SIG{ALRM} = sub { die "alarm\n" };
  1         1000122  
69 1         7 alarm $timeout;
70 1         4 $lock = $self->_lock;
71 0         0 alarm 0;
72             };
73 1 50       12 if (!$lock) {
74 1         13 die "could not establish lock after $timeout seconds";
75             }
76 0         0 return 1;
77             }
78              
79 4 100   4 0 376 sub lock {return shift->_lock(IPC_NOWAIT) ? 1 : 0}
80 2 50   2 0 3 sub lockWait {return shift->_lock ? 1 : 0}
81 5 50   5 0 416 sub addValue {return shift->_add_value(IPC_NOWAIT) ? 1 : 0}
82              
83             ############
84             ## Helper ##
85             ############
86              
87 33     33 0 141 sub number {return shift->{number}}
88 30     30 0 81 sub semaphore {return shift->{semaphore}}
89              
90             sub value {
91 15     15 0 3446 my $self = shift;
92 15         27 return $self->semaphore->getval($self->number);
93             }
94              
95             #############
96             ## Private ##
97             #############
98              
99             sub _lock
100             {
101 10     10   24 my ($self, $flags) = @_;
102 10 100       18 if ($self->semaphore->op($self->number, -1, $flags)) {
103 5         66 $self->{_locks}++;
104 5         18 return 1;
105             }
106 3         55 return 0;
107             }
108              
109             sub _add_value
110             {
111 5     5   17 my ($self, $flags) = @_;
112 5 50       10 if ($self->semaphore->op($self->number, 1, $flags)) {
113 5         72 $self->{_locks}--;
114 5         21 return 1;
115             }
116 0         0 return 0;
117             }
118              
119             sub DESTROY
120             {
121 8     8   2852 my $self = shift;
122 8 100       30 return unless $self->{cleanup_object};
123 6 100       132 if (defined($self->{_locks})) {
124 1 50       4 if ($self->{_locks} > 0) {
125 0         0 while ($self->{_locks} > 0) {
126 0         0 $self->semaphore->op($self->number, 1, IPC_NOWAIT);
127 0         0 $self->{_locks}--;
128             }
129             }
130 1 50       41 if ($self->{_locks} < 0) {
131 0           while ($self->{_locks} < 0) {
132 0           $self->semaphore->op($self->number, -1, IPC_NOWAIT);
133 0           $self->{_locks}++;
134             }
135             }
136             }
137             }
138              
139             1;
140              
141             __END__