What does perl select do?

Perl select lets you read from a whole bunch of files at once. You couldn't normally do this easily, because you might try to read from a file that didn't have any data available. For example, you might be trying to read from sort but since it hasn't finished sorting yet, it hasn't generated any output! Or, you might be waiting for something to arrive over the network? select allows your program to get on with something else in the meantime.

Where else can I learn about perl?

If you want a more thorough treatment of perl, you should look to this book. It's written by Larry Wall, who wrote perl, so you it's the book you want!

Can you give me an example perl's select function?

select is usually used in network applications. That's what all the examples do, anyway. But it doesn't have to be that way- you might want to read in from things which aren't network sockets. So there are two examples here- a file-ish one, and a network one.

The File-ish looking example

This example isn't very practical; instead, I want to show you the idea easily without complicating it. Cut, paste and modify! ;)
 

# Define a new readset 
# Think of this as the object which keeps track of which file's 
# the system is to consider. 
my $readset   = new IO::Select(); 

# Open a pipe from cat and sort.   Not a particularly practical example, 
# but gives the general idea.   All you need are programs which 
# will generate something on standard out. 
# Think, for example of some kind of terminal program that generates
# data intermittently.  I've used cat and sort here because it's easy to 
# imagine them generating data. 
# You might give them arguments so that they actually have 
# something to read ;) 

my $catpid = open($catHandle, "cat |"); 
my $sortpid = open($sortHandle, "sort |"); 

# Add the handles for our programs into the readset. 
# In other words, we're keeping track of these handles. 
$readset->add($catHandle, $sortHandle); 


# Okay, this is where the magic happens. 
# The can_read function is going to give us an 
# array of filehandles which have data waiting. 
# This is the magic! We  only  read 
# from files which have data waiting! 

while(my @ready = $sel->can_read)
{ 

        foreach my $handle (@ready) { 

        if ($_ =  $catHandle ) 
               { 
                # It came from cat. 

               } 
        else if ($_ = $sortHandle) 
               { 
                # It came from sort. 

                } 
 
        # Actually read the data that came in. 
        my $numBytesRead = sysread($rh,  $inStr, 1024);
  
      # Has one of the handles reached end-of-file?  
        $readset->remove($rh) if eof($rh); 

   } 

Network-ish looking example

TBC. In the meantime, check out a page like this one which gives a nice, classic example of using select for a socket.

Contribution

John Martin wrote in with the following working example.
 

#!/usr/bin/perl -w
#-*- perl -*-


use strict;
use IO::Select;
use IO::File;

# Think of this as the object which keeps track of which file's 
# the system is to consider. 
my $readset   = new IO::Select(); 



my $fifo1="/tmp/testfifo1"; # create from shell with "mkfifo /tmp/testfifo1"
if (!(-p $fifo1 && -w _ && -r _))
{
print STDERR "Bad fifo $fifo1!\n";
exit(1);
}
my $fifo2="/tmp/testfifo2"; # create from shell with "mkfifo /tmp/testfifo2"
if (!(-p $fifo1 && -w _ && -r _))
{
print STDERR "Bad fifo $fifo2!\n";
exit(1);
}


my $fifo1Handle = new IO::File( $fifo1,  O_RDWR|O_NONBLOCK );
my $fifo2Handle = new IO::File( $fifo2,  O_RDWR|O_NONBLOCK );;

#open( fifo1Handle, "+<$fifo1"); 
#open( fifo2Handle, "+<$fifo2"); 


# Add the handles for our programs into the readset. 
# In other words, we're keeping track of these handles. 
$readset->add($fifo1Handle);
$readset->add($fifo2Handle);


# Okay, this is where the magic happens. 
# The can_read function is going to give us an 
# array of filehandles which have data waiting. 
# This is the magic! We  only  read 
# from files which have data waiting! 


while(my @ready = $readset->can_read(15))
{ 
    foreach my $handle (@ready) 
    { 
	

        if ($handle ==  $fifo1Handle ) 
	{ 

	    print "It came from fifo1\n";
	    
	    
	} 
        elsif ($handle == $fifo2Handle) 
	{ 

	    print "It came from fifo2\n";
	    
	} 
	
        # Actually read the data that came in. 
	print Read( $handle ) , "\n";
	
	
	
    } 

}

$fifo1Handle->close();
$fifo2Handle ->close();
print "Timed out.\n";


sub Read {
    my ($handle, $bytesToRead ) = @_;
    
    $bytesToRead = 1 unless $bytesToRead;

    my $message = '';
    my $readByte;
    
    while(1) {
	my $bytesRead = sysread( $handle, $readByte, $bytesToRead ) or 
	    last;
	
	$message .= $readByte if $bytesRead;
    }
    
    chomp $message if $message;
    return $message;
}


__END__