File Coverage

lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm
Criterion Covered Total %
statement 21 58 36.2
branch 0 22 0.0
condition 0 12 0.0
subroutine 7 20 35.0
pod 0 11 0.0
total 28 123 22.7


line stmt bran cond sub pod time code
1             package Mojo::IOLoop::ReadWriteProcess::Shared::Semaphore;
2 38     38   19483 use Mojo::Base -base;
  38         100  
  38         254  
3              
4 38     38   5950 use Carp;
  38         79  
  38         2639  
5 38     38   276 use POSIX qw(O_WRONLY O_CREAT O_NONBLOCK O_NOCTTY);
  38         74  
  38         252  
6             use IPC::SysV
7 38     38   22891 qw(ftok IPC_NOWAIT IPC_CREAT IPC_EXCL S_IRUSR S_IWUSR S_IRGRP S_IWGRP S_IROTH S_IWOTH SEM_UNDO);
  38         43599  
  38         8095  
8 38     38   18891 use IPC::Semaphore;
  38         90719  
  38         2159  
9             our @EXPORT_OK = qw(semaphore);
10 38     38   275 use Exporter 'import';
  38         110  
  38         1527  
11              
12 38     38   235 use constant DEBUG => $ENV{MOJO_PROCESS_DEBUG};
  38         95  
  38         39160  
13             has key => sub { shift->_genkey };
14             has _sem => sub { $_[0]->_create(shift->key) };
15             has count => 1;
16             has _value => 1;
17             has flags => IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
18             | S_IROTH | S_IWOTH;
19              
20 0     0 0   sub semaphore { __PACKAGE__->new(@_) }
21              
22 0     0     sub _genkey { ftok($0, 0) }
23              
24             # The following is an adaptation over IPC::Semaphore::Concurrency
25             sub _create {
26 0     0     my ($self, $key) = @_;
27              
28             # Try acquiring already existing semaphore
29 0           my $sem = IPC::Semaphore->new($key, $self->count, 0);
30 0 0         unless (defined $sem) {
31 0           warn "[debug:$$] Create semaphore $key" if DEBUG;
32 0           $sem = IPC::Semaphore->new($key, $self->count, $self->flags);
33 0 0         confess 'Semaphore creation failed! ' unless defined($sem);
34 0           $sem->setall($self->_value);
35             }
36 0           return $sem;
37             }
38              
39             sub acquire {
40 0     0 0   my $self = shift;
41 0 0 0       my %args = @_ % 2 == 0 ? @_ : @_ == 1 && ref $_[0] eq 'HASH' ? %{$_[0]} : ();
  0 0          
42              
43             # Defaults
44 0 0         $args{'sem'} = 0 unless defined($args{'sem'});
45 0 0         $args{'wait'} = 0 unless defined($args{'wait'});
46 0 0         $args{'max'} = -1 unless defined($args{'max'});
47 0 0         $args{'undo'} = 0 unless defined($args{'undo'});
48 0           warn "[debug:$$] Acquire semaphore " . $self->key if DEBUG;
49              
50 0           my $sem = $self->_sem;
51 0           my $flags = IPC_NOWAIT;
52 0 0         $flags |= SEM_UNDO if ($args{'undo'});
53              
54 0 0         if ($args{'wait'}) {
55 0           my $ncnt = $self->getncnt($args{'sem'});
56 0 0 0       return if ($args{'max'} >= 0 && $ncnt >= $args{'max'});
57 0           warn "[debug:$$] Semaphore wait" if DEBUG;
58 0           warn "[debug:$$] Semaphore val " . $self->getval($args{sem}) if DEBUG;
59              
60             # Remove NOWAIT and block
61 0           $flags ^= IPC_NOWAIT;
62             }
63              
64 0           return $sem->op($args{'sem'}, -1, $flags);
65             }
66              
67              
68 0     0 0   sub getall { shift->_sem->getall() }
69              
70 0   0 0 0   sub getval { shift->_sem->getval(shift // 0) }
71              
72 0   0 0 0   sub getncnt { shift->_sem->getncnt(shift // 0) }
73              
74 0     0 0   sub setall { shift->_sem->setall(@_) }
75              
76 0     0 0   sub setval { shift->_sem->setval(@_) }
77              
78 0     0 0   sub stat { shift->_sem->stat() }
79              
80 0     0 0   sub id { shift->_sem->id() }
81              
82 0   0 0 0   sub release { shift->_sem->op(shift || 0, 1, 0) }
83              
84 0     0 0   sub remove { shift->_sem->remove() }
85              
86             !!42;