1AnyEvent::Impl::POE(3)User Contributed Perl DocumentationAnyEvent::Impl::POE(3)
2
3
4

NAME

6       AnyEvent::Impl::POE - AnyEvent adaptor for POE
7

SYNOPSIS

9          use AnyEvent;
10          use POE;
11
12          # this module gets loaded automatically as required
13

DESCRIPTION

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

SEE ALSO

267       AnyEvent, POE.
268

AUTHOR

270        Marc Lehmann <schmorp@schmorp.de>
271        http://home.schmorp.de/
272
273
274
275perl v5.12.1                      2010-01-07            AnyEvent::Impl::POE(3)
Impressum