File Coverage

blib/lib/IO/Mux.pm
Criterion Covered Total %
statement 86 88 97.7
branch 22 24 91.6
condition n/a
subroutine 20 20 100.0
pod 3 3 100.0
total 131 135 97.0


line stmt bran cond sub pod time code
1             package IO::Mux ;
2              
3 3     3   73269 use 5.008 ;
  3         11  
  3         247  
4 3     3   17 use strict ;
  3         6  
  3         110  
5 3     3   1201 use Symbol ;
  3         1100  
  3         227  
6 3     3   1905 use IO::Mux::Handle ;
  3         544  
  3         894  
7 3     3   24 use IO::Mux::Packet ;
  3         5  
  3         54  
8 3     3   1793 use IO::Mux::Buffer ;
  3         8  
  3         75  
9 3     3   16 use IO::Handle ;
  3         5  
  3         98  
10 3     3   3343 use IO::Select ;
  3         3693  
  3         131  
11 3     3   16 use Carp ;
  3         8  
  3         2348  
12              
13              
14             our $VERSION = '0.08' ;
15              
16              
17             sub new {
18 6     6 1 152 my $class = shift ;
19 6         10 my $fh = shift ;
20              
21 6         9 my $this = {} ;
22 6 100       29 if (UNIVERSAL::isa($fh, 'GLOB')){
23             # Make sure we save the actual IO bit, not the entire GLOB ref, because
24             # one typical usage could be to place \*STDOUT in a IO::Mux object and then
25             # do: *STDOUT = $mux. If we save the GLOB ref, that will create infinite
26             # recursion as the GLOB is deferenced each time to get the IO bit.
27 5         11 $this->{'glob'} = $fh ;
28 5         8 $fh = *{$fh}{IO} ;
  5         12  
29             }
30 6         47 $fh->autoflush(1) ;
31              
32 6         323 $this->{fh} = $fh ;
33 6         14 $this->{buffers} = {} ;
34 6         35 $this->{'select'} = new IO::Select($fh) ;
35              
36 6         266 return bless($this, $class) ;
37             }
38              
39              
40             sub get_handle {
41 2     2 1 7 my $this = shift ;
42              
43 2 100       17 return (defined($this->{'glob'}) ? $this->{'glob'} : $this->{fh}) ;
44             }
45              
46              
47             sub _get_handle {
48 105     105   126 my $this = shift ;
49              
50 105         420 return $this->{fh} ;
51             }
52              
53              
54             sub new_handle {
55 6     6 1 2297 my $this = shift ;
56              
57 6         38 return new IO::Mux::Handle($this) ;
58             }
59              
60              
61             sub _get_buffer {
62 179     179   206 my $this = shift ;
63 179         311 my $id = shift ;
64              
65 179 100       299 if (! $this->_buffer_exists($id)){
66 18         94 $this->{buffers}->{$id} = new IO::Mux::Buffer() ;
67             }
68              
69 179         765 return $this->{buffers}->{$id} ;
70             }
71              
72              
73             sub _buffer_exists {
74 198     198   197 my $this = shift ;
75 198         286 my $id = shift ;
76              
77 198         677 return defined($this->{buffers}->{$id}) ;
78             }
79              
80              
81             sub _kill_buffer {
82 18     18   25 my $this = shift ;
83 18         28 my $id = shift ;
84              
85 18         137 delete $this->{buffers}->{$id} ;
86             }
87              
88              
89             sub _read {
90 34     34   43 my $this = shift ;
91 34         37 my $id = shift ;
92 34         31 my $blocking = shift ;
93              
94 34         35 my $p = undef ;
95 34         75 while (! defined($p)){
96 38         71 my $tp = $this->_read_packet($blocking) ;
97 37 50       130 if (! defined($tp)){
    100          
    100          
98 0         0 return undef ;
99             }
100             elsif (! $tp){
101 1         2 return 0 ;
102             }
103             elsif ($tp == -1){
104             # No packet available in non-blocking mode.
105 10         24 return -1 ;
106             }
107             else {
108 26 100       60 if ($tp->get_id() eq $id){
109 22 100       46 if (! $tp->is_eof()){
110 18         58 $p = $tp ;
111             }
112             else {
113 4         14 return 0 ;
114             }
115             }
116             }
117             }
118              
119 18         47 return $p->get_length() ;
120             }
121              
122              
123             sub _is_packet_available {
124 27     27   32 my $this = shift ;
125              
126 27         90 my @ready = $this->{'select'}->can_read(0) ;
127              
128 27         625 return scalar(@ready) ;
129             }
130              
131              
132             # Returns a packet, 0 on real handle EOF or undef on error.
133             sub _read_packet {
134 49     49   54 my $this = shift ;
135 49         55 my $blocking = shift ;
136              
137 49 100       89 if (! $blocking){
138 27 100       56 return -1 unless $this->_is_packet_available() ;
139             }
140              
141 35         164 my $p = IO::Mux::Packet->read($this->_get_handle()) ;
142 34 50       104 if (! defined($p)){
    100          
143 0         0 return undef ;
144             }
145             elsif (! $p){
146 3         14 return 0 ;
147             }
148             else {
149             # Append the packet data to the correct buffer
150 31         81 my $buf = $this->_get_buffer($p->get_id()) ;
151 31         109 $buf->push_packet($p) ;
152              
153 31         105 return $p ;
154             }
155             }
156              
157              
158             sub _write {
159 43     43   61 my $this = shift ;
160 43         52 my $packet = shift ;
161              
162 43         82 return $packet->write($this->_get_handle()) ;
163             }
164              
165              
166              
167             1 ;
168             __END__