Reputation: 3172
I am learning about non blocking io in perl. I have the following script, where I am trying to write to a file in a non blocking fashion.
Is this the correct way to do it ? If not what is the correct way ? I am having trouble simulating a write that doesn't happen in an instant, so I can't really test it if it works or not.
use strict;
use warnings;
use POSIX qw(:errno_h);
open(my $fh, ">>", "b.txt") or die "$! \n";
my $buffer = "aaaaaaaaaaaaaaaaaaaaaaa\n";
my $rv = syswrite($fh, $buffer, length $buffer);
#start more non blocking operations
while(1)
{
if (!defined($rv) && $! == EAGAIN) {
print "Would block \n";
} elsif ($rv != length $buffer) {
print "Incomplete write \n";
} else {
print "Successfull write so we can do what we want with the read data\n";
}
#check the other operations
#sleep for a bit
sleep 1;
}
Upvotes: 1
Views: 1229
Reputation: 123320
First, non-blocking I/O works on sockets and pipes, but not on regular files. That is not a limit of Perl but of the underlying system. What you instead want for regular files would not be non-blocking but asynchronous I/O:
Unfortunately support for real asynchronous I/O is system specific and often not well supported so you would need to use threads here (again, that's not a problem of Perl but of the underlying system). You might want to take a look at IO::AIO which tries to give you the feeling of asynchronous I/O by using whatever the system supports. But note also that it is not very efficient and if you could use non-blocking sockets directly (i.e. with sockets but not with regular files) you should do it.
To use non-blocking you have to mark the file descriptor as non-blocking and then you read, write, connect, accept etc on it like you do normally, except that it will never block but return EAGAIN
/EWOULDBLOCK
if the operation can not be executed immediately. To wait until a file descriptor becomes readable/writable again you can use select
, poll
, kqueue
or similar mechanisms.
That's for a short introduction. Some things you have to watch out for:
IO::Socket->blocking
handles the major differences for you.EAGAIN
is the same as EWOULDBLOCK
but on Windows this is different and you have usually to use EWOULDBLOCK
. Upvotes: 4
Reputation: 53478
I'll go at a bit of a tangent - I'm not too familiar with doing nonblocking IO like that, because my approach tends to be to either thread
or fork
and do it that way.
Nonblocking writes to a file though, aren't all that common - it's usually not relevant when doing so with small files, so your test case probably isn't going to work. I'd suggest you aim for several megabytes of writes, just to be able to see it happen.
As for a threading approach - I tend to do it like this:
#!/usr/bin/perl
use strict;
use warnings;
use threads;
use Thread::Queue;
my $output_q = Thread::Queue->new();
sub writer {
open( my $output_fh, ">", "output_file.txt" ) or die $!;
while ( my $line = $output_q->dequeue ) {
print {$output_fh} $line;
}
close($output_fh) or die $!;
}
## main bit.
my $writer = threads->create( \&writer );
my $done = 0;
while ( not $done ) {
$output_q->enqueue( "a" x 1024 );
# do something else.
#repeat until $done
}
$output_q->end();
$writer->join();
Upvotes: 2