… | |
… | |
7 | use IO::AIO; |
7 | use IO::AIO; |
8 | |
8 | |
9 | =head1 DESCRIPTION |
9 | =head1 DESCRIPTION |
10 | |
10 | |
11 | This module implements asynchronous I/O using whatever means your |
11 | This module implements asynchronous I/O using whatever means your |
12 | operating system supports. Currently, it falls back to Linux::AIO if that |
12 | operating system supports. |
13 | module is available, or uses pthreads to emulato aio functionality. |
|
|
14 | |
13 | |
15 | Currently, in this module a number of threads are started that execute |
14 | Currently, a number of threads are started that execute your read/writes |
16 | your read/writes and signal their completion. You don't need thread |
15 | and signal their completion. You don't need thread support in your libc or |
17 | support in your libc or perl, and the threads created by this module will |
16 | perl, and the threads created by this module will not be visible to the |
18 | not be visible to the pthreads library. |
17 | pthreads library. In the future, this module might make use of the native |
|
|
18 | aio functions available on many operating systems. However, they are often |
|
|
19 | not well-supported (Linux doesn't allow them on normal files currently, |
|
|
20 | for example), and they would only support aio_read and aio_write, so the |
|
|
21 | remaining functionality would have to be implemented using threads anyway. |
19 | |
22 | |
20 | Although the module will work with in the presence of other threads, it is |
23 | Although the module will work with in the presence of other threads, it is |
21 | not reentrant, so use appropriate locking yourself. |
24 | currently not reentrant, so use appropriate locking yourself. |
22 | |
25 | |
23 | =head2 API NOTES |
26 | =head2 API NOTES |
24 | |
27 | |
25 | All the C<aio_*> calls are more or less thin wrappers around the syscall |
28 | All the C<aio_*> calls are more or less thin wrappers around the syscall |
26 | with the same name (sans C<aio_>). The arguments are similar or identical, |
29 | with the same name (sans C<aio_>). The arguments are similar or identical, |
… | |
… | |
43 | |
46 | |
44 | package IO::AIO; |
47 | package IO::AIO; |
45 | |
48 | |
46 | use base 'Exporter'; |
49 | use base 'Exporter'; |
47 | |
50 | |
|
|
51 | use Fcntl (); |
|
|
52 | |
48 | BEGIN { |
53 | BEGIN { |
49 | $VERSION = 0.1; |
54 | $VERSION = 0.2; |
50 | |
55 | |
51 | @EXPORT = qw(aio_read aio_write aio_open aio_close aio_stat aio_lstat aio_unlink |
56 | @EXPORT = qw(aio_read aio_write aio_open aio_close aio_stat aio_lstat aio_unlink |
52 | aio_fsync aio_fdatasync aio_readahead); |
57 | aio_fsync aio_fdatasync aio_readahead); |
53 | @EXPORT_OK = qw(poll_fileno poll_cb min_parallel max_parallel nreqs); |
58 | @EXPORT_OK = qw(poll_fileno poll_cb min_parallel max_parallel nreqs); |
54 | |
59 | |
… | |
… | |
118 | IO::AIO::poll_wait, IO::AIO::poll_cb |
123 | IO::AIO::poll_wait, IO::AIO::poll_cb |
119 | while IO::AIO::nreqs; |
124 | while IO::AIO::nreqs; |
120 | |
125 | |
121 | =item aio_open $pathname, $flags, $mode, $callback |
126 | =item aio_open $pathname, $flags, $mode, $callback |
122 | |
127 | |
123 | Asynchronously open or create a file and call the callback with the |
128 | Asynchronously open or create a file and call the callback with a newly |
124 | filedescriptor (NOT a perl filehandle, sorry for that, but watch out, this |
129 | created filehandle for the file. |
125 | might change in the future). |
|
|
126 | |
130 | |
127 | The pathname passed to C<aio_open> must be absolute. See API NOTES, above, |
131 | The pathname passed to C<aio_open> must be absolute. See API NOTES, above, |
128 | for an explanation. |
132 | for an explanation. |
129 | |
133 | |
130 | The C<$mode> argument is a bitmask. See the C<Fcntl> module for a |
134 | The C<$mode> argument is a bitmask. See the C<Fcntl> module for a |
131 | list. They are the same as used in C<sysopen>. |
135 | list. They are the same as used in C<sysopen>. |
132 | |
136 | |
133 | Example: |
137 | Example: |
134 | |
138 | |
135 | aio_open "/etc/passwd", O_RDONLY, 0, sub { |
139 | aio_open "/etc/passwd", O_RDONLY, 0, sub { |
136 | if ($_[0] >= 0) { |
140 | if ($_[0]) { |
137 | open my $fh, "<&$_[0]"; # create a copy for perl |
|
|
138 | aio_close $_[0], sub { }; # close the aio handle |
|
|
139 | print "open successful, fh is $fh\n"; |
141 | print "open successful, fh is $_[0]\n"; |
140 | ... |
142 | ... |
141 | } else { |
143 | } else { |
142 | die "open failed: $!\n"; |
144 | die "open failed: $!\n"; |
143 | } |
145 | } |
144 | }; |
146 | }; |
145 | |
147 | |
146 | =item aio_close $fh, $callback |
148 | =item aio_close $fh, $callback |
147 | |
149 | |
148 | Asynchronously close a file and call the callback with the result code. |
150 | Asynchronously close a file and call the callback with the result |
|
|
151 | code. I<WARNING:> although accepted, you should not pass in a perl |
|
|
152 | filehandle here, as perl will likely close the file descriptor itself when |
|
|
153 | the filehandle is destroyed. Normally, you can safely call perls C<close> |
|
|
154 | or just let filehandles go out of scope. |
149 | |
155 | |
150 | =item aio_read $fh,$offset,$length, $data,$dataoffset,$callback |
156 | =item aio_read $fh,$offset,$length, $data,$dataoffset,$callback |
151 | |
157 | |
152 | =item aio_write $fh,$offset,$length, $data,$dataoffset,$callback |
158 | =item aio_write $fh,$offset,$length, $data,$dataoffset,$callback |
153 | |
159 | |
… | |
… | |
216 | Asynchronously call fdatasync on the given filehandle and call the |
222 | Asynchronously call fdatasync on the given filehandle and call the |
217 | callback with the fdatasync result code. |
223 | callback with the fdatasync result code. |
218 | |
224 | |
219 | =cut |
225 | =cut |
220 | |
226 | |
|
|
227 | # support function to convert a fd into a perl filehandle |
|
|
228 | sub _fd2fh { |
|
|
229 | return undef if $_[0] < 0; |
|
|
230 | |
|
|
231 | # try to be perl5.6-compatible |
|
|
232 | local *AIO_FH; |
|
|
233 | open AIO_FH, "+<&=$_[0]" |
|
|
234 | or return undef; |
|
|
235 | |
|
|
236 | *AIO_FH |
|
|
237 | } |
|
|
238 | |
221 | min_parallel 4; |
239 | min_parallel 4; |
222 | |
240 | |
223 | END { |
241 | END { |
224 | max_parallel 0; |
242 | max_parallel 0; |
225 | } |
243 | } |
… | |
… | |
228 | |
246 | |
229 | =back |
247 | =back |
230 | |
248 | |
231 | =head1 BUGS |
249 | =head1 BUGS |
232 | |
250 | |
233 | - aio_open gives a fd, but all other functions expect a perl filehandle. |
251 | - could be optimized to use more semaphores instead of filehandles. |
234 | |
252 | |
235 | =head1 SEE ALSO |
253 | =head1 SEE ALSO |
236 | |
254 | |
237 | L<Coro>, L<Linux::AIO>. |
255 | L<Coro>, L<Linux::AIO>. |
238 | |
256 | |