Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
AnyEvent::Impl::POE(3)User Contributed Perl DocumentatioAnyEvent::Impl::POE(3)

NAME
       AnyEvent::Impl::POE - AnyEvent adaptor for POE

SYNOPSIS
	  use AnyEvent;
	  use POE;

	  # this module	gets loaded automatically as required

DESCRIPTION
       This module provides transparent	support	for AnyEvent. You don't	have
       to do anything to make POE work with AnyEvent except by loading POE
       before creating the first AnyEvent watcher. There are some cases	where
       POE will	issue spurious (and non-suppressible) warnings.	These can be
       avoided by loading AnyEvent::Impl::POE before loading any other modules
       using POE and AnyEvent, i.e. in your main program.

       AnyEvent::Impl::POE will	output some spurious message how to work
       around POE's spurious messages when it detects these cases.

       Unfortunately, POE isn't	generic	enough to implement a fully working
       AnyEvent	backend: POE is	too badly designed, too	badly documented and
       too badly implemented.

       Here are	the details, and what it means to you if you want to be
       interoperable with POE:

       Weird messages
	   If you only use "run_one_timeslice" (as AnyEvent has	to for its
	   condition variables), POE will print	an ugly, unsuppressible,
	   message at program exit:

	      Sessions were started, but POE::Kernel's run() method was	never...

	   The message is correct, the question	is why POE prints it in	the
	   first place in a correct program (this is not a singular case
	   though).

	   AnyEvent consequently patches the POE kernel	so it thinks it
	   already ran.	Other workarounds, even	the one	cited in the POE
	   documentation itself, have serious side effects, such as throwing
	   away	events.

	   The author of POE verified that this	is indeed true,	and has	no
	   plans to change this.

	   POE has other weird messages, and sometimes weird behaviour,	for
	   example, it doesn't support overloaded code references as callbacks
	   for no apparent reason.

       One POE session per Event
	   AnyEvent has	to create one POE::Session per event watcher, which is
	   immensely slow and makes watchers very large. The reason for	this
	   is lacking lifetime management (mostly undocumented,	too). Without
	   one session/watcher it is not possible to easily keep the kernel
	   from	running	endlessly.

	   This	is not just a problem with the way AnyEvent has	to interact
	   with	POE, but is a principal	issue with POEs	lifetime management
	   (namely that	stopping the kernel stops sessions, but	AnyEvent has
	   no control over who and when	the kernel starts or stops w.r.t.
	   AnyEvent watcher creation/destruction).

	   From	benchmark data it is not clear that session creation is	that
	   costly, though - the	real inefficiencies with POE seem to come from
	   other sources, such as event	handling.

       One watcher per fd/event	combo
	   POE,	of course, suffers from	the same bug as	Tk and some other
	   badly designed event	models in that it doesn't support multiple
	   watchers per	fd/poll	combo. The workaround is the same as with Tk:
	   AnyEvent::Impl::POE creates a separate file descriptor to hand to
	   POE,	which isn't fast and certainly not nice	to your	resources.

	   Of course, without the workaround, POE also prints ugly messages
	   again that say the program *might* be buggy.

	   While this is not good to performance, at least regarding speed,
	   with	a modern Linux kernel, the overhead is actually	quite small.

       Timing deficiencies
	   POE manages to not have a function that returns the current time.
	   This	is extremely problematic, as POE can use different time
	   functions, which can	differ by more than a second - and user	code
	   is left guessing which one is used.

	   In addition,	most timer functions in	POE want an absolute
	   timestamp, which is hard to create if all you have is a relative
	   time	and no function	to return the "current time".

	   And of course POE doesn't handle time jumps at all (not even	when
	   using an event loop that happens to do that,	such as	EV, as it does
	   its own unoptimised timer management).

	   AnyEvent works around the unavailability of the current time	using
	   relative timers exclusively,	in the hope that POE gets it right at
	   least internally.

       Lack of defined event ordering
	   POE cannot guarantee	the order of callback invocation for timers,
	   and usually gets it wrong. That is, if you have two timers, one
	   timing out after another (all else being equal), the	callbacks
	   might be called in reverse order.

	   How one manages to even implement stuff that	way escapes me.

       Child watchers
	   POE offers child watchers - which is	a laudable thing, as few event
	   loops do. Unfortunately, they cannot	even implement AnyEvent's
	   simple child	watchers: they are not generic enough (the POE
	   implementation isn't	even generic enough to let properly designed
	   back-end use	their native child watcher instead - it	insist on
	   doing it itself the broken way).

	   Unfortunately, POE's	child handling is inherently racy: if the
	   child exits before the handler is created (because e.g. it crashes
	   or simply is	quick about it), then current versions of POE (1.352)
	   will	never invoke the child watcher,	and there is nothing that can
	   be done about it. Older versions of POE only	delayed	in this	case.
	   The reason is that POE first	checks if the child has	already
	   exited, and then installs the signal	handler	- aa classical race.

	   Your	only hope is for the fork'ed process to	not exit too quickly,
	   in which case everything happens to work.

	   Of course, whenever POE reaps an unrelated child it will also
	   output a message for	it that	you cannot suppress (which shouldn't
	   be too surprising at	this point). Very professional.

	   As a	workaround, AnyEvent::Impl::POE	will take advantage of
	   undocumented	behaviour in POE::Kernel to catch the status of	all
	   child processes, but	it cannot guarantee delivery.

	   How one manages to have such	a glaring bug in an event loop after
	   ten years of	development escapes me.

	   (There are more annoying bugs, for example, POE runs	"waitpid"
	   unconditionally at finaliser	time, so your program will hang	until
	   all child processes have exited.)

       Documentation quality
	   At the time of this writing,	POE was	in its tenth year. Still, its
	   documentation is extremely lacking, making it impossible to
	   implement stuff as trivial as AnyEvent watchers without having to
	   resort to undocumented behaviour or features.

	   For example,	the POE::Kernel	manpage	has nine occurrences of	the
	   word	TODO with an explanation of whats missing. In general, the POE
	   man pages are littered with comments	like "section not yet
	   written".

	   Some	other gems:

	      This allows many object methods to also be package methods.

	   This	is nice, but since it doesn't document which methods these
	   are,	this is	utterly	useless	information.

	      Terminal signals will kill sessions if they are not handled by a
	      "sig_handled"() call. The	OS signals that	usually	kill or	dump a
	      process are considered terminal in POE, but they never trigger a
	      coredump.	These are: HUP,	INT, QUIT and TERM.

	   Although AnyEvent calls "sig_handled", removing it has no apparent
	   effects on POE handling SIGINT.

	      refcount_increment SESSION_ID, COUNTER_NAME

	   Nowhere is explained	which COUNTER_NAMEs are	valid and which	aren't
	   - not all scalars (or even strings) are valid counter names.	Take
	   your	guess, failure is of course completely silent. I found this
	   out the hard	way, as	the first name I came up with was silently
	   ignored.

	      get_next_event_time() returns the	time the next event is due, in a form
	      compatible with the UNIX time() function.

	   And surely, one would hope that POE supports	sub-second accuracy as
	   documented elsewhere, unlike	the explanation	above implies. Yet:

	      POE::Kernel timers support subsecond accuracy, but donat expect too
	      much here. Perl is not the right language	for realtime programming.

	   ... of course, Perl is not the right	language to expect sub-second
	   accuracy - the manpage author must hate Perl	to spread so much FUD
	   in so little	space. The Deliantra game server logs with
	   100A<micro>s-accuracy because Perl is fast enough to	require	this,
	   and is still	able to	deliver	map updates with little	jitter at
	   exactly the right time. It does not,	however, use POE.

	      Furthermore, since the Kernel keeps track	of everything sessions do, it
	      knows when a session has run out of tasks	to perform.

	   This	is impossible -	how does the kernel know that a	session	is no
	   longer watching for some (external) event (e.g. by some other
	   session)? It	cannot,	and therefore this is wrong - but you would be
	   hard	pressed	to find	out how	to work	around this and	tell the
	   kernel manually about such events.

	   It gets worse, though - the notion of "task"	or "resource",
	   although used throughout the	documentation, is not defined in a
	   usable way. For example, waiting for	a timeout is considered	to be
	   a task, waiting for a signal	is not (a session that only waits for
	   a signal is considered finished and gets removed). The user is left
	   guessing when waiting for an	event counts as	task and when not (in
	   fact, the issue with	signals	is mentioned in	passing	in a section
	   about child watchers	and directly contradicts earlier parts in that
	   document).

	   One could go	on endlessly - ten years, no usable documentation.

	   It is likely	that differences between documentation,	or the one or
	   two things I	had to guess, cause unanticipated problems with	this
	   adaptor.

       Fragile and inconsistent	API
	   The POE API is extremely inconsistent - sometimes you have to pass
	   a session argument, sometimes it gets ignored, sometimes a session-
	   specific method must	not use	a session argument.

	   Error handling is sub-standard as well: even	for programming
	   mistakes, POE does not "croak" but, in most cases, just sets	$! or
	   simply does nothing at all, leading to fragile programs.

	   Sometimes registering a handler uses	the "eventname,	parameter"
	   ordering (timeouts),	sometimes it is	"parameter, eventname"
	   (signals). There is little consistency overall.

       Lack of knowledge
	      The IO::Poll event loop provides an alternative that theoretically
	      scales better than select().

	   The IO::Poll	"event loop" (who in his right mind would call that an
	   event loop) of course scales	about identically (sometimes it	is a
	   bit faster, sometimes a bit slower) to select in theory, and	also
	   in practise,	of course, as both are O(n) in the number of file
	   descriptors,	which is rather	bad.

	   This	is just	one place where	it gets	obvious	how little the author
	   of the POE manpage understands.

       No idle events
	   The POE-recommended workaround to this is apparently	to use "fork".
	   Consequently, idle watchers will have to be emulated	by AnyEvent.

       Questionable maintainer behaviour
	   The author of POE is	known to fabricate statements and post these
	   to public mailinglists - apparently,	spreading FUD about competing
	   (in his eyes) projects or their maintainers is acceptable to	him.

	   This	has (I believe)	zero effects on	the quality or usefulness of
	   his code, but it does completely undermine his trustworthyness - so
	   don't blindly believe anything he says, he might have just made it
	   up to suit his needs	(benchmark results, the	names of my ten	wifes,
	   the length of my penis, etc.	etc.). When in doubt, double-check -
	   not just him, anybody actually.

	   Example:
	   <http://www.nntp.perl.org/group/perl.perl5.porters/2012/01/msg182141.html>.
	   I challenged	him in that thread to provide evidence for his
	   statement by	giving at least	two examples, but of course since he
	   just	made it	up, he couldn't	provide	any evidence.

       On the good side, AnyEvent allows you to	write your modules in a	100%
       POE-compatible way (bug-for-bug compatible even), without forcing your
       module to use POE - it is still open to better event models, of which
       there are plenty.

       Oh, and one other positive thing:

	  RUNNING_IN_HELL

       POE knows about the nature of the beast!

SEE ALSO
       AnyEvent, POE.

AUTHOR
	Marc Lehmann <schmorp@schmorp.de>
	http://anyevent.schmorp.de

perl v5.32.0			  2012-04-08		AnyEvent::Impl::POE(3)

NAME | SYNOPSIS | DESCRIPTION | SEE ALSO | AUTHOR

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=AnyEvent::Impl::POE&sektion=3&manpath=FreeBSD+12.2-RELEASE+and+Ports>

home | help