File Coverage

lib/IOMux/Select.pm
Criterion Covered Total %
statement 27 79 34.1
branch 0 34 0.0
condition 0 3 0.0
subroutine 9 17 52.9
pod 4 6 66.6
total 40 139 28.7


line stmt bran cond sub pod time code
1             # Copyrights 2011-2015 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5 1     1   944 use warnings;
  1         2  
  1         30  
6 1     1   6 use strict;
  1         2  
  1         32  
7              
8             package IOMux::Select;
9 1     1   5 use vars '$VERSION';
  1         3  
  1         50  
10             $VERSION = '1.00';
11              
12 1     1   5 use base 'IOMux';
  1         1  
  1         71  
13              
14 1     1   6 use Log::Report 'iomux';
  1         2  
  1         6  
15              
16 1     1   299 use List::Util 'min';
  1         2  
  1         89  
17 1     1   6 use POSIX 'errno_h';
  1         3  
  1         7  
18              
19             $SIG{PIPE} = 'IGNORE'; # pipes are handled in select
20              
21              
22             sub init($)
23 0     0 0   { my ($self, $args) = @_;
24 0           $self->SUPER::init($args);
25 0           $self->{IMS_readers} = '';
26 0           $self->{IMS_writers} = '';
27 0           $self->{IMS_excepts} = '';
28 0           $self;
29             }
30              
31             #-----------------
32              
33             sub _flags2string($);
34             sub showFlags($;$$)
35 0     0 1   { my $self = shift;
36 0 0         return _flags2string(shift)
37             if @_==1;
38              
39 0 0         my ($rdbits, $wrbits, $exbits) = @_ ? @_ : $self->selectFlags;
40 0           my $rd = _flags2string $rdbits;
41 0           my $wr = _flags2string $wrbits;
42 0           my $ex = _flags2string $exbits;
43              
44 0           <<__SHOW;
45             read: $rd
46             write: $wr
47             except: $ex
48             __SHOW
49             }
50              
51             sub _flags2string($)
52 0     0     { my $bytes = shift;
53 1     1   781 use bytes;
  1         3  
  1         9  
54 0           my $bits = length($bytes) * 8;
55 0           my $out = '';
56 0           for my $fileno (0..$bits-1)
57 0 0         { $out .= vec($bytes, $fileno, 1)==1 ? ($fileno%10) : '-';
58             }
59 0           $out =~ s/-+$//;
60 0 0         length $out ? $out : '(none)';
61             }
62              
63             #--------------------------
64              
65             sub fdset($$$$$)
66 0     0 1   { my ($self, $fileno, $state, $r, $w, $e) = @_;
67 0 0         vec($self->{IMS_readers}, $fileno, 1) = $state if $r;
68 0 0         vec($self->{IMS_writers}, $fileno, 1) = $state if $w;
69 0 0         vec($self->{IMS_excepts}, $fileno, 1) = $state if $e;
70 1     1   219 use Carp 'cluck';
  1         2  
  1         505  
71 0 0         cluck 'set write bit' if $w;
72             # trace "fdset(@_), now: " .$self->showFlags($self->waitFlags);
73             }
74              
75             sub one_go($$)
76 0     0 0   { my ($self, $wait, $heartbeat) = @_;
77              
78 0           trace "SELECT=\n".$self->showFlags($self->waitFlags);
79              
80             my ($rdready, $wrready, $exready)
81 0           = @$self{ qw/IMS_readers IMS_writers IMS_excepts/ };
82              
83 0           my ($numready, $timeleft)
84             = select $rdready, $wrready, $exready, $wait;
85              
86 0           trace "READY=\n".$self->showFlags($rdready, $wrready, $exready);
87              
88 0 0         if($heartbeat)
89             { # can be collected from within heartbeat
90 0           $self->{IMS_select_flags} = [$rdready, $wrready, $exready];
91 0           $heartbeat->($self, $numready, $timeleft)
92             }
93              
94 0 0         unless(defined $numready)
95 0 0 0       { return if $! == EINTR || $! == EAGAIN;
96 0           alert "leaving loop";
97 0           return 0;
98             }
99              
100             # Hopefully the regexp improves performance when many slow connections
101 0 0         $self->_ready(muxReadFlagged => $rdready) if $rdready =~ m/[^\x00]/;
102 0 0         $self->_ready(muxWriteFlagged => $wrready) if $wrready =~ m/[^\x00]/;
103 0 0         $self->_ready(muxExceptFlagged => $exready) if $exready =~ m/[^\x00]/;
104              
105 0           sleep 1;
106 0           1; # success
107             }
108              
109             # It would be nice to have an algorithm which is better than O(n)
110             sub _ready($$)
111 0     0     { my ($self, $call, $flags) = @_;
112 0           my $handlers = $self->_handlers;
113 0           while(my ($fileno, $conn) = each %$handlers)
114 0 0         { $conn->$call($fileno) if (vec $flags, $fileno, 1)==1;
115 0 0         warn "$conn $call($fileno)" if (vec $flags, $fileno, 1)==1;
116             }
117             }
118              
119              
120             sub waitFlags()
121 0     0 1   { my $self = shift;
122 0           @{$self}{ qw/IMS_readers IMS_writers IMS_excepts/ };
  0            
123             }
124              
125              
126 0 0   0 1   sub selectFlags() { @{shift->{IMS_select_flags} || []} }
  0            
127              
128             1;
129              
130             __END__