… | |
… | |
4 | |
4 | |
5 | =encoding utf-8 |
5 | =encoding utf-8 |
6 | |
6 | |
7 | =head1 SYNOPSIS |
7 | =head1 SYNOPSIS |
8 | |
8 | |
9 | use AnyEvent; |
9 | use AnyEvent; |
10 | use POE; |
10 | use POE; |
11 | |
11 | |
12 | # this module gets loaded automatically as required |
12 | # this module gets loaded automatically as required |
13 | |
13 | |
14 | =head1 DESCRIPTION |
14 | =head1 DESCRIPTION |
15 | |
15 | |
16 | This module provides transparent support for AnyEvent. You don't have to |
16 | This module provides transparent support for AnyEvent. You don't have to |
17 | do anything to make POE work with AnyEvent except by loading POE before |
17 | do anything to make POE work with AnyEvent except by loading POE before |
18 | creating the first AnyEvent watcher. |
18 | creating the first AnyEvent watcher. There are some cases where POE will |
|
|
19 | issue spurious (and non-suppressable) warnings. These can be avoided by |
|
|
20 | loading AnyEvent::Impl::POE before loading any other modules using POE and |
|
|
21 | AnyEvent, i.e. in your main program. |
|
|
22 | |
|
|
23 | AnyEvent::Impl::POE will output some spurious message how to work around |
|
|
24 | POE's spurious messages when it detects these cases. |
19 | |
25 | |
20 | Unfortunately, POE isn't generic enough to implement a fully working |
26 | Unfortunately, POE isn't generic enough to implement a fully working |
21 | AnyEvent backend: POE is too badly designed, too badly documented and too |
27 | AnyEvent backend: POE is too badly designed, too badly documented and too |
22 | badly implemented. |
28 | badly implemented. |
23 | |
29 | |
… | |
… | |
47 | change this. |
53 | change this. |
48 | |
54 | |
49 | This means that you will either have to live with lost events or you have |
55 | This means that you will either have to live with lost events or you have |
50 | to make sure to load AnyEvent early enough (this is usually not that |
56 | to make sure to load AnyEvent early enough (this is usually not that |
51 | difficult in a main program, but hard in a module). |
57 | difficult in a main program, but hard in a module). |
|
|
58 | |
|
|
59 | POE has other weird messages, and sometimes weird behaviour, for example, |
|
|
60 | it doesn't support overloaded code references as callbacks for no apparent |
|
|
61 | reason. |
52 | |
62 | |
53 | =item One POE session per Event |
63 | =item One POE session per Event |
54 | |
64 | |
55 | AnyEvent has to create one POE::Session per event watcher, which is |
65 | AnyEvent has to create one POE::Session per event watcher, which is |
56 | immensely slow and makes watchers very large. The reason for this is |
66 | immensely slow and makes watchers very large. The reason for this is |
… | |
… | |
218 | |
228 | |
219 | Sometimes registering a handler uses the "eventname, parameter" ordering |
229 | Sometimes registering a handler uses the "eventname, parameter" ordering |
220 | (timeouts), sometimes it is "parameter, eventname" (signals). There is |
230 | (timeouts), sometimes it is "parameter, eventname" (signals). There is |
221 | little consistency overall. |
231 | little consistency overall. |
222 | |
232 | |
|
|
233 | =item Lack of knowledge |
|
|
234 | |
|
|
235 | The IO::Poll event loop provides an alternative that theoretically |
|
|
236 | scales better than select(). |
|
|
237 | |
|
|
238 | The IO::Poll "event loop" (who in his right mind would call that an event |
|
|
239 | loop) of course scales about identically (sometimes it is a bit faster, |
|
|
240 | sometimes a bit slower) to select in theory, and also in practise, of |
|
|
241 | course, as both are O(n) in the number of file descriptors, which is |
|
|
242 | rather bad. |
|
|
243 | |
|
|
244 | This is just one place where it gets obvious how little the author of the |
|
|
245 | POE manpage understands. |
|
|
246 | |
|
|
247 | =item No idle events |
|
|
248 | |
|
|
249 | The POE-recommended workaround to this is apparently to use |
|
|
250 | C<fork>. Consequently, idle watchera will have to be emulated by AnyEvent. |
|
|
251 | |
223 | =back |
252 | =back |
224 | |
253 | |
225 | On the good side, AnyEvent allows you to write your modules in a 100% |
254 | On the good side, AnyEvent allows you to write your modules in a 100% |
226 | POE-compatible way (bug-for-bug compatible even), without forcing your |
255 | POE-compatible way (bug-for-bug compatible even), without forcing your |
227 | module to use POE - it is still open to better event models, of which |
256 | module to use POE - it is still open to better event models, of which |
… | |
… | |
232 | package AnyEvent::Impl::POE; |
261 | package AnyEvent::Impl::POE; |
233 | |
262 | |
234 | no warnings; |
263 | no warnings; |
235 | use strict; |
264 | use strict; |
236 | |
265 | |
|
|
266 | use AnyEvent (); |
237 | use POE; |
267 | use POE; |
238 | |
268 | |
239 | # have to do this to keep POE from spilling ugly messages |
269 | # if POE is already running |
|
|
270 | if (${ $poe_kernel->[POE::Kernel::KR_RUN] } && POE::Kernel::KR_RUN_CALLED) { |
|
|
271 | print STDERR <<EOF; |
|
|
272 | POE is going to complain about |
|
|
273 | Sessions were started, but POE::Kernel's run() method was never... |
|
|
274 | Try putting: |
|
|
275 | use AnyEvent::Impl::POE; |
|
|
276 | at the very top of your main program to suppress these spurious warnings. |
|
|
277 | EOF |
|
|
278 | } else { |
|
|
279 | # workaround to suppress noise |
240 | POE::Session->create (inline_states => { _start => sub { @_[KERNEL]->stop } }); |
280 | POE::Session->create (inline_states => { _start => sub { @_[KERNEL]->stop } }); |
241 | POE::Kernel->run; |
281 | POE::Kernel->run; |
|
|
282 | } |
242 | |
283 | |
243 | sub io { |
284 | sub io { |
244 | my ($class, %arg) = @_; |
285 | my ($class, %arg) = @_; |
245 | my $poll = delete $arg{poll}; |
|
|
246 | my $cb = delete $arg{cb}; |
|
|
247 | |
286 | |
248 | # cygwin requires the fh mode to be matching, unix doesn't |
287 | # cygwin requires the fh mode to be matching, unix doesn't |
249 | my ($pee, $mode) = $poll eq "r" ? ("select_read" , "<") |
288 | my ($fh, $pee) = AnyEvent::_dupfh $arg{poll}, $arg{fh}, "select_read", "select_write"; |
250 | : $poll eq "w" ? ("select_write", ">") |
|
|
251 | : Carp::croak "AnyEvent->io requires poll set to either 'r' or 'w'"; |
|
|
252 | |
289 | |
253 | open my $fh, "$mode&" . fileno $arg{fh} |
290 | my $cb = $arg{cb}; |
254 | or die "cannot dup() filehandle: $!"; |
|
|
255 | |
291 | |
256 | my $session = POE::Session->create ( |
292 | my $session = POE::Session->create ( |
257 | inline_states => { |
293 | inline_states => { |
258 | _start => sub { |
294 | _start => sub { |
259 | $_[KERNEL]->$pee ($fh => "ready"); |
295 | $_[KERNEL]->$pee ($fh => "ready"); |
… | |
… | |
264 | stop => sub { |
300 | stop => sub { |
265 | $_[KERNEL]->$pee ($fh); |
301 | $_[KERNEL]->$pee ($fh); |
266 | }, |
302 | }, |
267 | }, |
303 | }, |
268 | ); |
304 | ); |
269 | bless \\$session, AnyEvent::Impl::POE:: |
305 | bless \\$session, "AnyEvent::Impl::POE" |
270 | } |
306 | } |
271 | |
307 | |
272 | sub timer { |
308 | sub timer { |
273 | my ($class, %arg) = @_; |
309 | my ($class, %arg) = @_; |
|
|
310 | |
274 | my $after = delete $arg{after}; |
311 | my $after = $arg{after}; |
|
|
312 | my $ival = $arg{interval}; |
275 | my $cb = delete $arg{cb}; |
313 | my $cb = $arg{cb}; |
|
|
314 | |
276 | my $session = POE::Session->create ( |
315 | my $session = POE::Session->create ( |
277 | inline_states => { |
316 | inline_states => { |
278 | _start => sub { |
317 | _start => sub { |
279 | $_[KERNEL]->delay_set (timeout => $after); |
318 | $_[KERNEL]->delay_set (timeout => $after); |
280 | }, |
319 | }, |
281 | timeout => sub { |
320 | timeout => $ival ? sub { $_[KERNEL]->delay_set (timeout => $ival); $cb->() } : $cb, |
282 | $cb->(); |
|
|
283 | }, |
|
|
284 | stop => sub { |
321 | stop => sub { |
285 | $_[KERNEL]->alarm_remove_all; |
322 | $_[KERNEL]->alarm_remove_all; |
286 | }, |
323 | }, |
287 | }, |
324 | }, |
288 | ); |
325 | ); |
289 | bless \\$session, AnyEvent::Impl::POE:: |
326 | bless \\$session, "AnyEvent::Impl::POE" |
290 | } |
327 | } |
291 | |
328 | |
292 | sub signal { |
329 | sub signal { |
293 | my ($class, %arg) = @_; |
330 | my ($class, %arg) = @_; |
294 | my $signal = delete $arg{signal}; |
331 | my $signal = delete $arg{signal}; |
… | |
… | |
307 | $_[KERNEL]->refcount_decrement ($_[SESSION]->ID => "poe"); |
344 | $_[KERNEL]->refcount_decrement ($_[SESSION]->ID => "poe"); |
308 | $_[KERNEL]->sig ($signal); |
345 | $_[KERNEL]->sig ($signal); |
309 | }, |
346 | }, |
310 | }, |
347 | }, |
311 | ); |
348 | ); |
312 | bless \\$session, AnyEvent::Impl::POE:: |
349 | bless \\$session, "AnyEvent::Impl::POE" |
313 | } |
350 | } |
314 | |
351 | |
315 | sub child { |
352 | sub child { |
316 | my ($class, %arg) = @_; |
353 | my ($class, %arg) = @_; |
317 | my $pid = delete $arg{pid}; |
354 | my $pid = delete $arg{pid}; |
… | |
… | |
331 | $_[KERNEL]->refcount_decrement ($_[SESSION]->ID => "poe"); |
368 | $_[KERNEL]->refcount_decrement ($_[SESSION]->ID => "poe"); |
332 | $_[KERNEL]->sig ("CHLD"); |
369 | $_[KERNEL]->sig ("CHLD"); |
333 | }, |
370 | }, |
334 | }, |
371 | }, |
335 | ); |
372 | ); |
336 | bless \\$session, AnyEvent::Impl::POE:: |
373 | bless \\$session, "AnyEvent::Impl::POE" |
337 | } |
374 | } |
338 | |
375 | |
339 | sub DESTROY { |
376 | sub DESTROY { |
340 | POE::Kernel->post (${${$_[0]}}, "stop"); |
377 | POE::Kernel->post (${${$_[0]}}, "stop"); |
341 | } |
378 | } |