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.1 by root, Wed Apr 27 01:26:44 2005 UTC vs.
Revision 1.7 by root, Fri Dec 30 01:28:31 2005 UTC

1=head1 NAME 1=head1 NAME
2 2
3AnyEvent - ??? 3AnyEvent - provide framework for multiple event loops
4
5Event, Coro, Glib, Tk - various supported event loops
4 6
5=head1 SYNOPSIS 7=head1 SYNOPSIS
6 8
9 use AnyEvent;
10
11 my $w = AnyEvent->io (fh => ..., poll => "[rw]+", cb => sub {
12 my ($poll_got) = @_;
13 ...
14 });
15
16* only one io watcher per $fh and $poll type is allowed (i.e. on a socket
17you can have one r + one w or one rw watcher, not any more (limitation by
18Tk).
19
20* the C<$poll_got> passed to the handler needs to be checked by looking
21for single characters (e.g. with a regex), as it can contain more event
22types than were requested (e.g. a 'w' watcher might generate 'rw' events,
23limitation by Glib).
24
25* AnyEvent will keep filehandles alive, so as long as the watcher exists,
26the filehandle exists.
27
28 my $w = AnyEvent->timer (after => $seconds, cb => sub {
29 ...
30 });
31
32* io and time watchers get canceled whenever $w is destroyed, so keep a copy
33
34* timers can only be used once and must be recreated for repeated
35operation (limitation by Glib and Tk).
36
37 my $w = AnyEvent->condvar; # kind of main loop replacement
38 $w->wait; # enters main loop till $condvar gets ->broadcast
39 $w->broadcast; # wake up current and all future wait's
40
41* condvars are used to give blocking behaviour when neccessary. Create
42a condvar for any "request" or "event" your module might create, C<<
43->broadcast >> it when the event happens and provide a function that calls
44C<< ->wait >> for it. See the examples below.
45
7=head1 DESCRIPTION 46=head1 DESCRIPTION
8 47
48L<AnyEvent> provides an identical interface to multiple event loops. This
49allows module authors to utilizy an event loop without forcing module
50users to use the same event loop (as only a single event loop can coexist
51peacefully at any one time).
52
53The interface itself is vaguely similar but not identical to the Event
54module.
55
56On the first call of any method, the module tries to detect the currently
57loaded event loop by probing wether any of the following modules is
58loaded: L<Coro::Event>, L<Event>, L<Glib>, L<Tk>. The first one found is
59used. If none is found, the module tries to load these modules in the
60order given. The first one that could be successfully loaded will be
61used. If still none could be found, it will issue an error.
62
9=over 4 63=over 4
10 64
11=cut 65=cut
12 66
13package AnyEvent; 67package AnyEvent;
14 68
69no warnings;
70use strict 'vars';
15use Carp; 71use Carp;
16 72
17$VERSION = 0.1; 73our $VERSION = '0.4';
74our $MODEL;
18 75
19no warnings; 76our $AUTOLOAD;
77our @ISA;
78
79our $verbose = $ENV{PERL_ANYEVENT_VERBOSE}*1;
20 80
21my @models = ( 81my @models = (
22 [Coro => Coro::Event::], 82 [Coro => Coro::Event::],
23 [Event => Event::], 83 [Event => Event::],
24 [Glib => Glib::], 84 [Glib => Glib::],
25 [Tk => Tk::], 85 [Tk => Tk::],
26); 86);
27 87
88our %method = map +($_ => 1), qw(io timer condvar broadcast wait cancel DESTROY);
89
28sub AUTOLOAD { 90sub AUTOLOAD {
29 $AUTOLOAD =~ s/.*://; 91 $AUTOLOAD =~ s/.*://;
30 92
93 $method{$AUTOLOAD}
94 or croak "$AUTOLOAD: not a valid method for AnyEvent objects";
95
96 unless ($MODEL) {
97 # check for already loaded models
31 for (@models) { 98 for (@models) {
32 my ($model, $package) = @$_; 99 my ($model, $package) = @$_;
33 if (defined ${"$package\::VERSION"}) { 100 if (${"$package\::VERSION"} > 0) {
34 $EVENT = "AnyEvent::Impl::$model"; 101 eval "require AnyEvent::Impl::$model";
35 eval "require $EVENT"; die if $@; 102 warn "AnyEvent: found model '$model', using it.\n" if $MODEL && $verbose > 1;
36 goto &{"$EVENT\::$AUTOLOAD"}; 103 last if $MODEL;
104 }
105 }
106
107 unless ($MODEL) {
108 # try to load a model
109
110 for (@models) {
111 my ($model, $package) = @$_;
112 eval "require AnyEvent::Impl::$model";
113 warn "AnyEvent: autprobed and loaded model '$model', using it.\n" if $MODEL && $verbose > 1;
114 last if $MODEL;
115 }
116
117 $MODEL
118 or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: Coro, Event, Glib or Tk.";
37 } 119 }
38 } 120 }
39 121
40 for (@models) { 122 @ISA = $MODEL;
41 my ($model, $package) = @$_; 123
42 $EVENT = "AnyEvent::Impl::$model"; 124 my $class = shift;
43 if (eval "require $EVENT") { 125 $class->$AUTOLOAD (@_);
44 goto &{"$EVENT\::$AUTOLOAD"}; 126}
127
128=back
129
130=head1 ENVIRONMENT VARIABLES
131
132The following environment variables are used by this module:
133
134C<PERL_ANYEVENT_VERBOSE> when set to C<2> or higher, reports which event
135model gets used.
136
137=head1 EXAMPLE
138
139The following program uses an io watcher to read data from stdin, a timer
140to display a message once per second, and a condvar to exit the program
141when the user enters quit:
142
143 use AnyEvent;
144
145 my $cv = AnyEvent->condvar;
146
147 my $io_watcher = AnyEvent->io (fh => \*STDIN, poll => 'r', cb => sub {
148 warn "io event <$_[0]>\n"; # will always output <r>
149 chomp (my $input = <STDIN>); # read a line
150 warn "read: $input\n"; # output what has been read
151 $cv->broadcast if $input =~ /^q/i; # quit program if /^q/i
152 });
153
154 my $time_watcher; # can only be used once
155
156 sub new_timer {
157 $timer = AnyEvent->timer (after => 1, cb => sub {
158 warn "timeout\n"; # print 'timeout' about every second
159 &new_timer; # and restart the time
45 } 160 });
46 } 161 }
47 162
48 die "No event module selected for AnyEvent and autodetect failed. Install any of these: Coro, Event, Glib or Tk."; 163 new_timer; # create first timer
49}
50 164
511; 165 $cv->wait; # wait until user enters /^q/i
52 166
167=head1 REAL-WORLD EXAMPLE
168
169Consider the L<Net::FCP> module. It features (among others) the following
170API calls, which are to freenet what HTTP GET requests are to http:
171
172 my $data = $fcp->client_get ($url); # blocks
173
174 my $transaction = $fcp->txn_client_get ($url); # does not block
175 $transaction->cb ( sub { ... } ); # set optional result callback
176 my $data = $transaction->result; # possibly blocks
177
178The C<client_get> method works like C<LWP::Simple::get>: it requests the
179given URL and waits till the data has arrived. It is defined to be:
180
181 sub client_get { $_[0]->txn_client_get ($_[1])->result }
182
183And in fact is automatically generated. This is the blocking API of
184L<Net::FCP>, and it works as simple as in any other, similar, module.
185
186More complicated is C<txn_client_get>: It only creates a transaction
187(completion, result, ...) object and initiates the transaction.
188
189 my $txn = bless { }, Net::FCP::Txn::;
190
191It also creates a condition variable that is used to signal the completion
192of the request:
193
194 $txn->{finished} = AnyAvent->condvar;
195
196It then creates a socket in non-blocking mode.
197
198 socket $txn->{fh}, ...;
199 fcntl $txn->{fh}, F_SETFL, O_NONBLOCK;
200 connect $txn->{fh}, ...
201 and !$!{EWOULDBLOCK}
202 and !$!{EINPROGRESS}
203 and Carp::croak "unable to connect: $!\n";
204
205Then it creates a write-watcher which gets called whenever an error occurs
206or the connection succeeds:
207
208 $txn->{w} = AnyEvent->io (fh => $txn->{fh}, poll => 'w', cb => sub { $txn->fh_ready_w });
209
210And returns this transaction object. The C<fh_ready_w> callback gets
211called as soon as the event loop detects that the socket is ready for
212writing.
213
214The C<fh_ready_w> method makes the socket blocking again, writes the
215request data and replaces the watcher by a read watcher (waiting for reply
216data). The actual code is more complicated, but that doesn't matter for
217this example:
218
219 fcntl $txn->{fh}, F_SETFL, 0;
220 syswrite $txn->{fh}, $txn->{request}
221 or die "connection or write error";
222 $txn->{w} = AnyEvent->io (fh => $txn->{fh}, poll => 'r', cb => sub { $txn->fh_ready_r });
223
224Again, C<fh_ready_r> waits till all data has arrived, and then stores the
225result and signals any possible waiters that the request ahs finished:
226
227 sysread $txn->{fh}, $txn->{buf}, length $txn->{$buf};
228
229 if (end-of-file or data complete) {
230 $txn->{result} = $txn->{buf};
231 $txn->{finished}->broadcast;
232 $txb->{cb}->($txn) of $txn->{cb}; # also call callback
233 }
234
235The C<result> method, finally, just waits for the finished signal (if the
236request was already finished, it doesn't wait, of course, and returns the
237data:
238
239 $txn->{finished}->wait;
240 return $txn->{result};
241
242The actual code goes further and collects all errors (C<die>s, exceptions)
243that occured during request processing. The C<result> method detects
244wether an exception as thrown (it is stored inside the $txn object)
245and just throws the exception, which means connection errors and other
246problems get reported tot he code that tries to use the result, not in a
247random callback.
248
249All of this enables the following usage styles:
250
2511. Blocking:
252
253 my $data = $fcp->client_get ($url);
254
2552. Blocking, but parallelizing:
256
257 my @datas = map $_->result,
258 map $fcp->txn_client_get ($_),
259 @urls;
260
261Both blocking examples work without the module user having to know
262anything about events.
263
2643a. Event-based in a main program, using any support Event module:
265
266 use Event;
267
268 $fcp->txn_client_get ($url)->cb (sub {
269 my $txn = shift;
270 my $data = $txn->result;
271 ...
272 });
273
274 Event::loop;
275
2763b. The module user could use AnyEvent, too:
277
278 use AnyEvent;
279
280 my $quit = AnyEvent->condvar;
281
282 $fcp->txn_client_get ($url)->cb (sub {
283 ...
284 $quit->broadcast;
285 });
286
287 $quit->wait;
288
289=head1 SEE ALSO
290
291Event modules: L<Coro::Event>, L<Coro>, L<Event>, L<Glib::Event>, L<Glib>.
292
293Implementations: L<AnyEvent::Impl::Coro>, L<AnyEvent::Impl::Event>, L<AnyEvent::Impl::Glib>, L<AnyEvent::Impl::Tk>.
294
295Nontrivial usage example: L<Net::FCP>.
296
297=head1
298
299=cut
300
3011
302

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines