line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mojo::IOLoop::ReadWriteProcess::Shared::Semaphore; |
2
|
38
|
|
|
38
|
|
19309
|
use Mojo::Base -base; |
|
38
|
|
|
|
|
81
|
|
|
38
|
|
|
|
|
245
|
|
3
|
|
|
|
|
|
|
|
4
|
38
|
|
|
38
|
|
5870
|
use Carp; |
|
38
|
|
|
|
|
99
|
|
|
38
|
|
|
|
|
2334
|
|
5
|
38
|
|
|
38
|
|
241
|
use POSIX qw(O_WRONLY O_CREAT O_NONBLOCK O_NOCTTY); |
|
38
|
|
|
|
|
77
|
|
|
38
|
|
|
|
|
363
|
|
6
|
|
|
|
|
|
|
use IPC::SysV |
7
|
38
|
|
|
38
|
|
22186
|
qw(ftok IPC_NOWAIT IPC_CREAT IPC_EXCL S_IRUSR S_IWUSR S_IRGRP S_IWGRP S_IROTH S_IWOTH SEM_UNDO); |
|
38
|
|
|
|
|
41634
|
|
|
38
|
|
|
|
|
7101
|
|
8
|
38
|
|
|
38
|
|
19567
|
use IPC::Semaphore; |
|
38
|
|
|
|
|
93013
|
|
|
38
|
|
|
|
|
2033
|
|
9
|
|
|
|
|
|
|
our @EXPORT_OK = qw(semaphore); |
10
|
38
|
|
|
38
|
|
262
|
use Exporter 'import'; |
|
38
|
|
|
|
|
79
|
|
|
38
|
|
|
|
|
1467
|
|
11
|
|
|
|
|
|
|
|
12
|
38
|
|
|
38
|
|
199
|
use constant DEBUG => $ENV{MOJO_PROCESS_DEBUG}; |
|
38
|
|
|
|
|
72
|
|
|
38
|
|
|
|
|
39398
|
|
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; |