ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent.pm
(Generate patch)

Comparing AnyEvent/lib/AnyEvent.pm (file contents):
Revision 1.4 by root, Thu Dec 1 22:04:50 2005 UTC vs.
Revision 1.5 by root, Sun Dec 4 09:44:32 2005 UTC

6 6
7=head1 SYNOPSIS 7=head1 SYNOPSIS
8 8
9use AnyEvent; 9use AnyEvent;
10 10
11 my $w = AnyEvent->timer (fh => ..., poll => "[rw]+", cb => sub { 11 my $w = AnyEvent->io (fh => ..., poll => "[rw]+", cb => sub {
12 my ($poll_got) = @_; 12 my ($poll_got) = @_;
13 ... 13 ...
14 }); 14 });
15
16- only one io watcher per $fh and $poll type is allowed
17(i.e. on a socket you can have one r + one w or one rw
18watcher, not any more.
19
20- AnyEvent will keep filehandles alive, so as long as the watcher exists,
21the filehandle exists.
22
15 my $w = AnyEvent->io (after => $seconds, cb => sub { 23 my $w = AnyEvent->timer (after => $seconds, cb => sub {
16 ... 24 ...
17 }); 25 });
18 26
19 # watchers get canceled whenever $w is destroyed 27- io and time watchers get canceled whenever $w is destroyed, so keep a copy
20 # only one watcher per $fh and $poll type is allowed 28
21 # (i.e. on a socket you cna have one r + one w or one rw 29- timers can only be used once and must be recreated for repeated operation
22 # watcher, not any more.
23 # timers can only be used once
24 30
25 my $w = AnyEvent->condvar; # kind of main loop replacement 31 my $w = AnyEvent->condvar; # kind of main loop replacement
26 # can only be used once
27 $w->wait; # enters main loop till $condvar gets ->send 32 $w->wait; # enters main loop till $condvar gets ->broadcast
28 $w->broadcast; # wake up waiting and future wait's 33 $w->broadcast; # wake up current and all future wait's
34
35- condvars are used to give blocking behaviour when neccessary. Create
36a condvar for any "request" or "event" your module might create, C<<
37->broadcast >> it when the event happens and provide a function that calls
38C<< ->wait >> for it. See the examples below.
29 39
30=head1 DESCRIPTION 40=head1 DESCRIPTION
31 41
32L<AnyEvent> provides an identical interface to multiple event loops. This 42L<AnyEvent> provides an identical interface to multiple event loops. This
33allows module authors to utilizy an event loop without forcing module 43allows module authors to utilizy an event loop without forcing module
52 62
53no warnings; 63no warnings;
54use strict 'vars'; 64use strict 'vars';
55use Carp; 65use Carp;
56 66
57our $VERSION = 0.2; 67our $VERSION = 0.3;
58our $MODEL; 68our $MODEL;
59 69
60our $AUTOLOAD; 70our $AUTOLOAD;
61our @ISA; 71our @ISA;
62 72
135 145
136 new_timer; # create first timer 146 new_timer; # create first timer
137 147
138 $cv->wait; # wait until user enters /^q/i 148 $cv->wait; # wait until user enters /^q/i
139 149
150=head1 REAL-WORLD EXAMPLE
151
152Consider the L<Net::FCP> module. It features (among others) the following
153API calls, which are to freenet what HTTP GET requests are to http:
154
155 my $data = $fcp->client_get ($url); # blocks
156
157 my $transaction = $fcp->txn_client_get ($url); # does not block
158 $transaction->cb ( sub { ... } ); # set optional result callback
159 my $data = $transaction->result; # possibly blocks
160
161The C<client_get> method works like C<LWP::Simple::get>: it requests the
162given URL and waits till the data has arrived. It is defined to be:
163
164 sub client_get { $_[0]->txn_client_get ($_[1])->result }
165
166And in fact is automatically generated. This is the blocking API of
167L<Net::FCP>, and it works as simple as in any other, similar, module.
168
169More complicated is C<txn_client_get>: It only creates a transaction
170(completion, result, ...) object and initiates the transaction.
171
172 my $txn = bless { }, Net::FCP::Txn::;
173
174It also creates a condition variable that is used to signal the completion
175of the request:
176
177 $txn->{finished} = AnyAvent->condvar;
178
179It then creates a socket in non-blocking mode.
180
181 socket $txn->{fh}, ...;
182 fcntl $txn->{fh}, F_SETFL, O_NONBLOCK;
183 connect $txn->{fh}, ...
184 and !$!{EWOULDBLOCK}
185 and !$!{EINPROGRESS}
186 and Carp::croak "unable to connect: $!\n";
187
188Then it creates a write-watcher which gets called wehnever an error occurs
189or the connection succeeds:
190
191 $txn->{w} = AnyEvent->io (fh => $txn->{fh}, poll => 'w', cb => sub { $txn->fh_ready_w });
192
193And returns this transaction object. The C<fh_ready_w> callback gets
194called as soon as the event loop detects that the socket is ready for
195writing.
196
197The C<fh_ready_w> method makes the socket blocking again, writes the
198request data and replaces the watcher by a read watcher (waiting for reply
199data). The actual code is more complicated, but that doesn't matter for
200this example:
201
202 fcntl $txn->{fh}, F_SETFL, 0;
203 syswrite $txn->{fh}, $txn->{request}
204 or die "connection or write error";
205 $txn->{w} = AnyEvent->io (fh => $txn->{fh}, poll => 'r', cb => sub { $txn->fh_ready_r });
206
207Again, C<fh_ready_r> waits till all data has arrived, and then stores the
208result and signals any possible waiters that the request ahs finished:
209
210 sysread $txn->{fh}, $txn->{buf}, length $txn->{$buf};
211
212 if (end-of-file or data complete) {
213 $txn->{result} = $txn->{buf};
214 $txn->{finished}->broadcast;
215 }
216
217The C<result> method, finally, just waits for the finished signal (if the
218request was already finished, it doesn't wait, of course, and returns the
219data:
220
221 $txn->{finished}->wait;
222 return $txn->{buf};
223
224The actual code goes further and collects all errors (C<die>s, exceptions)
225that occured during request processing. The C<result> method detects
226wether an exception as thrown (it is stored inside the $txn object)
227and just throws the exception, which means connection errors and other
228problems get reported tot he code that tries to use the result, not in a
229random callback.
230
231All of this enables the following usage styles:
232
2331. Blocking:
234
235 my $data = $fcp->client_get ($url);
236
2372. Blocking, but parallelizing:
238
239 my @datas = map $_->result,
240 map $fcp->txn_client_get ($_),
241 @urls;
242
243Both blocking examples work without the module user having to know
244anything about events.
245
2463a. Event-based in a main program, using any support Event module:
247
248 use Event;
249
250 $fcp->txn_client_get ($url)->cb (sub {
251 my $txn = shift;
252 my $data = $txn->result;
253 ...
254 });
255
256 Event::loop;
257
2583b. The module user could use AnyEvent, too:
259
260 use AnyEvent;
261
262 my $quit = AnyEvent->condvar;
263
264 $fcp->txn_client_get ($url)->cb (sub {
265 ...
266 $quit->broadcast;
267 });
268
269 $quit->wait;
270
140=head1 SEE ALSO 271=head1 SEE ALSO
141 272
142L<Coro::Event>, L<Coro>, L<Event>, L<Glib::Event>, L<Glib>, 273Event modules: L<Coro::Event>, L<Coro>, L<Event>, L<Glib::Event>, L<Glib>.
143L<AnyEvent::Impl::Coro>, 274
144L<AnyEvent::Impl::Event>, 275Implementations: L<AnyEvent::Impl::Coro>, L<AnyEvent::Impl::Event>, L<AnyEvent::Impl::Glib>, L<AnyEvent::Impl::Tk>.
145L<AnyEvent::Impl::Glib>, 276
146L<AnyEvent::Impl::Tk>. 277Nontrivial usage example: L<Net::FCP>.
147 278
148=head1 279=head1
149 280
150=cut 281=cut
151 282

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines