File Coverage

blib/lib/IO/Mux/Select.pm
Criterion Covered Total %
statement 100 100 100.0
branch 25 28 89.2
condition 5 6 83.3
subroutine 15 15 100.0
pod 2 7 28.5
total 147 156 94.2


line stmt bran cond sub pod time code
1             package IO::Mux::Select ;
2              
3 1     1   25765 use strict ;
  1         2  
  1         44  
4 1     1   1273 use IO::Select ;
  1         1978  
  1         64  
5 1     1   672 use IO::Mux ;
  1         4  
  1         31  
6 1     1   8 use IO::Mux::Handle ;
  1         2  
  1         37  
7 1     1   6 use IO::Mux::Packet ;
  1         1  
  1         23  
8 1     1   5 use Carp ;
  1         1  
  1         1047  
9              
10              
11             our $VERSION = '0.08' ;
12              
13              
14             sub new {
15 1     1 1 496 my $class = shift ;
16              
17 1         3 my $this = {} ;
18 1         7 $this->{'select'} = new IO::Select() ;
19 1         11 $this->{mux_handles} = {} ;
20 1         3 bless($this, $class) ;
21              
22 1         4 $this->add(@_) ;
23              
24 1         2 return $this ;
25             }
26              
27              
28             sub _get_select {
29 50     50   76 my $this = shift ;
30              
31 50         213 return $this->{'select'} ;
32             }
33              
34              
35             sub _get_mux_handles {
36 42     42   58 my $this = shift ;
37              
38 42         158 return $this->{mux_handles} ;
39             }
40              
41              
42             sub add {
43 4     4 0 1135 my $this = shift ;
44              
45 4         9 foreach my $h (@_){
46 3 100       33 if ($h->isa('IO::Mux::Handle')){
47 2         6 $this->_get_mux_handles()->{$h->_get_tie()->_get_id()} = $h ;
48             }
49             else {
50 1         4 $this->_get_select()->add($h) ;
51             }
52             }
53             }
54              
55              
56             sub remove {
57 3     3 0 2491 my $this = shift ;
58              
59 3         11 foreach my $h (@_){
60 3 100       27 if ($h->isa('IO::Mux::Handle')){
    100          
61 1         3 delete $this->_get_mux_handles()->{$h->_get_tie()->_get_id()} ;
62             }
63             elsif ($this->_get_select()->exists($h)){
64 1         39 $this->_get_select()->remove($h) ;
65             }
66             }
67             }
68              
69              
70             sub exists {
71 5     5 0 96 my $this = shift ;
72 5         10 my $h = shift ;
73              
74 5 100       21 if ($h->isa('IO::Mux::Handle')){
75 3         7 return $this->_get_mux_handles()->{$h->_get_tie()->_get_id()} ;
76             }
77             else {
78 2         7 return $this->_get_select()->exists($h) ;
79             }
80             }
81              
82              
83             sub handles {
84 3     3 0 6 my $this = shift ;
85              
86 3         7 my @ret = () ;
87 3         5 push @ret, values %{$this->_get_mux_handles()} ;
  3         9  
88 3         9 push @ret, $this->_get_select()->handles() ;
89              
90 3         69 return @ret ;
91             }
92              
93              
94             sub count {
95 3     3 0 1294 my $this = shift ;
96              
97 3         9 return scalar($this->handles()) ;
98             }
99              
100              
101             sub can_read {
102 15     15 1 4047 my $this = shift ;
103 15         24 my $timeout = shift ;
104              
105             # First, we will check to see if the IO::Mux::Handles have data in their buffers.
106 15         31 my @ready = () ;
107 15         20 foreach my $h (values %{$this->_get_mux_handles()}){
  15         37  
108 17 100 100     77 if ((eof($h))||($h->_get_tie()->_get_buffer()->get_length() > 0)){
109 2         7 push @ready, $h ;
110             }
111             }
112              
113 15 100       47 if (scalar(@ready)){
114             # Maybe some real handles are immediately ready
115 2         6 push @ready, $this->_get_select()->can_read(0) ;
116 2         17 return @ready ;
117             }
118              
119             # So it seems we may have to wait after all. We now need to build a list
120             # of all the REAL handles underneath all the IO::Mux::Handles.
121 13         30 my %mux_objects = () ;
122 13         19 foreach my $h (values %{$this->_get_mux_handles()}){
  13         30  
123 14         44 my $mux = $h->_get_tie()->_get_mux() ;
124 14         44 my $rh = $mux->_get_handle() ;
125 14 100       52 if (! exists($mux_objects{$rh})){
126 12         99 $mux_objects{$rh} = {mux => $mux, mux_handles => {}} ;
127             }
128 14         83 $mux_objects{$rh}->{mux_handles}->{$h} = $h ;
129             }
130              
131 13         36 my @real_handles = map {$_->{mux}->_get_handle()} values(%mux_objects) ;
  12         44  
132 13         33 $this->_get_select()->add(@real_handles) ;
133 13         495 @ready = $this->_get_select()->can_read($timeout) ;
134 13         381 $this->_get_select()->remove(@real_handles) ;
135              
136 13 100       423 if (scalar(@ready)){
137 9         18 my @tmp = @ready ;
138 9         20 my %ready = () ;
139 9         18 @ready = () ;
140 9         24 foreach my $h (@tmp){
141 10         23 my $mux_data = $mux_objects{$h} ;
142 10 100       27 if ($mux_data){
143 6         9 my $mux = $mux_data->{mux} ;
144             # We have data ready on the REAL handle. Let's consume the packet
145             # and add the corresponding IO::Mux::Handle in the new ready list.
146 6         23 while ((my $p = $mux->_read_packet(0)) != -1){
147 7 100 66     36 if ((! defined($p))||(! $p)){
148             # ERROR or EOF on the real handle. Return all mux_handles
149             # as they all now are at EOF or have an error state.
150 2         6 foreach my $mh (values %{$mux_data->{mux_handles}}){
  2         9  
151 2 50       10 if (! $ready{$mh}){
152 2         4 push @ready, $mh ;
153 2         10 $ready{$mh} = 1 ;
154             }
155             }
156 2         11 last ;
157             }
158             else {
159 5         12 my $mh = $this->_get_mux_handles()->{$p->get_id()} ;
160 5 50       14 next unless defined($mh) ;
161 5 50       14 if (! $ready{$mh}){
162 5         7 push @ready, $mh ;
163 5 100       13 if ($p->is_eof()){
164 1         4 $mh->_get_tie()->_set_eof() ;
165             }
166 5         28 $ready{$mh} = 1 ;
167             }
168             }
169             }
170             }
171             else {
172             # REAL handle, we simply push it.
173 4         14 push @ready, $h ;
174             }
175             }
176             }
177              
178 13         77 return @ready ;
179             }
180              
181              
182             1 ;
183             __END__