File Coverage

blib/lib/MCE/Mutex/Channel2.pm
Criterion Covered Total %
statement 59 77 76.6
branch 17 52 32.6
condition 2 9 22.2
subroutine 14 18 77.7
pod 6 6 100.0
total 98 162 60.4


line stmt bran cond sub pod time code
1             ###############################################################################
2             ## ----------------------------------------------------------------------------
3             ## MCE::Mutex::Channel2 - Provides two mutexes using a single channel.
4             ##
5             ###############################################################################
6              
7             package MCE::Mutex::Channel2;
8              
9 14     14   94 use strict;
  14         19  
  14         516  
10 14     14   65 use warnings;
  14         25  
  14         1017  
11              
12 14     14   149 no warnings qw( threads recursion uninitialized once );
  14         18  
  14         1122  
13              
14             our $VERSION = '1.902';
15              
16 14     14   77 use if $^O eq 'MSWin32', 'threads';
  14         38  
  14         723  
17 14     14   86 use if $^O eq 'MSWin32', 'threads::shared';
  14         41  
  14         523  
18              
19 14     14   58 use base 'MCE::Mutex::Channel';
  14         25  
  14         8428  
20 14     14   92 use MCE::Util ();
  14         19  
  14         262  
21 14     14   51 use Scalar::Util 'looks_like_number';
  14         19  
  14         644  
22 14     14   62 use Time::HiRes 'alarm';
  14         30  
  14         70  
23              
24             my $is_MSWin32 = ($^O eq 'MSWin32') ? 1 : 0;
25             my $tid = $INC{'threads.pm'} ? threads->tid() : 0;
26              
27             sub CLONE {
28 0 0   0   0 $tid = threads->tid() if $INC{'threads.pm'};
29             }
30              
31             sub MCE::Mutex::Channel2::_guard::DESTROY {
32 46     46   103 my ($pid, $obj) = @{ $_[0] };
  46         438  
33 46 50       683 CORE::syswrite($obj->{_r_sock}, '0'), $obj->{$pid.'b'} = 0 if $obj->{$pid.'b'};
34              
35 46         1456 return;
36             }
37              
38             ###############################################################################
39             ## ----------------------------------------------------------------------------
40             ## Public methods.
41             ##
42             ###############################################################################
43              
44             sub new {
45 24     24 1 320 my ($class, %obj) = (@_, impl => 'Channel2');
46 24 50       227 $obj{_init_pid} = $tid ? $$ .'.'. $tid : $$;
47 24 50       86 $obj{_t_lock} = threads::shared::share( my $t_lock ) if $is_MSWin32;
48 24 50       52 $obj{_t_lock2} = threads::shared::share( my $t_lock2 ) if $is_MSWin32;
49              
50 24         108 MCE::Util::_sock_pair(\%obj, qw(_r_sock _w_sock), undef, 1);
51              
52 24         601 CORE::syswrite($obj{_w_sock}, '0');
53 24         187 CORE::syswrite($obj{_r_sock}, '0');
54 24         103 bless \%obj, $class;
55              
56 24 100 66     269 if ( caller !~ /^MCE:?/ || caller(1) !~ /^MCE:?/ ) {
57 1         5 MCE::Mutex::Channel::_save_for_global_cleanup(\%obj);
58             }
59              
60 24         139 return \%obj;
61             }
62              
63             sub lock2 {
64 42 50   42 1 303 my ($pid, $obj) = ($tid ? $$ .'.'. $tid : $$, shift);
65              
66 42 50       238 unless ($obj->{ $pid.'b' }) {
67             CORE::lock($obj->{_t_lock2}), MCE::Util::_sock_ready($obj->{_w_sock})
68 42 50       92 if $is_MSWin32;
69 42         158 MCE::Util::_sysread($obj->{_w_sock}, my($b), 1), $obj->{ $pid.'b' } = 1;
70             }
71              
72 42         110 return;
73             }
74              
75             sub guard_lock2 {
76 0     0 1 0 &lock2(@_);
77 0 0       0 bless([ $tid ? $$ .'.'. $tid : $$, $_[0] ], MCE::Mutex::Channel2::_guard::);
78             }
79              
80             *lock_exclusive2 = \&lock2;
81             *lock_shared2 = \&lock2;
82              
83             sub unlock2 {
84 42 50   42 1 207 my ($pid, $obj) = ($tid ? $$ .'.'. $tid : $$, shift);
85              
86             CORE::syswrite($obj->{_r_sock}, '0'), $obj->{ $pid.'b' } = 0
87 42 50       457 if $obj->{ $pid.'b' };
88              
89 42         102 return;
90             }
91              
92             sub synchronize2 {
93 46 50   46 1 608 my ($pid, $obj, $code) = ($tid ? $$ .'.'. $tid : $$, shift, shift);
94 46         96 my (@ret, $b);
95              
96 46 50       245 return unless ref($code) eq 'CODE';
97              
98             # lock, run, unlock - inlined for performance
99 46         726 my $guard = bless([ $pid, $obj ], MCE::Mutex::Channel2::_guard::);
100 46 50       551 unless ($obj->{ $pid.'b' }) {
101             CORE::lock($obj->{_t_lock2}), MCE::Util::_sock_ready($obj->{_w_sock})
102 46 50       234 if $is_MSWin32;
103 46         411 MCE::Util::_sysread($obj->{_w_sock}, $b, 1), $obj->{ $pid.'b' } = 1;
104             }
105             (defined wantarray)
106 46 0       354 ? @ret = wantarray ? $code->(@_) : scalar $code->(@_)
    50          
107             : $code->(@_);
108              
109 46 50       713 return wantarray ? @ret : $ret[-1];
110             }
111              
112             *enter2 = \&synchronize2;
113              
114             sub timedwait2 {
115 0     0 1   my ($obj, $timeout) = @_;
116              
117 0 0         $timeout = 1 unless defined $timeout;
118 0 0 0       Carp::croak('MCE::Mutex::Channel2: timedwait2 (timeout) is not valid')
119             if (!looks_like_number($timeout) || $timeout < 0);
120              
121 0 0         $timeout = 0.0003 if $timeout < 0.0003;
122 0           local $@; my $ret = '';
  0            
123              
124 0           eval {
125 0     0     local $SIG{ALRM} = sub { alarm 0; die "alarm clock restart\n" };
  0            
  0            
126 0 0         alarm $timeout unless $is_MSWin32;
127              
128             die "alarm clock restart\n"
129 0 0 0       if $is_MSWin32 && MCE::Util::_sock_ready($obj->{_w_sock}, $timeout);
130              
131 0 0         (!$is_MSWin32)
132             ? ($obj->lock_exclusive2, $ret = 1, alarm(0))
133             : ($obj->lock_exclusive2, $ret = 1);
134             };
135              
136 0 0         alarm 0 unless $is_MSWin32;
137              
138 0           $ret;
139             }
140              
141             1;
142              
143             __END__
144              
145             ###############################################################################
146             ## ----------------------------------------------------------------------------
147             ## Module usage.
148             ##
149             ###############################################################################
150              
151             =head1 NAME
152              
153             MCE::Mutex::Channel2 - Provides two mutexes using a single channel
154              
155             =head1 VERSION
156              
157             This document describes MCE::Mutex::Channel2 version 1.902
158              
159             =head1 DESCRIPTION
160              
161             A socket implementation based on C<MCE::Mutex>. The secondary lock is accessed
162             by calling methods with the C<2> suffix.
163              
164             The API is described in L<MCE::Mutex>.
165              
166             =head2 construction
167              
168             =over 3
169              
170             =item new
171              
172             my $mutex = MCE::Mutex->new( impl => 'Channel2' );
173              
174             =back
175              
176             =head2 primary lock
177              
178             =over 3
179              
180             =item lock
181              
182             =item lock_exclusive
183              
184             =item lock_shared
185              
186             =item guard_lock
187              
188             =item unlock
189              
190             =item synchronize
191              
192             =item enter
193              
194             =item timedwait
195              
196             =back
197              
198             =head2 secondary lock
199              
200             =over 3
201              
202             =item lock2
203              
204             =item lock_exclusive2
205              
206             =item lock_shared2
207              
208             =item guard_lock2
209              
210             =item unlock2
211              
212             =item synchronize2
213              
214             =item enter2
215              
216             =item timedwait2
217              
218             =back
219              
220             =head1 AUTHOR
221              
222             Mario E. Roy, S<E<lt>marioeroy AT gmail DOT comE<gt>>
223              
224             =cut
225