AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/IO.pm view on Meta::CPAN
use AnyEvent::IO;
# load /etc/passwd, call callback with the file data when done.
aio_load "/etc/passwd", sub {
my ($data) = @_
or return AE::log error => "/etc/passwd: $!";
warn "/etc/passwd contains ", ($data =~ y/://) , " colons.\n";
};
# the rest of the SYNOPSIS does the same, but with individual I/O calls
# also import O_XXX flags
use AnyEvent::IO qw(:DEFAULT :flags);
my $filedata = AE::cv;
# first open the file
aio_open "/etc/passwd", O_RDONLY, 0, sub {
my ($fh) = @_
or return AE::log error => "/etc/passwd: $!";
# now stat the file to get the size
aio_stat $fh, sub {
@_
or return AE::log error => "/etc/passwd: $!";
my $size = -s _;
# now read all the file data
aio_read $fh, $size, sub {
my ($data) = @_
or return AE::log error => "/etc/passwd: $!";
$size == length $data
or return AE::log error => "/etc/passwd: short read, file changed?";
# mostly the same as aio_load, above - $data contains
# the file contents now.
$filedata->($data);
};
};
};
my $passwd = $filedata->recv;
warn length $passwd, " octets.\n";
=head1 DESCRIPTION
This module provides functions that do I/O in an asynchronous fashion. It
is to I/O the same as L<AnyEvent> is to event libraries - it only
I<interfaces> to other implementations or to a portable pure-perl
implementation (which does not, however, do asynchronous I/O).
The only other implementation that is supported (or even known to the
author) is L<IO::AIO>, which is used automatically when it can be loaded
(via L<AnyEvent::AIO>, which also needs to be installed). If it is not
available, then L<AnyEvent::IO> falls back to its synchronous pure-perl
implementation.
Unlike L<AnyEvent>, which model to use is currently decided at module load
time, not at first use. Future releases might change this.
=head2 RATIONALE
While disk I/O often seems "instant" compared to, say, socket I/O, there
are many situations where your program can block for extended time periods
when doing disk I/O. For example, you access a disk on an NFS server and
it is gone - can take ages to respond again, if ever. Or your system is
extremely busy because it creates or restores a backup - reading data from
disk can then take seconds. Or you use Linux, which for so many years has
a close-to-broken VM/IO subsystem that can often induce minutes or more of
delay for disk I/O, even under what I would consider light I/O loads.
Whatever the situation, some programs just can't afford to block for long
times (say, half a second or more), because they need to respond as fast
as possible.
For those cases, you need asynchronous I/O.
The problem is, AnyEvent itself sometimes reads disk files (for example,
when looking at F</etc/hosts>), and under the above situations, this can
bring your program to a complete halt even if your program otherwise
takes care to only use asynchronous I/O for everything (e.g. by using
L<IO::AIO>).
On the other hand, requiring L<IO::AIO> for AnyEvent is clearly
impossible, as AnyEvent promises to stay pure-perl, and the overhead of
IO::AIO for small programs would be immense, especially when asynchronous
I/O isn't even needed.
Clearly, this calls for an abstraction layer, and that is what you are
looking at right now :-)
=head2 ASYNCHRONOUS VS. NON-BLOCKING
Many people are continuously confused on what the difference is between
asynchronous I/O and non-blocking I/O. In fact, those two terms are
not well defined, which often makes it hard to even talk about the
difference. Here is a short guideline that should leave you less
confused. It only talks about read operations, but the reasoning works
with other I/O operations as well.
Non-blocking I/O means that data is delivered by some external means,
automatically - that is, something I<pushes> data towards your file
handle, without you having to do anything. Non-blocking means that if
your operating system currently has no data (or EOF, or some error)
available for you, it will not wait ("block") as it would normally do,
but immediately return with an error (e.g. C<EWOULDBLOCK> - "I would have
blocked, but you forbid it").
Your program can then wait for data to arrive by other means, for example,
an I/O watcher which tells you when to re-attempt the read, after which it
can try to read again, and so on.
Often, you would expect this to work for disk files as well - if the data
isn't already in memory, one might want to wait for it and then re-attempt
the read for example. While this is sound reasoning, the POSIX API does
not support this, because disk drives and file systems do not send data
"on their own", and more so, the OS already knows that data is there, it
doesn't need to "wait" until it arrives from some external entity, it only
( run in 0.558 second using v1.01-cache-2.11-cpan-39bf76dae61 )