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

Comparing AnyEvent/lib/AnyEvent/Impl/POE.pm (file contents):
Revision 1.16 by root, Thu May 1 10:51:27 2008 UTC vs.
Revision 1.23 by root, Thu Apr 23 22:44:30 2009 UTC

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
16This module provides transparent support for AnyEvent. You don't have to 16This module provides transparent support for AnyEvent. You don't have to
17do anything to make POE work with AnyEvent except by loading POE before 17do anything to make POE work with AnyEvent except by loading POE before
18creating the first AnyEvent watcher. 18creating the first AnyEvent watcher. There are some cases where POE will
19issue spurious (and non-suppressable) warnings. These can be avoided by
20loading AnyEvent::Impl::POE before loading any other modules using POE and
21AnyEvent, i.e. in your main program.
22
23AnyEvent::Impl::POE will output some spurious message how to work around
24POE's spurious messages when it detects these cases.
19 25
20Unfortunately, POE isn't generic enough to implement a fully working 26Unfortunately, POE isn't generic enough to implement a fully working
21AnyEvent backend: POE is too badly designed, too badly documented and too 27AnyEvent backend: POE is too badly designed, too badly documented and too
22badly implemented. 28badly implemented.
23 29
47change this. 53change this.
48 54
49This means that you will either have to live with lost events or you have 55This means that you will either have to live with lost events or you have
50to make sure to load AnyEvent early enough (this is usually not that 56to make sure to load AnyEvent early enough (this is usually not that
51difficult in a main program, but hard in a module). 57difficult in a main program, but hard in a module).
58
59POE has other weird messages, and sometimes weird behaviour, for example,
60it doesn't support overloaded code references as callbacks for no apparent
61reason.
52 62
53=item One POE session per Event 63=item One POE session per Event
54 64
55AnyEvent has to create one POE::Session per event watcher, which is 65AnyEvent has to create one POE::Session per event watcher, which is
56immensely slow and makes watchers very large. The reason for this is 66immensely slow and makes watchers very large. The reason for this is
218 228
219Sometimes registering a handler uses the "eventname, parameter" ordering 229Sometimes 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
221little consistency overall. 231little 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
238The IO::Poll "event loop" (who in his right mind would call that an event
239loop) of course scales about identically (sometimes it is a bit faster,
240sometimes a bit slower) to select in theory, and also in practise, of
241course, as both are O(n) in the number of file descriptors, which is
242rather bad.
243
244This is just one place where it gets obvious how little the author of the
245POE manpage understands.
246
247=item No idle events
248
249The POE-recommended workaround to this is apparently to use
250C<fork>. Consequently, idle watchera will have to be emulated by AnyEvent.
251
223=back 252=back
224 253
225On the good side, AnyEvent allows you to write your modules in a 100% 254On the good side, AnyEvent allows you to write your modules in a 100%
226POE-compatible way (bug-for-bug compatible even), without forcing your 255POE-compatible way (bug-for-bug compatible even), without forcing your
227module to use POE - it is still open to better event models, of which 256module to use POE - it is still open to better event models, of which
232package AnyEvent::Impl::POE; 261package AnyEvent::Impl::POE;
233 262
234no warnings; 263no warnings;
235use strict; 264use strict;
236 265
266use AnyEvent ();
237use POE; 267use POE;
238 268
239# have to do this to keep POE from spilling ugly messages 269# if POE is already running
270if (${ $poe_kernel->[POE::Kernel::KR_RUN] } && POE::Kernel::KR_RUN_CALLED) {
271 print STDERR <<EOF;
272POE is going to complain about
273 Sessions were started, but POE::Kernel's run() method was never...
274Try putting:
275 use AnyEvent::Impl::POE;
276at the very top of your main program to suppress these spurious warnings.
277EOF
278} else {
279 # workaround to suppress noise
240POE::Session->create (inline_states => { _start => sub { @_[KERNEL]->stop } }); 280 POE::Session->create (inline_states => { _start => sub { @_[KERNEL]->stop } });
241POE::Kernel->run; 281 POE::Kernel->run;
282}
242 283
243sub io { 284sub 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
272sub timer { 308sub 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
292sub signal { 329sub 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
315sub child { 352sub 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
339sub DESTROY { 376sub DESTROY {
340 POE::Kernel->post (${${$_[0]}}, "stop"); 377 POE::Kernel->post (${${$_[0]}}, "stop");
341} 378}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines