1 package TAP::Parser::Multiplexer;
8 use base 'TAP::Object';
10 use constant IS_WIN32 => $^O =~ /^(MS)?Win32$/;
11 use constant IS_VMS => $^O eq 'VMS';
12 use constant SELECT_OK => !( IS_VMS || IS_WIN32 );
16 TAP::Parser::Multiplexer - Multiplex multiple TAP::Parsers
24 our $VERSION = '3.42';
28 use TAP::Parser::Multiplexer;
30 my $mux = TAP::Parser::Multiplexer->new;
31 $mux->add( $parser1, $stash1 );
32 $mux->add( $parser2, $stash2 );
33 while ( my ( $parser, $stash, $result ) = $mux->next ) {
39 C<TAP::Parser::Multiplexer> gathers input from multiple TAP::Parsers.
40 Internally it calls select on the input file handles for those parsers
41 to wait for one or more of them to have input available.
43 See L<TAP::Harness> for an example of its use.
51 my $mux = TAP::Parser::Multiplexer->new;
53 Returns a new C<TAP::Parser::Multiplexer> object.
57 # new() implementation supplied by TAP::Object
61 $self->{select} = IO::Select->new;
62 $self->{avid} = []; # Parsers that can't select
67 ##############################################################################
69 =head2 Instance Methods
73 $mux->add( $parser, $stash );
75 Add a TAP::Parser to the multiplexer. C<$stash> is an optional opaque
76 reference that will be returned from C<next> along with the parser and
82 my ( $self, $parser, $stash ) = @_;
84 if ( SELECT_OK && ( my @handles = $parser->get_select_handles ) ) {
85 my $sel = $self->{select};
87 # We have to turn handles into file numbers here because by
88 # the time we want to remove them from our IO::Select they
89 # will already have been closed by the iterator.
90 my @filenos = map { fileno $_ } @handles;
91 for my $h (@handles) {
92 $sel->add( [ $h, $parser, $stash, @filenos ] );
98 push @{ $self->{avid} }, [ $parser, $stash ];
104 my $count = $mux->parsers;
106 Returns the number of parsers. Parsers are removed from the multiplexer
107 when their input is exhausted.
113 return $self->{count} + scalar @{ $self->{avid} };
119 my $sel = $self->{select};
120 my $avid = $self->{avid};
125 # Drain all the non-selectable parsers first
127 my ( $parser, $stash ) = @{ $avid->[0] };
128 my $result = $parser->next;
129 shift @$avid unless defined $result;
130 return ( $parser, $stash, $result );
134 return unless $sel->count;
135 @ready = $sel->can_read;
138 my ( $h, $parser, $stash, @handles ) = @{ shift @ready };
139 my $result = $parser->next;
141 unless ( defined $result ) {
142 $sel->remove(@handles);
145 # Force another can_read - we may now have removed a handle
146 # thought to have been ready.
150 return ( $parser, $stash, $result );
156 Return a result from the next available parser. Returns a list
157 containing the parser from which the result came, the stash that
158 corresponds with that parser and the result.
160 my ( $parser, $stash, $result ) = $mux->next;
162 If C<$result> is undefined the corresponding parser has reached the end
163 of its input (and will automatically be removed from the multiplexer).
165 When all parsers are exhausted an empty list will be returned.
167 if ( my ( $parser, $stash, $result ) = $mux->next ) {
168 if ( ! defined $result ) {
176 # All parsers finished
183 return ( $self->{_iter} ||= $self->_iter )->();