1 | =head1 NAME |
1 | =head1 NAME |
2 | |
2 | |
3 | Coro::AIO - truely asynchronous file access |
3 | Coro::AIO - truly asynchronous file and directrory I/O |
4 | |
4 | |
5 | =head1 SYNOPSIS |
5 | =head1 SYNOPSIS |
6 | |
6 | |
7 | use Coro::AIO; |
7 | use Coro::AIO; |
8 | |
8 | |
9 | # can now use any of: |
9 | # can now use any of |
10 | # aio_sendfile aio_read aio_write aio_open aio_close |
10 | # aio_sendfile aio_read aio_write aio_open aio_close aio_stat aio_lstat |
11 | # aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink aio_fsync |
11 | # aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink aio_fsync |
12 | # aio_fdatasync aio_readahead |
12 | # aio_fdatasync aio_readahead |
13 | |
13 | |
14 | # read 1MB of /etc/passwd, without blocking other coroutines |
14 | # read 1MB of /etc/passwd, without blocking other coroutines |
15 | my $fh = aio_open "/etc/passwd", O_RDONLY, 0 |
15 | my $fh = aio_open "/etc/passwd", O_RDONLY, 0 |
… | |
… | |
19 | aio_close $fh; |
19 | aio_close $fh; |
20 | |
20 | |
21 | =head1 DESCRIPTION |
21 | =head1 DESCRIPTION |
22 | |
22 | |
23 | This module implements a thin wrapper around L<IO::AIO|IO::AIO>. All of |
23 | This module implements a thin wrapper around L<IO::AIO|IO::AIO>. All of |
24 | the functions (except C<aio_lstat> and C<aio_stat>) that expect a callback |
24 | the functions that expect a callback are being wrapped by this module. |
25 | are being wrapped by this module. |
|
|
26 | |
25 | |
27 | The API is exactly the same as that of the corresponding IO::AIO routines, |
26 | The API is exactly the same as that of the corresponding IO::AIO routines, |
28 | except that you have to specify I<all> arguments I<except> the callback |
27 | except that you have to specify I<all> arguments I<except> the callback |
29 | argument. Instead the routines return the values normally passed to the |
28 | argument. Instead the routines return the values normally passed to the |
30 | callback. They also all have a prototype of C<@> currently, but that might |
29 | callback. They also all have a prototype of C<@> currently, but that might |
31 | change. |
30 | change. Everything else, including C<$!> and perls stat cache, are set as |
|
|
31 | expected after these functions return. |
32 | |
32 | |
33 | You can mix calls to C<IO::AIO> functions with calls to this module. You |
33 | You can mix calls to C<IO::AIO> functions with calls to this module. You |
34 | also can, but do not need to, call C<IO::AIO::poll_cb>, as this module |
34 | also can, but do not need to, call C<IO::AIO::poll_cb>, as this module |
35 | automatically installs an event watcher for the C<IO::AIO> file |
35 | automatically installs an event watcher for the C<IO::AIO> file |
36 | descriptor. It uses the L<AnyEvent|AnyEvent> module for this, so please |
36 | descriptor. It uses the L<AnyEvent|AnyEvent> module for this, so please |
… | |
… | |
44 | |
44 | |
45 | =cut |
45 | =cut |
46 | |
46 | |
47 | package Coro::AIO; |
47 | package Coro::AIO; |
48 | |
48 | |
|
|
49 | use strict; |
|
|
50 | |
49 | use Coro (); |
51 | use Coro (); |
50 | use AnyEvent; |
52 | use AnyEvent; |
51 | use IO::AIO (); |
53 | use IO::AIO (); |
52 | |
54 | |
53 | use base Exporter::; |
55 | use base Exporter::; |
… | |
… | |
57 | |
59 | |
58 | our @EXPORT; |
60 | our @EXPORT; |
59 | |
61 | |
60 | sub wrap($) { |
62 | sub wrap($) { |
61 | my ($sub) = @_; |
63 | my ($sub) = @_; |
|
|
64 | |
|
|
65 | no strict 'refs'; |
62 | |
66 | |
63 | push @EXPORT, $sub; |
67 | push @EXPORT, $sub; |
64 | |
68 | |
65 | my $iosub = "IO::AIO::$sub"; |
69 | my $iosub = "IO::AIO::$sub"; |
66 | |
70 | |
67 | *$sub = sub { |
71 | *$sub = sub { |
68 | my $current = $Coro::current; |
72 | my $current = $Coro::current; |
69 | my $errno; |
73 | my $stat; |
70 | my @res; |
74 | my @res; |
71 | |
75 | |
72 | $iosub->(@_, sub { |
76 | $iosub->(@_, sub { |
73 | $errno = $!; |
77 | $stat = Coro::_aio_get_state; |
74 | @res = @_; |
78 | @res = @_; |
75 | $current->ready; |
79 | $current->ready; |
76 | undef $current; |
80 | undef $current; |
77 | }); |
81 | }); |
78 | |
82 | |
79 | Coro::schedule while $current; |
83 | Coro::schedule while $current; |
80 | |
84 | |
81 | $! = $errno; |
85 | Coro::_aio_set_state $stat; |
82 | wantarray ? @res : $res[0] |
86 | wantarray ? @res : $res[0] |
83 | }; |
87 | }; |
84 | } |
88 | } |
85 | |
89 | |
86 | wrap $_ for qw(aio_sendfile aio_read aio_write aio_open aio_close |
90 | wrap $_ for qw(aio_sendfile aio_read aio_write aio_open aio_close aio_stat |
87 | aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink |
91 | aio_lstat aio_unlink aio_rmdir aio_readdir aio_scandir |
88 | aio_fsync aio_fdatasync aio_readahead); |
92 | aio_symlink aio_fsync aio_fdatasync aio_readahead); |
89 | |
93 | |
90 | =item $fh = aio_open $pathname, $flags, $mode |
94 | =item $fh = aio_open $pathname, $flags, $mode |
91 | |
95 | |
92 | =item $status = aio_close $fh |
96 | =item $status = aio_close $fh |
93 | |
97 | |
… | |
… | |
96 | =item $retval = aio_write $fh,$offset,$length, $data,$dataoffset |
100 | =item $retval = aio_write $fh,$offset,$length, $data,$dataoffset |
97 | |
101 | |
98 | =item $retval = aio_sendfile $out_fh, $in_fh, $in_offset, $length |
102 | =item $retval = aio_sendfile $out_fh, $in_fh, $in_offset, $length |
99 | |
103 | |
100 | =item $retval = aio_readahead $fh,$offset,$length |
104 | =item $retval = aio_readahead $fh,$offset,$length |
|
|
105 | |
|
|
106 | =item $status = aio_stat $fh_or_path |
|
|
107 | |
|
|
108 | =item $status = aio_lstat $fh |
101 | |
109 | |
102 | =item $status = aio_unlink $pathname |
110 | =item $status = aio_unlink $pathname |
103 | |
111 | |
104 | =item $status = aio_rmdir $pathname |
112 | =item $status = aio_rmdir $pathname |
105 | |
113 | |
… | |
… | |
111 | |
119 | |
112 | =item $status = aio_fdatasync $fh |
120 | =item $status = aio_fdatasync $fh |
113 | |
121 | |
114 | =back |
122 | =back |
115 | |
123 | |
|
|
124 | =head1 SEE ALSO |
|
|
125 | |
|
|
126 | L<Coro::Socket> and L<Coro::Handle> for non-blocking file operation. |
|
|
127 | |
116 | =head1 AUTHOR |
128 | =head1 AUTHOR |
117 | |
129 | |
118 | Marc Lehmann <schmorp@schmorp.de> |
130 | Marc Lehmann <schmorp@schmorp.de> |
119 | http://home.schmorp.de/ |
131 | http://home.schmorp.de/ |
120 | |
132 | |