1 package TAP::Parser::Multiplexer;
7 use constant IS_WIN32 => $^O =~ /^(MS)?Win32$/;
8 use constant IS_VMS => $^O eq 'VMS';
9 use constant SELECT_OK => !( IS_VMS || IS_WIN32 );
13 TAP::Parser::Multiplexer - Multiplex multiple TAP::Parsers
25 use TAP::Parser::Multiplexer;
27 my $mux = TAP::Parser::Multiplexer->new;
28 $mux->add( $parser1, $stash1 );
29 $mux->add( $parser2, $stash2 );
30 while ( my ( $parser, $stash, $result ) = $mux->next ) {
36 C<TAP::Parser::Multiplexer> gathers input from multiple TAP::Parsers.
37 Internally it calls select on the input file handles for those parsers
38 to wait for one or more of them to have input available.
40 See L<TAP::Harness> for an example of its use.
48 my $mux = TAP::Parser::Multiplexer->new;
50 Returns a new C<TAP::Parser::Multiplexer> object.
57 select => IO::Select->new,
58 avid => [], # Parsers that can't select
63 ##############################################################################
65 =head2 Instance Methods
69 $mux->add( $parser, $stash );
71 Add a TAP::Parser to the multiplexer. C<$stash> is an optional opaque
72 reference that will be returned from C<next> along with the parser and
78 my ( $self, $parser, $stash ) = @_;
80 if ( SELECT_OK && ( my @handles = $parser->get_select_handles ) ) {
81 my $sel = $self->{select};
83 # We have to turn handles into file numbers here because by
84 # the time we want to remove them from our IO::Select they
85 # will already have been closed by the iterator.
86 my @filenos = map { fileno $_ } @handles;
87 for my $h (@handles) {
88 $sel->add( [ $h, $parser, $stash, @filenos ] );
94 push @{ $self->{avid} }, [ $parser, $stash ];
100 my $count = $mux->parsers;
102 Returns the number of parsers. Parsers are removed from the multiplexer
103 when their input is exhausted.
109 return $self->{count} + scalar @{ $self->{avid} };
115 my $sel = $self->{select};
116 my $avid = $self->{avid};
121 # Drain all the non-selectable parsers first
123 my ( $parser, $stash ) = @{ $avid->[0] };
124 my $result = $parser->next;
125 shift @$avid unless defined $result;
126 return ( $parser, $stash, $result );
130 return unless $sel->count;
132 # TODO: Win32 doesn't do select properly on handles...
133 @ready = $sel->can_read;
136 my ( $h, $parser, $stash, @handles ) = @{ shift @ready };
137 my $result = $parser->next;
139 unless ( defined $result ) {
140 $sel->remove(@handles);
143 # Force another can_read - we may now have removed a handle
144 # thought to have been ready.
148 return ( $parser, $stash, $result );
154 Return a result from the next available parser. Returns a list
155 containing the parser from which the result came, the stash that
156 corresponds with that parser and the result.
158 my ( $parser, $stash, $result ) = $mux->next;
160 If C<$result> is undefined the corresponding parser has reached the end
161 of its input (and will automatically be removed from the multiplexer).
163 When all parsers are exhausted an empty list will be returned.
165 if ( my ( $parser, $stash, $result ) = $mux->next ) {
166 if ( ! defined $result ) {
174 # All parsers finished
181 return ( $self->{_iter} ||= $self->_iter )->();