File Coverage

lib/IOMux/Select.pm
Criterion Covered Total %
statement 24 70 34.2
branch 0 30 0.0
condition 0 3 0.0
subroutine 8 16 50.0
pod 4 6 66.6
total 36 125 28.8


line stmt bran cond sub pod time code
1             # Copyrights 2011 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 1.07.
5 1     1   1323 use warnings;
  1         2  
  1         39  
6 1     1   6 use strict;
  1         2  
  1         45  
7              
8             package IOMux::Select;
9 1     1   5 use vars '$VERSION';
  1         2  
  1         52  
10             $VERSION = '0.12';
11              
12 1     1   5 use base 'IOMux';
  1         3  
  1         102  
13              
14 1     1   5 use Log::Report 'iomux';
  1         2  
  1         10  
15              
16 1     1   315 use List::Util 'min';
  1         2  
  1         73  
17 1     1   5 use POSIX 'errno_h';
  1         2  
  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   788 use bytes;
  1         4  
  1         10  
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             # trace "fdset(@_), now: " .$self->showFlags($self->waitFlags);
71             }
72              
73             sub one_go($$)
74 0     0 0   { my ($self, $wait, $heartbeat) = @_;
75              
76             # trace "SELECT=".$self->showFlags($self->waitFlags);
77              
78 0           my ($rdready, $wrready, $exready) = ('', '', '');
79 0           my ($numready, $timeleft) = select
80             +($rdready = $self->{IMS_readers})
81             , ($wrready = $self->{IMS_writers})
82             , ($exready = $self->{IMS_excepts})
83             , $wait;
84              
85             # trace "READY=".$self->showFlags($rdready, $wrready, $exready);
86              
87 0 0         if($heartbeat)
88             { # can be collected from within heartbeat
89 0           $self->{IMS_select_flags} = [$rdready, $wrready, $exready];
90 0           $heartbeat->($self, $numready, $timeleft)
91             }
92              
93 0 0         unless(defined $numready)
94 0 0 0       { return if $! == EINTR || $! == EAGAIN;
95 0           alert "Leaving loop with $!";
96 0           return 0;
97             }
98              
99             # Hopefully the regexp improves performance when many slow connections
100 0 0         $self->_ready(mux_read_flagged => $rdready) if $rdready =~ m/[^\x00]/;
101 0 0         $self->_ready(mux_write_flagged => $wrready) if $wrready =~ m/[^\x00]/;
102 0 0         $self->_ready(mux_except_flagged => $exready) if $exready =~ m/[^\x00]/;
103 0           1; # success
104             }
105              
106             # It would be nice to have an algorithm which is better than O(n)
107             sub _ready($$)
108 0     0     { my ($self, $call, $flags) = @_;
109 0           my $handlers = $self->_handlers;
110 0           while(my ($fileno, $conn) = each %$handlers)
111 0 0         { $conn->$call($fileno) if (vec $flags, $fileno, 1)==1;
112             }
113             }
114              
115              
116 0     0 1   sub waitFlags() { @{$_[0]}{ qw/IMS_readers IMS_writers IMS_excepts/} }
  0            
117              
118              
119 0 0   0 1   sub selectFlags() { @{shift->{IMS_select_flags} || []} }
  0            
120              
121             1;
122              
123             __END__