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.8 by root, Fri Apr 25 02:38:31 2008 UTC vs.
Revision 1.17 by root, Mon May 26 20:02:22 2008 UTC

1=head1 NAME 1=head1 NAME
2 2
3AnyEvent::Impl::POE - AnyEvent adaptor for POE 3AnyEvent::Impl::POE - AnyEvent adaptor for POE
4
5=encoding utf-8
4 6
5=head1 SYNOPSIS 7=head1 SYNOPSIS
6 8
7 use AnyEvent; 9 use AnyEvent;
8 use POE; 10 use POE;
39->run >> at AnyEvent loading time and stop the kernel immediately 41->run >> at AnyEvent loading time and stop the kernel immediately
40again. Unfortunately, due to another design bug in POE, this cannot be 42again. Unfortunately, due to another design bug in POE, this cannot be
41done (by documented means at least) without throwing away events in the 43done (by documented means at least) without throwing away events in the
42event queue. 44event queue.
43 45
46The author of POE verified that this is indeed true, and has no plans to
47change this.
48
44This means that you will either have to live with lost events or you have 49This means that you will either have to live with lost events or you have
45to make sure to load AnyEvent early enough (this is usually not that 50to make sure to load AnyEvent early enough (this is usually not that
46difficult in a main program, but hard in a module). 51difficult in a main program, but hard in a module).
47 52
48=item One POE session per Event 53=item One POE session per Event
51immensely slow and makes watchers very large. The reason for this is 56immensely slow and makes watchers very large. The reason for this is
52lacking lifetime management (mostly undocumented, too). Without one 57lacking lifetime management (mostly undocumented, too). Without one
53session/watcher it is not possible to easily keep the kernel from running 58session/watcher it is not possible to easily keep the kernel from running
54endlessly. 59endlessly.
55 60
61This is not just a problem with the way AnyEvent has to interact with
62POE, but is a principal issue with POEs lifetime management (namely
63that stopping the kernel stops sessions, but AnyEvent has no control
64over who and when the kernel starts or stops w.r.t. AnyEvent watcher
65creation/destruction).
66
67From benchmark data it is not clear that session creation is that costly,
68though - the real inefficiencies with POE seem to come from other sources,
69such as event handling.
70
56=item One watcher per fd/event combo 71=item One watcher per fd/event combo
57 72
58POE, of course, suffers from the same bug as Tk and some other badly 73POE, of course, suffers from the same bug as Tk and some other badly
59designed event models in that it doesn't support multiple watchers per 74designed event models in that it doesn't support multiple watchers per
60fd/poll combo. The workaround is the same as with Tk: AnyEvent::Impl::POE 75fd/poll combo. The workaround is the same as with Tk: AnyEvent::Impl::POE
62certainly not nice to your resources. 77certainly not nice to your resources.
63 78
64Of course, without the workaround, POE also prints ugly messages again 79Of course, without the workaround, POE also prints ugly messages again
65that say the program *might* be buggy. 80that say the program *might* be buggy.
66 81
82While this is not good to performance, at least regarding speed, with a
83modern Linux kernel, the overhead is actually quite small.
84
67=item Timing Deficiencies 85=item Timing Deficiencies
68 86
69POE manages to not have a function that returns the current time. This is 87POE manages to not have a function that returns the current time. This is
70extremely problematic, as POE can use different time functions, which can 88extremely problematic, as POE can use different time functions, which can
71differ by more than a second. In addition, most timer functions in POE 89differ by more than a second - and user code is left guessing which one is
72want an absoltue timestamp, which is hard to create if all you have is a 90used.
73relative time and no function to return the "current time".
74 91
75AnyEvent works around this by using relative timer fucntions, in the hope 92In addition, most timer functions in POE want an absoltue timestamp, which
76that POE gets it right at least internally. 93is hard to create if all you have is a relative time and no function to
94return the "current time".
95
96And of course POE doesn't handle time jumps at all (not even when using
97an event loop that happens to do that, such as L<EV>, as it does its own
98unoptimised timer management).
99
100AnyEvent works around the unavailability of the current time using
101relative timers exclusively, in the hope that POE gets it right at least
102internally.
77 103
78=item Event Non-Ordering 104=item Event Non-Ordering
79 105
80POE cannot guarentee the order of callback invocation for timers, and 106POE cannot guarentee the order of callback invocation for timers, and
81usually gets it wrong. That is, if you have two timers, one timing out 107usually gets it wrong. That is, if you have two timers, one timing out
82after another, the callbacks might be called in reverse order. 108after another (all els ebeing equal), the callbacks might be called in
109reverse order.
83 110
84How one manages to even implement stuff that way escapes me. 111How one manages to even implement stuff that way escapes me.
85 112
86=item Child Watchers 113=item Child Watchers
87 114
88POE offers child watchers - which is a laudable thing, as few event loops 115POE offers child watchers - which is a laudable thing, as few event loops
89do. Unfortunately, they cannot even implement AnyEvent's simple child 116do. Unfortunately, they cannot even implement AnyEvent's simple child
90watchers: they are not generic enough. 117watchers: they are not generic enough (even the POE implementation itself
118isn't generic enough to let properly designed event loops such as EV use
119their child watcher instead - it insist on doing it itself the slow way).
91 120
92Of course, if POE reaps an unrelated child it will also output a message 121Of course, if POE reaps an unrelated child it will also output a message
122for it that you cannot suppress (which shouldn't be too surprising at this
93for it. Very professional. 123point). Very professional.
94 124
95As a workaround, AnyEvent::Impl::POE will take advantage of undocumented 125As a workaround, AnyEvent::Impl::POE will take advantage of undocumented
96behaviour in POE::Kernel to catch the status fo all child processes. 126behaviour in POE::Kernel to catch the status of all child processes.
97 127
98Unfortunately, POE's child handling is racy: if the child exits before the 128Unfortunately, POE's child handling is racy: if the child exits before the
99handler is created (which is impossible to guarantee...), one has to wait 129handler is created (which is impossible to avoid in general), one has to
100for another event to occur, which can take an indefinite time (apparently 130wait for another event to occur, which can take an indefinite amount of
101POE does a busy-waiting loop every second, but this is not guarenteed 131time (apparently POE does a busy-waiting loop every second, but this is
102or documented, so in practise child status events can be delayed for a 132not guarenteed or documented, so in practise child status events can be
103second). 133delayed for up to a second "only" at least in the current version).
104 134
105How one manages to have such a glaring bug in an event loop after ten 135How one manages to have such a glaring bug in an event loop after ten
106years of development escapes me. 136years of development escapes me.
107 137
108=item Documentation Quality 138=item Documentation Quality
109 139
110At the time of this writing, POE was in its tenth year. Still, its 140At the time of this writing, POE was in its tenth year. Still, its
111documentation is extremely lacking, making it impossible to implement 141documentation is extremely lacking, making it impossible to implement
112stuff as trivial as AnyEvent watchers without havign to resort to 142stuff as trivial as AnyEvent watchers without having to resort to
113undocumented behaviour or features. 143undocumented behaviour or features.
114 144
115For example, the POE::Kernel manpage has nice occurances of the word TODO 145For example, the POE::Kernel manpage has nine occurances of the word TODO
116with an explanation of whats missing. Some other gems: 146with an explanation of whats missing. In general, the POE manpages are
147littered with comments like "section not yet written".
148
149Some other gems:
117 150
118 This allows many object methods to also be package methods. 151 This allows many object methods to also be package methods.
119 152
120This is nice, but since it doesn't document I<which> methods these are, 153This is nice, but since it doesn't document I<which> methods these are,
121this is utterly useless information. 154this is utterly useless information.
122 155
123 Terminal signals will kill sessions if they are not handled by a 156 Terminal signals will kill sessions if they are not handled by a
124 "sig_handled"() call. The OS signals that usually kill or dump a 157 "sig_handled"() call. The OS signals that usually kill or dump a
125 process are considered terminal in POE, but they never trigger a 158 process are considered terminal in POE, but they never trigger a
126 coredump. These are: HUP, INT, QUIT and TERM. 159 coredump. These are: HUP, INT, QUIT and TERM.
127 160
128Although AnyEvent calls sig_handled, removing it has no apparent effects 161Although AnyEvent calls C<sig_handled>, removing it has no apparent
129on POE handling SIGINT. 162effects on POE handling SIGINT.
163
164 refcount_increment SESSION_ID, COUNTER_NAME
165
166Nowhere is explained which COUNTER_NAMEs are valid and which aren't - not
167all scalars (or even strings) are valid counter names. Take your guess,
168failure is of course completely silent. I found this out the hard way, as
169the first name I came up with was silently ignored.
170
171 get_next_event_time() returns the time the next event is due, in a form
172 compatible with the UNIX time() function.
173
174And surely, one would hope that POE supports subsecond accuracy as
175documented elsewhere, unlike the explanation above implies. Yet:
176
177 POE::Kernel timers support subsecond accuracy, but don’t expect too
178 much here. Perl is not the right language for realtime programming.
179
180... of course, Perl is not the right language to expect subsecond accuray
181- the manpage author must hate Perl to spread so much FUD in so little
182space. The Deliantra game server logs with 100µs-accuracy because Perl is
183fast enough to require this, and is still able to deliver map updates with
184little jitter at exactly the right time. It does not, however, use POE.
130 185
131 Furthermore, since the Kernel keeps track of everything sessions do, it 186 Furthermore, since the Kernel keeps track of everything sessions do, it
132 knows when a session has run out of tasks to perform. 187 knows when a session has run out of tasks to perform.
133 188
134This is impossible - how does the kernel now that a session is no longer 189This is impossible - how does the kernel know that a session is no longer
135watching for some (external) event (e.g. by some other session)? It 190watching for some (external) event (e.g. by some other session)? It
136cannot, and therefore this is wrong. 191cannot, and therefore this is wrong - but you would be hard pressed to
192find out how to work around this and tell the kernel manually about such
193events.
137 194
138It gets worse, though - the notion of "task" or "resource", although used 195It gets worse, though - the notion of "task" or "resource", although used
139throughout the documentation, is not defined in a usable way. For example, 196throughout the documentation, is not defined in a usable way. For example,
140waiting for a timeout is considered to be a task, waiting for a signal is 197waiting for a timeout is considered to be a task, waiting for a signal is
198not (a session that only waits for a signal is considered finished and
141not. The user is left guessing when waiting for an event counts as task 199gets removed). The user is left guessing when waiting for an event counts
142and when not. 200as task and when not (in fact, the issue with signals is mentioned in
201passing in a section about child watchers and directly contradicts earlier
202parts in that document).
143 203
144One could go on endlessly - ten years, no usable docs. 204One could go on endlessly - ten years, no usable documentation.
145 205
146It is likely that differences between documentation, or the one or two 206It is likely that differences between documentation, or the one or two
147things I had to guess, cause unanticipated problems with the backend. 207things I had to guess, cause unanticipated problems with this adaptor.
148 208
149=item Bad API 209=item Fragile and inconsistent API
150 210
151The POE API is extremely inconsistent - sometimes you have to pass a 211The POE API is extremely inconsistent - sometimes you have to pass a
152session argument, sometimes it gets ignored, sometimes a session-specific 212session argument, sometimes it gets ignored, sometimes a session-specific
153method must not use a session argument. 213method must not use a session argument.
154 214
215Error handling is sub-standard as well: even for programming mistakes,
216POE does not C<croak> but, in most cases, just sets C<$!> or simply does
217nothing at all, leading to fragile programs.
218
155Sometimes registering a handler uses "eventname, parameter" (timeouts), 219Sometimes registering a handler uses the "eventname, parameter" ordering
156sometimes it is "parameter, eventname" (signals). There is little 220(timeouts), sometimes it is "parameter, eventname" (signals). There is
157consistency. 221little consistency overall.
222
223=item Lack of knowledge
224
225 The IO::Poll event loop provides an alternative that theoretically
226 scales better than select().
227
228The IO::Poll "event loop" (who in his right mind would call that an event
229loop) of course scales about identically (sometimes it is a bit faster,
230sometimes a bit slower) to select in theory, and also in practise, of
231course, as both are O(n) in the number of file descriptors, which is
232rather bad.
233
234This is just one place where it gets obvious how little the author of the
235POE manpage understands.
158 236
159=back 237=back
160 238
161On the good side, AnyEvent allows you to write your modules in a 99% 239On the good side, AnyEvent allows you to write your modules in a 100%
162POE-compatible way (conflicting child watchers), without forcing your 240POE-compatible way (bug-for-bug compatible even), without forcing your
163module to use POE - it is still open to better event models, of which 241module to use POE - it is still open to better event models, of which
164there are plenty. 242there are plenty.
165 243
166=cut 244=cut
167 245
206} 284}
207 285
208sub timer { 286sub timer {
209 my ($class, %arg) = @_; 287 my ($class, %arg) = @_;
210 my $after = delete $arg{after}; 288 my $after = delete $arg{after};
211 my $cb = delete $arg{cb}; 289 my $cb = delete $arg{cb};
212 my $session = POE::Session->create ( 290 my $session = POE::Session->create (
213 inline_states => { 291 inline_states => {
214 _start => sub { 292 _start => sub {
215 $_[KERNEL]->delay_set (timeout => $after); 293 $_[KERNEL]->delay_set (timeout => $after);
216 }, 294 },

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines