--- IO-AIO/AIO.pm 2006/10/22 21:13:47 1.62 +++ IO-AIO/AIO.pm 2006/10/24 11:57:30 1.71 @@ -20,6 +20,7 @@ # version 2+ has request and group objects use IO::AIO 2; + aioreq_pri 4; # give next request a very high priority my $req = aio_unlink "/tmp/file", sub { }; $req->cancel; # cancel request if still in queue @@ -53,18 +54,18 @@ operating system supports. Currently, a number of threads are started that execute your read/writes -and signal their completion. You don't need thread support in your libc or -perl, and the threads created by this module will not be visible to the -pthreads library. In the future, this module might make use of the native -aio functions available on many operating systems. However, they are often -not well-supported (Linux doesn't allow them on normal files currently, -for example), and they would only support aio_read and aio_write, so the -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, always call -C from within the same thread, or never call C (or other -C functions) recursively. +and signal their completion. You don't need thread support in perl, and +the threads created by this module will not be visible to perl. In the +future, this module might make use of the native aio functions available +on many operating systems. However, they are often not well-supported +(Linux doesn't allow them on normal files currently, for example), +and they would only support aio_read and aio_write, so the 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 in any way, so use appropriate locking +yourself, always call C from within the same thread, or never +call C (or other C functions) recursively. =cut @@ -78,11 +79,13 @@ BEGIN { our $VERSION = '2.0'; - our @EXPORT = qw(aio_sendfile aio_read aio_write aio_open aio_close aio_stat - aio_lstat aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink - aio_fsync aio_fdatasync aio_readahead aio_rename aio_link aio_move - aio_group); - our @EXPORT_OK = qw(poll_fileno poll_cb min_parallel max_parallel max_outstanding nreqs); + our @AIO_REQ = qw(aio_sendfile aio_read aio_write aio_open aio_close aio_stat + aio_lstat aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink + aio_fsync aio_fdatasync aio_readahead aio_rename aio_link aio_move + aio_group aio_nop); + our @EXPORT = (@AIO_REQ, qw(aioreq_pri aioreq_nice)); + our @EXPORT_OK = qw(poll_fileno poll_cb poll_wait flush + min_parallel max_parallel max_outstanding nreqs); @IO::AIO::GRP::ISA = 'IO::AIO::REQ'; @@ -123,6 +126,34 @@ =over 4 +=item aioreq_pri $pri + +Sets the priority for the next aio request. The default priority +is C<0>, the minimum and maximum priorities are C<-4> and C<4>, +respectively. Requests with higher priority will be serviced first. + +The priority will be reset to C<0> after each call to one of the C +functions. + +Example: open a file with low priority, then read something from it with +higher priority so the read request is serviced before other low priority +open requests (potentially spamming the cache): + + aioreq_pri -3; + aio_open ..., sub { + return unless $_[0]; + + aioreq_pri -2; + aio_read $_[0], ..., sub { + ... + }; + }; + +=item aioreq_nice $pri_adjust + +Similar to C, but subtracts the given value from the current +priority, so effects are cumulative. + =item aio_open $pathname, $flags, $mode, $callback->($fh) Asynchronously open or create a file and call the callback with a newly @@ -184,8 +215,6 @@ =item aio_move $srcpath, $dstpath, $callback->($status) -[EXPERIMENTAL due to internal aio_group use] - Try to move the I (directories not supported as either source or destination) from C<$srcpath> to C<$dstpath> and call the callback with the C<0> (error) or C<-1> ok. @@ -347,8 +376,6 @@ =item aio_scandir $path, $maxreq, $callback->($dirs, $nondirs) -[EXPERIMENTAL due to internal aio_group use] - Scans a directory (similar to C) but additionally tries to separate the entries of directory C<$path> into two sets of names, ones you can recurse into (directories or links to them), and ones you cannot @@ -519,7 +546,8 @@ This is a very special aio request: Instead of doing something, it is a container for other aio requests, which is useful if you want to bundle -many requests into a single, composite, request. +many requests into a single, composite, request with a definite callback +and the ability to cancel the whole request with its subrequests. Returns an object of class L. See its documentation below for more info. @@ -535,15 +563,28 @@ (aio_stat ...), ...; -=item IO::AIO::aio_sleep $fractional_seconds, $callback->() *NOT EXPORTED* +=item aio_nop $callback->() + +This is a special request - it does nothing in itself and is only used for +side effects, such as when you want to add a dummy request to a group so +that finishing the requests in the group depends on executing the given +code. + +While this request does nothing, it still goes through the execution +phase and still requires a worker thread. Thus, the callback will not +be executed immediately but only after other requests in the queue have +entered their execution phase. This can be used to measure request +latency. + +=item IO::AIO::aio_busy $fractional_seconds, $callback->() *NOT EXPORTED* Mainly used for debugging and benchmarking, this aio request puts one of the request workers to sleep for the given time. While it is theoretically handy to have simple I/O scheduling requests -like sleep and file handle readable/writable, the overhead this creates -is immense, so do not use this function except to put your application -under artificial I/O pressure. +like sleep and file handle readable/writable, the overhead this creates is +immense (it blocks a thread for a long time) so do not use this function +except to put your application under artificial I/O pressure. =back @@ -562,7 +603,7 @@ =over 4 -=item $req->cancel +=item cancel $req Cancels the request, if possible. Has the effect of skipping execution when entering the B state and skipping calling the callback when @@ -570,6 +611,10 @@ untouched. That means that requests that currently execute will not be stopped and resources held by the request will not be freed prematurely. +=item cb $req $callback->(...) + +Replace (or simply set) the callback registered to the request. + =back =head2 IO::AIO::GRP CLASS @@ -636,10 +681,10 @@ =over 4 -=item $grp->add (...) - =item add $grp ... +=item $grp->add (...) + Add one or more requests to the group. Any type of L can be added, including other groups, as long as you do not create circular dependencies. @@ -651,7 +696,7 @@ Set the result value(s) that will be passed to the group callback when all subrequests have finished. By default, no argument will be passed. -=item $grp->set_feeder ($callback->($grp)) +=item feed $grp $callback->($grp) [VERY EXPERIMENTAL] @@ -664,32 +709,32 @@ To avoid this, and allow incremental generation of requests, you can instead a group and set a feeder on it that generates those requests. The -feeder will be called whenever there are few enough (see C, +feed callback will be called whenever there are few enough (see C, below) requests active in the group itself and is expected to queue more requests. -The feeder can queue as many requests as it likes (i.e. C does not -impose any limits). +The feed callback can queue as many requests as it likes (i.e. C does +not impose any limits). -If the feeder does not queue more requests when called, it will be +If the feed does not queue more requests when called, it will be automatically removed from the group. -If the feeder limit is C<0>, it will be set to C<2> automatically. +If the feed limit is C<0>, it will be set to C<2> automatically. Example: # stat all files in @files, but only ever use four aio requests concurrently: my $grp = aio_group sub { print "finished\n" }; - $grp->feeder_limit (4); - $grp->set_feeder (sub { + limit $grp 4; + feed $grp sub { my $file = pop @files or return; add $grp aio_stat $file, sub { ... }; - }); + }; -=item $grp->feeder_limit ($num) +=item limit $grp $num Sets the feeder limit for the group: The feeder will be called whenever the group contains less than this many requests. @@ -869,7 +914,7 @@ =head1 SEE ALSO -L, L (obsolete). +L. =head1 AUTHOR