ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent.pm
Revision: 1.7
Committed: Fri Dec 30 01:28:31 2005 UTC (18 years, 6 months ago) by root
Branch: MAIN
CVS Tags: rel-0_4
Changes since 1.6: +27 -10 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 AnyEvent - provide framework for multiple event loops
4
5 Event, Coro, Glib, Tk - various supported event loops
6
7 =head1 SYNOPSIS
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
17 you can have one r + one w or one rw watcher, not any more (limitation by
18 Tk).
19
20 * the C<$poll_got> passed to the handler needs to be checked by looking
21 for single characters (e.g. with a regex), as it can contain more event
22 types than were requested (e.g. a 'w' watcher might generate 'rw' events,
23 limitation by Glib).
24
25 * AnyEvent will keep filehandles alive, so as long as the watcher exists,
26 the 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
35 operation (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
42 a condvar for any "request" or "event" your module might create, C<<
43 ->broadcast >> it when the event happens and provide a function that calls
44 C<< ->wait >> for it. See the examples below.
45
46 =head1 DESCRIPTION
47
48 L<AnyEvent> provides an identical interface to multiple event loops. This
49 allows module authors to utilizy an event loop without forcing module
50 users to use the same event loop (as only a single event loop can coexist
51 peacefully at any one time).
52
53 The interface itself is vaguely similar but not identical to the Event
54 module.
55
56 On the first call of any method, the module tries to detect the currently
57 loaded event loop by probing wether any of the following modules is
58 loaded: L<Coro::Event>, L<Event>, L<Glib>, L<Tk>. The first one found is
59 used. If none is found, the module tries to load these modules in the
60 order given. The first one that could be successfully loaded will be
61 used. If still none could be found, it will issue an error.
62
63 =over 4
64
65 =cut
66
67 package AnyEvent;
68
69 no warnings;
70 use strict 'vars';
71 use Carp;
72
73 our $VERSION = '0.4';
74 our $MODEL;
75
76 our $AUTOLOAD;
77 our @ISA;
78
79 our $verbose = $ENV{PERL_ANYEVENT_VERBOSE}*1;
80
81 my @models = (
82 [Coro => Coro::Event::],
83 [Event => Event::],
84 [Glib => Glib::],
85 [Tk => Tk::],
86 );
87
88 our %method = map +($_ => 1), qw(io timer condvar broadcast wait cancel DESTROY);
89
90 sub AUTOLOAD {
91 $AUTOLOAD =~ s/.*://;
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
98 for (@models) {
99 my ($model, $package) = @$_;
100 if (${"$package\::VERSION"} > 0) {
101 eval "require AnyEvent::Impl::$model";
102 warn "AnyEvent: found model '$model', using it.\n" if $MODEL && $verbose > 1;
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.";
119 }
120 }
121
122 @ISA = $MODEL;
123
124 my $class = shift;
125 $class->$AUTOLOAD (@_);
126 }
127
128 =back
129
130 =head1 ENVIRONMENT VARIABLES
131
132 The following environment variables are used by this module:
133
134 C<PERL_ANYEVENT_VERBOSE> when set to C<2> or higher, reports which event
135 model gets used.
136
137 =head1 EXAMPLE
138
139 The following program uses an io watcher to read data from stdin, a timer
140 to display a message once per second, and a condvar to exit the program
141 when 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
160 });
161 }
162
163 new_timer; # create first timer
164
165 $cv->wait; # wait until user enters /^q/i
166
167 =head1 REAL-WORLD EXAMPLE
168
169 Consider the L<Net::FCP> module. It features (among others) the following
170 API 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
178 The C<client_get> method works like C<LWP::Simple::get>: it requests the
179 given 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
183 And in fact is automatically generated. This is the blocking API of
184 L<Net::FCP>, and it works as simple as in any other, similar, module.
185
186 More 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
191 It also creates a condition variable that is used to signal the completion
192 of the request:
193
194 $txn->{finished} = AnyAvent->condvar;
195
196 It 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
205 Then it creates a write-watcher which gets called whenever an error occurs
206 or the connection succeeds:
207
208 $txn->{w} = AnyEvent->io (fh => $txn->{fh}, poll => 'w', cb => sub { $txn->fh_ready_w });
209
210 And returns this transaction object. The C<fh_ready_w> callback gets
211 called as soon as the event loop detects that the socket is ready for
212 writing.
213
214 The C<fh_ready_w> method makes the socket blocking again, writes the
215 request data and replaces the watcher by a read watcher (waiting for reply
216 data). The actual code is more complicated, but that doesn't matter for
217 this 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
224 Again, C<fh_ready_r> waits till all data has arrived, and then stores the
225 result 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
235 The C<result> method, finally, just waits for the finished signal (if the
236 request was already finished, it doesn't wait, of course, and returns the
237 data:
238
239 $txn->{finished}->wait;
240 return $txn->{result};
241
242 The actual code goes further and collects all errors (C<die>s, exceptions)
243 that occured during request processing. The C<result> method detects
244 wether an exception as thrown (it is stored inside the $txn object)
245 and just throws the exception, which means connection errors and other
246 problems get reported tot he code that tries to use the result, not in a
247 random callback.
248
249 All of this enables the following usage styles:
250
251 1. Blocking:
252
253 my $data = $fcp->client_get ($url);
254
255 2. Blocking, but parallelizing:
256
257 my @datas = map $_->result,
258 map $fcp->txn_client_get ($_),
259 @urls;
260
261 Both blocking examples work without the module user having to know
262 anything about events.
263
264 3a. 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
276 3b. 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
291 Event modules: L<Coro::Event>, L<Coro>, L<Event>, L<Glib::Event>, L<Glib>.
292
293 Implementations: L<AnyEvent::Impl::Coro>, L<AnyEvent::Impl::Event>, L<AnyEvent::Impl::Glib>, L<AnyEvent::Impl::Tk>.
294
295 Nontrivial usage example: L<Net::FCP>.
296
297 =head1
298
299 =cut
300
301 1
302