File Coverage

blib/lib/Mutex/Channel.pm
Criterion Covered Total %
statement 38 69 55.0
branch 7 54 12.9
condition 0 6 0.0
subroutine 11 17 64.7
pod 5 5 100.0
total 61 151 40.4


line stmt bran cond sub pod time code
1             ###############################################################################
2             ## ----------------------------------------------------------------------------
3             ## Mutex::Channel - Mutex locking via a pipe or socket.
4             ##
5             ###############################################################################
6              
7             package Mutex::Channel;
8              
9 2     2   767 use strict;
  2         4  
  2         50  
10 2     2   8 use warnings;
  2         3  
  2         47  
11              
12 2     2   8 no warnings qw( threads recursion uninitialized once );
  2         3  
  2         89  
13              
14             our $VERSION = '1.009';
15              
16 2     2   1120 use if $^O eq 'MSWin32', 'threads';
  2         24  
  2         10  
17 2     2   79 use if $^O eq 'MSWin32', 'threads::shared';
  2         3  
  2         23  
18              
19 2     2   54 use base 'Mutex';
  2         2  
  2         152  
20 2     2   348 use Mutex::Util;
  2         4  
  2         43  
21 2     2   8 use Scalar::Util 'looks_like_number';
  2         2  
  2         111  
22 2     2   458 use Time::HiRes 'alarm';
  2         1109  
  2         8  
23              
24             my $is_MSWin32 = ($^O eq 'MSWin32') ? 1 : 0;
25             my $use_pipe = ($^O !~ /mswin|mingw|msys|cygwin/i && $] gt '5.010000');
26             my $tid = $INC{'threads.pm'} ? threads->tid : 0;
27              
28             sub CLONE {
29 0 0   0   0 $tid = threads->tid if $INC{'threads.pm'};
30             }
31              
32             sub DESTROY {
33 2 50   2   1257 my ($pid, $obj) = ($tid ? $$ .'.'. $tid : $$, @_);
34              
35 2 50       6 CORE::syswrite($obj->{_w_sock}, '0'), $obj->{ $pid } = 0 if $obj->{ $pid };
36              
37 2 50       7 if ( $obj->{_init_pid} eq $pid ) {
38 2 50       6 $use_pipe
39             ? Mutex::Util::destroy_pipes($obj, qw(_w_sock _r_sock))
40             : Mutex::Util::destroy_socks($obj, qw(_w_sock _r_sock));
41             }
42              
43 2         7 return;
44             }
45              
46             ###############################################################################
47             ## ----------------------------------------------------------------------------
48             ## Public methods.
49             ##
50             ###############################################################################
51              
52             sub new {
53 2     2 1 7 my ($class, %obj) = (@_, impl => 'Channel');
54 2 50       7 $obj{_init_pid} = $tid ? $$ .'.'. $tid : $$;
55 2 50       3 $obj{_t_lock} = threads::shared::share( my $t_lock ) if $is_MSWin32;
56              
57 2 50       10 $use_pipe
58             ? Mutex::Util::pipe_pair(\%obj, qw(_r_sock _w_sock))
59             : Mutex::Util::sock_pair(\%obj, qw(_r_sock _w_sock));
60              
61 2         35 CORE::syswrite($obj{_w_sock}, '0');
62              
63 2         14 return bless(\%obj, $class);
64             }
65              
66             sub lock {
67 0 0   0 1   my ($pid, $obj) = ($tid ? $$ .'.'. $tid : $$, shift);
68              
69             CORE::lock($obj->{_t_lock}), Mutex::Util::_sock_ready($obj->{_r_sock})
70 0 0         if $is_MSWin32;
71             Mutex::Util::_sysread($obj->{_r_sock}, my($b), 1), $obj->{ $pid } = 1
72 0 0         unless $obj->{ $pid };
73              
74 0           return;
75             }
76              
77             *lock_exclusive = \&lock;
78             *lock_shared = \&lock;
79              
80             sub unlock {
81 0 0   0 1   my ($pid, $obj) = ($tid ? $$ .'.'. $tid : $$, shift);
82              
83             CORE::syswrite($obj->{_w_sock}, '0'), $obj->{ $pid } = 0
84 0 0         if $obj->{ $pid };
85              
86 0           return;
87             }
88              
89             sub synchronize {
90 0 0   0 1   my ($pid, $obj, $code) = ($tid ? $$ .'.'. $tid : $$, shift, shift);
91 0           my (@ret, $b);
92              
93 0 0         return unless ref($code) eq 'CODE';
94              
95             # lock, run, unlock - inlined for performance
96             CORE::lock($obj->{_t_lock}), Mutex::Util::_sock_ready($obj->{_r_sock})
97 0 0         if $is_MSWin32;
98             Mutex::Util::_sysread($obj->{_r_sock}, $b, 1), $obj->{ $pid } = 1
99 0 0         unless $obj->{ $pid };
100              
101             (defined wantarray)
102 0 0         ? @ret = wantarray ? $code->(@_) : scalar $code->(@_)
    0          
103             : $code->(@_);
104              
105 0           CORE::syswrite($obj->{_w_sock}, '0'), $obj->{ $pid } = 0;
106              
107 0 0         return wantarray ? @ret : $ret[-1];
108             }
109              
110             *enter = \&synchronize;
111              
112             sub timedwait {
113 0     0 1   my ($obj, $timeout) = @_;
114              
115 0 0         $timeout = 1 unless defined $timeout;
116 0 0 0       Carp::croak('Mutex::Channel: timedwait (timeout) is not valid')
117             if (!looks_like_number($timeout) || $timeout < 0);
118              
119 0 0         $timeout = 0.0003 if $timeout < 0.0003;
120 0           local $@; my $ret = '';
  0            
121              
122 0           eval {
123 0     0     local $SIG{ALRM} = sub { alarm 0; die "alarm clock restart\n" };
  0            
  0            
124 0 0         alarm $timeout unless $is_MSWin32;
125              
126             die "alarm clock restart\n"
127 0 0 0       if $is_MSWin32 && Mutex::Util::_sock_ready($obj->{_r_sock}, $timeout);
128              
129 0 0         (!$is_MSWin32)
130             ? ($obj->lock_exclusive, $ret = 1, alarm(0))
131             : ($obj->lock_exclusive, $ret = 1);
132             };
133              
134 0 0         alarm 0 unless $is_MSWin32;
135              
136 0           $ret;
137             }
138              
139             1;
140              
141             __END__