File Coverage

blib/lib/MCE/Mutex.pm
Criterion Covered Total %
statement 22 22 100.0
branch 5 6 83.3
condition 1 2 50.0
subroutine 7 7 100.0
pod 2 2 100.0
total 37 39 94.8


line stmt bran cond sub pod time code
1             ###############################################################################
2             ## ----------------------------------------------------------------------------
3             ## Locking for Many-Core Engine.
4             ##
5             ###############################################################################
6              
7             package MCE::Mutex;
8              
9 112     112   282040 use strict;
  112         207  
  112         4511  
10 112     112   538 use warnings;
  112         218  
  112         7077  
11              
12 112     112   680 no warnings qw( threads recursion uninitialized );
  112         186  
  112         7785  
13              
14             our $VERSION = '1.902';
15              
16             ## no critic (BuiltinFunctions::ProhibitStringyEval)
17             ## no critic (TestingAndDebugging::ProhibitNoStrict)
18              
19 112     112   656 use Carp ();
  112         197  
  112         29309  
20              
21             ## global Mutex used by MCE, MCE::Child, and MCE::Hobo inside threads
22             ## on UNIX platforms
23              
24             if ( $INC{'threads.pm'} && $^O !~ /mswin|mingw|msys|cygwin/i ) {
25             $MCE::_GMUTEX = MCE::Mutex->new( impl => 'Channel' );
26             MCE::Mutex::Channel::_save_for_global_cleanup($MCE::_GMUTEX);
27             }
28              
29             sub new {
30 499     499 1 541301 my ($class, %argv) = @_;
31             my $impl = defined($argv{impl})
32 499 100       1754 ? $argv{impl} : defined($argv{path}) ? 'Flock' : 'Channel';
    100          
33              
34 499         1469 $impl = ucfirst( lc $impl );
35              
36 499 50       32888 eval "require MCE::Mutex::$impl; 1;" ||
37             Carp::croak("Could not load Mutex implementation '$impl': $@");
38              
39 499         2591 my $pkg = 'MCE::Mutex::'.$impl;
40 112     112   752 no strict 'refs';
  112         680  
  112         16671  
41              
42 499         2327 return $pkg->new( %argv );
43             }
44              
45             ## base class method
46              
47             sub impl {
48 5   50 5 1 67 return $_[0]->{impl} || 'Not defined';
49             }
50              
51             1;
52              
53             __END__
54              
55             ###############################################################################
56             ## ----------------------------------------------------------------------------
57             ## Module usage.
58             ##
59             ###############################################################################
60              
61             =head1 NAME
62              
63             MCE::Mutex - Locking for Many-Core Engine
64              
65             =head1 VERSION
66              
67             This document describes MCE::Mutex version 1.902
68              
69             =head1 SYNOPSIS
70              
71             use MCE::Mutex;
72              
73             my $mutex = MCE::Mutex->new;
74              
75             {
76             use MCE::Flow max_workers => 4;
77              
78             mce_flow sub {
79             $mutex->lock;
80              
81             # access shared resource
82             my $wid = MCE->wid; MCE->say($wid); sleep 1;
83              
84             $mutex->unlock;
85             };
86             }
87              
88             {
89             use MCE::Hobo;
90              
91             MCE::Hobo->create('work', $_) for 1..4;
92             MCE::Hobo->waitall;
93             }
94              
95             {
96             use threads;
97              
98             threads->create('work', $_) for 5..8;
99             $_->join for ( threads->list );
100             }
101              
102             sub work {
103             my ($id) = @_;
104             $mutex->lock;
105              
106             # access shared resource
107             print $id, "\n";
108             sleep 1;
109              
110             $mutex->unlock;
111             }
112              
113             =head1 DESCRIPTION
114              
115             This module implements locking methods that can be used to coordinate access
116             to shared data from multiple workers spawned as processes or threads.
117              
118             The inspiration for this module came from reading Mutex for Ruby.
119              
120             =head1 API DOCUMENTATION
121              
122             =head2 MCE::Mutex->new ( )
123              
124             =head2 MCE::Mutex->new ( impl => "Channel" )
125              
126             =head2 MCE::Mutex->new ( impl => "Flock", [ path => "/tmp/file.lock" ] )
127              
128             =head2 MCE::Mutex->new ( path => "/tmp/file.lock" )
129              
130             Creates a new mutex.
131              
132             Channel locking (the default), unless C<path> is given, is through a pipe
133             or socket depending on the platform. The advantage of channel locking is
134             not having to re-establish handles inside new processes and threads.
135              
136             For Fcntl-based locking, it is the responsibility of the caller to remove
137             the C<tempfile>, associated with the mutex, when path is given. Otherwise,
138             it establishes a C<tempfile> internally including removal on scope exit.
139              
140             =head2 $mutex->impl ( void )
141              
142             Returns the implementation used for the mutex.
143              
144             $m1 = MCE::Mutex->new( );
145             $m1->impl(); # Channel
146              
147             $m2 = MCE::Mutex->new( path => /tmp/my.lock );
148             $m2->impl(); # Flock
149              
150             $m3 = MCE::Mutex->new( impl => "Channel" );
151             $m3->impl(); # Channel
152              
153             $m4 = MCE::Mutex->new( impl => "Flock" );
154             $m4->impl(); # Flock
155              
156             Current API available since 1.822.
157              
158             =head2 $mutex->lock ( void )
159              
160             =head2 $mutex->lock_exclusive ( void )
161              
162             Attempts to grab an exclusive lock and waits if not available. Multiple calls
163             to mutex->lock by the same process or thread is safe. The mutex will remain
164             locked until mutex->unlock is called.
165              
166             The method C<lock_exclusive> is an alias for C<lock>, available since 1.822.
167              
168             ( my $mutex = MCE::Mutex->new( path => $0 ) )->lock_exclusive;
169              
170             =head2 $mutex->lock_shared ( void )
171              
172             Like C<lock_exclusive>, but attempts to grab a shared lock instead.
173             The C<lock_shared> method is an alias to C<lock> otherwise for non-Fcntl
174             implementations.
175              
176             Current API available since 1.822.
177              
178             =head2 $guard = $mutex->guard_lock ( void )
179              
180             This method calls C<lock> and returns a guard object. When the guard object is
181             destroyed, it automatically calls C<unlock>.
182              
183             Current API available since 1.889.
184              
185             =head2 $mutex->unlock ( void )
186              
187             Releases the lock. A held lock by an exiting process or thread is released
188             automatically.
189              
190             =head2 $mutex->synchronize ( sub { ... }, @_ )
191              
192             =head2 $mutex->enter ( sub { ... }, @_ )
193              
194             Obtains a lock, runs the code block, and releases the lock after the block
195             completes. Optionally, the method is C<wantarray> aware.
196              
197             my $val = $mutex->synchronize( sub {
198             # access shared resource
199             return 'scalar';
200             });
201              
202             my @ret = $mutex->enter( sub {
203             # access shared resource
204             return @list;
205             });
206              
207             The method C<enter> is an alias for C<synchronize>, available since 1.822.
208              
209             =head2 $mutex->timedwait ( floating_seconds )
210              
211             Blocks until obtaining an exclusive lock. A false value is returned
212             if the timeout is reached, and a true value otherwise. The default is
213             1 second.
214              
215             my $mutex = MCE::Mutex->new( path => $0 );
216              
217             # terminate script if a previous instance is still running
218              
219             exit unless $mutex->timedwait( 2 );
220              
221             ...
222              
223             Current API available since 1.822.
224              
225             =head1 INDEX
226              
227             L<MCE|MCE>, L<MCE::Core>
228              
229             =head1 AUTHOR
230              
231             Mario E. Roy, S<E<lt>marioeroy AT gmail DOT comE<gt>>
232              
233             =cut
234