--- IO-AIO/AIO.pm 2005/07/10 22:19:48 1.6 +++ IO-AIO/AIO.pm 2005/08/23 00:03:14 1.36 @@ -14,22 +14,27 @@ aio_unlink "/tmp/file", sub { }; aio_read $fh, 30000, 1024, $buffer, 0, sub { - $_[0] >= 0 or die "read error: $!"; + $_[0] > 0 or die "read error: $!"; }; # Event Event->io (fd => IO::AIO::poll_fileno, - poll => 'r', async => 1, + poll => 'r', cb => \&IO::AIO::poll_cb); # Glib/Gtk2 add_watch Glib::IO IO::AIO::poll_fileno, - \&IO::AIO::poll_cb; + in => sub { IO::AIO::poll_cb; 1 }; # Tk Tk::Event::IO->fileevent (IO::AIO::poll_fileno, "", readable => \&IO::AIO::poll_cb); + # Danga::Socket + Danga::Socket->AddOtherFds (IO::AIO::poll_fileno => + \&IO::AIO::poll_cb); + + =head1 DESCRIPTION This module implements asynchronous I/O using whatever means your @@ -45,21 +50,25 @@ remaining functionality would have to be implemented using threads anyway. Although the module will work with in the presence of other threads, it is -currently not reentrant, so use appropriate locking yourself. +currently not reentrant, so use appropriate locking yourself, always call +C from within the same thread, or never call C (or other +C functions) recursively. =cut package IO::AIO; +no warnings; + use base 'Exporter'; use Fcntl (); BEGIN { - $VERSION = 0.2; + $VERSION = 1.6; @EXPORT = qw(aio_read aio_write aio_open aio_close aio_stat aio_lstat aio_unlink - aio_fsync aio_fdatasync aio_readahead); + aio_rmdir aio_symlink aio_fsync aio_fdatasync aio_readahead); @EXPORT_OK = qw(poll_fileno poll_cb min_parallel max_parallel max_outstanding nreqs); require XSLoader; @@ -72,18 +81,27 @@ All the C calls are more or less thin wrappers around the syscall with the same name (sans C). The arguments are similar or identical, -and they all accept an additional C<$callback> argument which must be -a code reference. This code reference will get called with the syscall -return code (e.g. most syscalls return C<-1> on error, unlike perl, which -usually delivers "false") as it's sole argument when the given syscall has -been executed asynchronously. - -All functions that expect a filehandle will also accept a file descriptor. - -The filenames you pass to these routines I be absolute. The reason -is that at the time the request is being executed, the current working -directory could have changed. Alternatively, you can make sure that you -never change the current working directory. +and they all accept an additional (and optional) C<$callback> argument +which must be a code reference. This code reference will get called with +the syscall return code (e.g. most syscalls return C<-1> on error, unlike +perl, which usually delivers "false") as it's sole argument when the given +syscall has been executed asynchronously. + +All functions expecting a filehandle keep a copy of the filehandle +internally until the request has finished. + +The pathnames you pass to these routines I be absolute and +encoded in byte form. The reason for the former is that at the time the +request is being executed, the current working directory could have +changed. Alternatively, you can make sure that you never change the +current working directory. + +To encode pathnames to byte form, either make sure you either: a) +always pass in filenames you got from outside (command line, readdir +etc.), b) are ASCII or ISO 8859-1, c) use the Encode module and encode +your pathnames to the locale (or other) encoding in effect in the user +environment, d) use Glib::filename_from_unicode on unicode filenames or e) +use something else. =over 4 @@ -95,8 +113,13 @@ The pathname passed to C must be absolute. See API NOTES, above, for an explanation. -The C<$mode> argument is a bitmask. See the C module for a -list. They are the same as used in C. +The C<$flags> argument is a bitmask. See the C module for a +list. They are the same as used by C. + +Likewise, C<$mode> specifies the mode of the newly created file, if it +didn't exist and C has been given, just like perl's C, +except that it is mandatory (i.e. use C<0> if you don't create new files, +and C<0666> or C<0777> if you do). Example: @@ -113,9 +136,12 @@ Asynchronously close a file and call the callback with the result code. I although accepted, you should not pass in a perl -filehandle here, as perl will likely close the file descriptor itself when -the filehandle is destroyed. Normally, you can safely call perls C -or just let filehandles go out of scope. +filehandle here, as perl will likely close the file descriptor another +time when the filehandle is destroyed. Normally, you can safely call perls +C or just let filehandles go out of scope. + +This is supposed to be a bug in the API, so that might change. It's +therefore best to avoid this function. =item aio_read $fh,$offset,$length, $data,$dataoffset,$callback @@ -126,29 +152,55 @@ callback without the actual number of bytes read (or -1 on error, just like the syscall). -Example: Read 15 bytes at offset 7 into scalar C<$buffer>, strating at +The C<$data> scalar I be modified in any way while the request +is outstanding. Modifying it can result in segfaults or WW3 (if the +necessary/optional hardware is installed). + +Example: Read 15 bytes at offset 7 into scalar C<$buffer>, starting at offset C<0> within the scalar: aio_read $fh, 7, 15, $buffer, 0, sub { - $_[0] >= 0 or die "read error: $!"; - print "read <$buffer>\n"; + $_[0] > 0 or die "read error: $!"; + print "read $_[0] bytes: <$buffer>\n"; }; -=item aio_readahead $fh,$offset,$length, $callback +=item aio_sendfile $out_fh, $in_fh, $in_offset, $length, $callback -Asynchronously reads the specified byte range into the page cache, using -the C syscall. If that syscall doesn't exist the status will be -C<-1> and C<$!> is set to ENOSYS. +Tries to copy C<$length> bytes from C<$in_fh> to C<$out_fh>. It starts +reading at byte offset C<$in_offset>, and starts writing at the current +file offset of C<$out_fh>. Because of that, it is not safe to issue more +than one C per C<$out_fh>, as they will interfere with each +other. + +This call tries to make use of a native C syscall to provide +zero-copy operation. For this to work, C<$out_fh> should refer to a +socket, and C<$in_fh> should refer to mmap'able file. + +If the native sendfile call fails or is not implemented, it will be +emulated, so you can call C on any type of filehandle +regardless of the limitations of the operating system. + +Please note, however, that C can read more bytes from +C<$in_fh> than are written, and there is no way to find out how many +bytes have been read from C alone, as C only +provides the number of bytes written to C<$out_fh>. Only if the result +value equals C<$length> one can assume that C<$length> bytes have been +read. -readahead() populates the page cache with data from a file so that +=item aio_readahead $fh,$offset,$length, $callback + +C populates the page cache with data from a file so that subsequent reads from that file will not block on disk I/O. The C<$offset> argument specifies the starting point from which data is to be read and C<$length> specifies the number of bytes to be read. I/O is performed in whole pages, so that offset is effectively rounded down to a page boundary and bytes are read up to the next page boundary greater than or equal to -(off-set+length). aio_readahead() does not read beyond the end of the +(off-set+length). C does not read beyond the end of the file. The current file offset of the file is left unchanged. +If that syscall doesn't exist (likely if your OS isn't Linux) it will be +emulated by simply reading the data, which would have a similar effect. + =item aio_stat $fh_or_path, $callback =item aio_lstat $fh, $callback @@ -176,6 +228,11 @@ Asynchronously unlink (delete) a file and call the callback with the result code. +=item aio_rmdir $pathname, $callback + +Asynchronously rmdir (delete) a directory and call the callback with the +result code. + =item aio_fsync $fh, $callback Asynchronously call fsync on the given filehandle and call the callback @@ -186,6 +243,9 @@ Asynchronously call fdatasync on the given filehandle and call the callback with the fdatasync result code. +If this call isn't available because your OS lacks it or it couldn't be +detected, it will be emulated by calling C instead. + =back =head2 SUPPORT FUNCTIONS @@ -194,10 +254,10 @@ =item $fileno = IO::AIO::poll_fileno -Return the I. This filehandle must be -polled for reading by some mechanism outside this module (e.g. Event -or select, see below). If the pipe becomes readable you have to call -C to check the results. +Return the I. This filehandle must be +polled for reading by some mechanism outside this module (e.g. Event or +select, see below or the SYNOPSIS). If the pipe becomes readable you have +to call C to check the results. See C for an example. @@ -207,7 +267,8 @@ regularly. Returns the number of events processed. Returns immediately when no events are outstanding. -You can use Event to multiplex, e.g.: +Example: Install an Event watcher that automatically calls +IO::AIO::poll_cb with high priority: Event->io (fd => IO::AIO::poll_fileno, poll => 'r', async => 1, @@ -216,40 +277,64 @@ =item IO::AIO::poll_wait Wait till the result filehandle becomes ready for reading (simply does a -select on the filehandle. This is useful if you want to synchronously wait +C