File Coverage

lib/Mojo/IOLoop/ReadWriteProcess/Shared/Lock.pm
Criterion Covered Total %
statement 9 36 25.0
branch 0 8 0.0
condition 0 8 0.0
subroutine 3 8 37.5
pod 4 5 80.0
total 16 65 24.6


line stmt bran cond sub pod time code
1             package Mojo::IOLoop::ReadWriteProcess::Shared::Lock;
2              
3 38     38   275 use Mojo::Base 'Mojo::IOLoop::ReadWriteProcess::Shared::Semaphore';
  38         63  
  38         248  
4              
5             our @EXPORT_OK = qw(shared_lock semaphore);
6 38     38   3245 use Exporter 'import';
  38         92  
  38         1444  
7 38     38   202 use constant DEBUG => $ENV{MOJO_PROCESS_DEBUG};
  38         73  
  38         24854  
8              
9             # Mojo::IOLoop::ReadWriteProcess::Shared::Semaphore has same defaults - but locks have 1 count and 1 as setup value
10             # Make it explict
11             has count => 1;
12             has _value => 1;
13             has locked => 0;
14              
15 0     0 0   sub shared_lock { __PACKAGE__->new(@_) }
16              
17             sub lock {
18 0     0 1   my $self = shift;
19 0           warn "[debug:$$] Attempt to acquire lock " . $self->key if DEBUG;
20 0 0         my $r = @_ > 0 ? $self->acquire(@_) : $self->acquire(wait => 1, undo => 0);
21 0           warn "[debug:$$] lock Returned : $r" if DEBUG;
22 0 0 0       $self->locked(1) if defined $r && $r == 1;
23 0           return $r;
24             }
25              
26             sub lock_section {
27 0     0 1   my ($self, $fn) = @_;
28 0           warn "[debug:$$] Acquiring lock (blocking)" if DEBUG;
29 0           1 while $self->lock != 1;
30 0           warn "[debug:$$] Lock acquired $$" if DEBUG;
31              
32 0           my $r;
33             {
34 0           local $@;
  0            
35 0           $r = eval { $fn->() };
  0            
36 0           $self->unlock();
37 0 0 0       warn "[debug:$$] Error inside locked section : $@" if $@ && DEBUG;
38             };
39 0           return $r;
40             }
41              
42             *section = \&lock_section;
43              
44 0     0 1   sub try_lock { shift->acquire(undo => 0, wait => 0) }
45              
46             sub unlock {
47 0     0 1   my $self = shift;
48 0           warn "[debug:$$] UNLock " . $self->key if DEBUG;
49 0           my $r;
50 0           eval {
51 0           $r = $self->release(@_);
52 0 0 0       $self->locked(0) if defined $r && $r == 1;
53             };
54 0           return $r;
55             }
56              
57             =encoding utf-8
58              
59             =head1 NAME
60              
61             Mojo::IOLoop::ReadWriteProcess::Shared::Lock - IPC Lock
62              
63             =head1 SYNOPSIS
64              
65             use Mojo::IOLoop::ReadWriteProcess qw(process queue lock);
66              
67             my $q = queue; # Create a Queue
68             $q->pool->maximum_processes(10); # 10 Concurrent processes at maximum
69             $q->queue->maximum_processes(50); # 50 is maximum total to be allowed in the queue
70              
71             $q->add(
72             process(
73             sub {
74             my $l = lock(key => 42); # IPC Lock
75             my $e = 1;
76             if ($l->lock) { # Blocking lock acquire
77             # Critical section
78             $e = 0;
79             $l->unlock;
80             }
81             exit($e);
82             }
83             )->set_pipes(0)->internal_pipes(0)) for 1 .. 20; # Fill with 20 processes
84              
85             $q->consume(); # Consume the processes
86              
87             =head1 DESCRIPTION
88              
89             L uses L internally and creates a Lock from a semaphore that is available across different processes.
90              
91             =head1 METHODS
92              
93             L inherits all events from L and implements
94             the following new ones.
95              
96             =head2 lock/unlock
97              
98             use Mojo::IOLoop::ReadWriteProcess qw(lock);
99              
100             my $l = lock(key => "42"); # Create Lock with key 42
101              
102             if ($l->lock) { # Blocking call
103             # Critical section
104             ...
105              
106             $l->unlock; # Release the lock
107             }
108              
109             Acquire access to the lock and unlocks it.
110              
111             C has the same arguments as L C.
112              
113             =head2 try_lock
114              
115             use Mojo::IOLoop::ReadWriteProcess qw(lock);
116              
117             my $l = lock(key => "42"); # Create Lock with key 42
118              
119             if ($l->try_lock) { # Non Blocking call
120             # Critical section
121             ...
122              
123             $l->unlock; # Release the lock
124             }
125              
126             Try to acquire lock in a non-blocking way.
127              
128             =head2 lock_section
129              
130             use Mojo::IOLoop::ReadWriteProcess qw(lock);
131             my $l = lock(key => 3331);
132             my $e = 1;
133             $l->lock_section(sub { $e = 0; die; }); # or also $l->section(sub { $e = 0 });
134              
135             $l->locked; # is 0
136              
137             Executes a function inside a locked section. Errors are caught so lock is released in case of failures.
138              
139             =head1 ATTRIBUTES
140              
141             L inherits all attributes from L and provides
142             the following new ones.
143              
144             =head2 flags
145              
146             use Mojo::IOLoop::ReadWriteProcess qw(lock);
147             use IPC::SysV qw(IPC_CREAT IPC_EXCL S_IRUSR S_IWUSR);
148              
149             my $l = lock(flags=> IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
150              
151             Sets flag for the lock. In such way you can limit the access to the lock, e.g. to specific user/group process.
152              
153             =head2 key
154              
155             use Mojo::IOLoop::ReadWriteProcess qw(lock);
156             my $l = lock(key => 42);
157              
158             Sets the lock key that is used to retrieve the lock among different processes, must be an integer.
159              
160             =head2 locked
161              
162             use Mojo::IOLoop::ReadWriteProcess qw(lock);
163              
164             my $l = lock(key => 42);
165              
166             $l->lock_section(sub {
167             $l->locked; # 1
168             });
169              
170             $l->locked; # 0
171              
172             Returns the lock status
173              
174             =head1 DEBUGGING
175              
176             You can set MOJO_PROCESS_DEBUG environment variable to get diagnostics about the process execution.
177              
178             MOJO_PROCESS_DEBUG=1
179              
180             =head1 LICENSE
181              
182             Copyright (C) Ettore Di Giacinto.
183              
184             This library is free software; you can redistribute it and/or modify
185             it under the same terms as Perl itself.
186              
187             =head1 AUTHOR
188              
189             Ettore Di Giacinto Eedigiacinto@suse.comE
190              
191             =cut
192              
193             !!42;