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.6 by root, Mon Dec 19 17:03:29 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 whenever 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 $txb->{cb}->($txn) of $txn->{cb}; # also call callback
216 }
217
218The C<result> method, finally, just waits for the finished signal (if the
219request was already finished, it doesn't wait, of course, and returns the
220data:
221
222 $txn->{finished}->wait;
223 return $txn->{result};
224
225The actual code goes further and collects all errors (C<die>s, exceptions)
226that occured during request processing. The C<result> method detects
227wether an exception as thrown (it is stored inside the $txn object)
228and just throws the exception, which means connection errors and other
229problems get reported tot he code that tries to use the result, not in a
230random callback.
231
232All of this enables the following usage styles:
233
2341. Blocking:
235
236 my $data = $fcp->client_get ($url);
237
2382. Blocking, but parallelizing:
239
240 my @datas = map $_->result,
241 map $fcp->txn_client_get ($_),
242 @urls;
243
244Both blocking examples work without the module user having to know
245anything about events.
246
2473a. Event-based in a main program, using any support Event module:
248
249 use Event;
250
251 $fcp->txn_client_get ($url)->cb (sub {
252 my $txn = shift;
253 my $data = $txn->result;
254 ...
255 });
256
257 Event::loop;
258
2593b. The module user could use AnyEvent, too:
260
261 use AnyEvent;
262
263 my $quit = AnyEvent->condvar;
264
265 $fcp->txn_client_get ($url)->cb (sub {
266 ...
267 $quit->broadcast;
268 });
269
270 $quit->wait;
271
140=head1 SEE ALSO 272=head1 SEE ALSO
141 273
142L<Coro::Event>, L<Coro>, L<Event>, L<Glib::Event>, L<Glib>, 274Event modules: L<Coro::Event>, L<Coro>, L<Event>, L<Glib::Event>, L<Glib>.
143L<AnyEvent::Impl::Coro>, 275
144L<AnyEvent::Impl::Event>, 276Implementations: L<AnyEvent::Impl::Coro>, L<AnyEvent::Impl::Event>, L<AnyEvent::Impl::Glib>, L<AnyEvent::Impl::Tk>.
145L<AnyEvent::Impl::Glib>, 277
146L<AnyEvent::Impl::Tk>. 278Nontrivial usage example: L<Net::FCP>.
147 279
148=head1 280=head1
149 281
150=cut 282=cut
151 283

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines