File Coverage

lib/IOMux/Select.pm
Criterion Covered Total %
statement 24 74 32.4
branch 0 30 0.0
condition 0 3 0.0
subroutine 8 16 50.0
pod 4 6 66.6
total 36 129 27.9


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