7.13. Reading from Many Filehandles Without BlockingProblemYou want to learn whether input is available to be read, rather than blocking for input as < > does. This is useful when reading from pipes, sockets, devices, and other programs. SolutionUse $rin = '';
# repeat next line for all filehandles to poll
vec($rin, fileno(FH1), 1) = 1;
vec($rin, fileno(FH2), 1) = 1;
vec($rin, fileno(FH3), 1) = 1;
$nfound = select($rout=$rin, undef, undef, 0);
if ($nfound) {
# input waiting on one or more of those 3 filehandles
if (vec($rout,fileno(FH1),1)) {
# do something with FH1
}
if (vec($rout,fileno(FH2),1)) {
# do something with FH2
}
if (vec($rout,fileno(FH3),1)) {
# do something with FH3
}
}The IO::Select module provides an abstraction to hide the bit-vector operations: use IO::Select;
$select = IO::Select->new();
# repeat next line for all filehandles to poll
$select->add(*FILEHANDLE);
if (@ready = $select->can_read(0)) {
# input waiting on the filehandles in @ready
}DiscussionThe The first three arguments to $rin = '';
vec($rin, fileno(FILEHANDLE), 1) = 1;
$nfound = select($rin, undef, undef, 0); # just check
if ($nfound) {
$line = <FILEHANDLE>;
print "I read $line";
}This code isn't perfect, though. If someone connects and sends a character but never sends a newline, your program will block in the The IO::Select module hides the bit-vectors from you. Don't mix calls to four-argument If you want to read whatever is available on a socket or pipe and return immediately, see Recipe 7.14. If you're trying to do non-blocking reads on a terminal, see Recipes Recipe 15.6 and Recipe 15.8. See AlsoThe |