Reading from Many Filehandles Without Blocking
Problem
You 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.
Solution
Use select
with a timeout value of
seconds, if you’re comfortable with manipulating bit-vectors
representing file descriptor sets:
$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 }
Discussion
The select
function is really two functions in
one. If you call it with one argument, you change the current default
output filehandle (see Section 7.12). If you call it
with four arguments, it tells you which filehandles have input
waiting or are ready to receive output. This recipe only deals with
four-argument select
.
The first three arguments to select
are strings containing bit-vectors. Each ...
Get Perl Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.