Mojo implementation?

Marc Lehmann schmorp at schmorp.de
Sun Oct 25 06:11:38 CET 2020


On Sat, Oct 24, 2020 at 07:40:00PM -0400, Felipe Gasper <felipe at felipegasper.com> wrote:
> > Digging a bit deeper, it seems Mojo already uses EV, which would make it
> > trivially compatible with AnyEvent, and according to the author the way it
> > is meant to be used with AnyEvent.
> 
> Mojo::IOLoop is the same idea as AnyEvent, just reinvented for Mojolicious. Like AnyEvent, Mojo::IOLoop *can* use EV but comes with its own pure-Perl event loop. If EV isn’t available, then both Mojo and AE will use their own loops, which of course doesn’t work.

Ah, I see. However: AnyEvent was written to be small, pure-perl and
without hard dependencies to facilitate it being usable for exactly this
purpose. Having it sit on top of Mojo seems counter-produtive, especially
as Mojo::IOLoop currently can't implement the AnyEvent API properly, otr at
leats it seems so from a cursory glance.

(As an unrelated sidenote, the manpage for Mojo::IOLoop incorrectly claims
libev commonly defaults to select, which is not (and has never been)
the case - select is only used when there is no other working backend
available (which should only happen on OS X as it doesn't have a working
poll or kqueue). Might be worth fixing, as telling people to use kqueue on
OS X can result in spurious and hard to track down bugs unless they know
exactly what they are doing.)

> We don’t use EV, and when we’ve tried it some of our tests have broken. That may indicate bugs on our end that should fix,

That is highly likely, and would, in my eyes, be a very worthwhile thing
to investigate, as the chance that it indicates bugs in Mojo is high. A
good first step would be to run with PERL_ANYEVENT_STRICT=1 in the
environment, which would catch many simple bugs (but of course can't do
miracles).

> AnyEvent::Impl::IOAsync is needed: a bridge that allows AnyEvent to call into the other event loop abstraction--in this case, Mojo rather than IO::Async--without caring about which actual event loop runs underneath.

IO::Async is a good example of what can go wrong, which is why I would be
very reluctant to put code into AnyEvent itself that would perpetuate such
a bad design and would also preclude a more sensible solution.

> Alternatively, Marc’s idea of having Mojo call into AnyEvent--a “Mojo::Reactor::AnyEvent” module--might work,
> but my understanding is that it’s problematic for IO::Async to call into AnyEvent, so I would think Mojo would have the same problem?

I don't know why it would be problematic, but I do know that I tried hard
to work with the IO::Async author, who unfortunately didn't even bother
to reply to my mails but instead asked the CPAN maintainers to delete
all my modules from CPAN and running around asking everybody to boycott
"me". As such, I suspect there is a certain animosity towards AnyEvent on
the IO::Async side...

To be more specific, Mojo would have the same problem if it would come
with its own AnyEvent-like solution, causing loops and very hard to track
down bugs that get reported to me, while simply refusing to work on
fixing those issues. It's totally fine to implement your own competing
AnyEvent-like infrastructure (well, it probably would be a disservice
to the user to be incompatible to AnyEvent on purpose, but that's your
choice), but as soon as I get bombarded with bug reports because of bugs
in your code, my goodwill ends :)

AnyEvent can either be on top of some other library, or on the bottom, but
not on both, and preferably it should be on the bottom, as AnyEvent tries
not to be a big framework or be very user-friendly - that is meant for the
library on top of it.

In my eyes, IO::Async is the *best* example of not having an
AnyEvent::Impl::Mojo, as it forces IO::Async to stay needlessly
incompatible and fixing things would require a concerted and synchronised
effort from both sides, which is hard to do, so the situation should be
avoided in the first place.

> Marc, if you’re amenable to the AnyEvent::Impl::Mojo idea I can whip up a proof-of-concept?

I think the most reasonable way would be to use AnyEvent directly (and fix
any bugs or incompatibilities that might come up) - that is what it's meant
for, and if there is a reason on why AnyEvent isn't suitable (again, a
lot of effort has been put into making it small, pure-perl and not low on
dependencies), maybe that should be worked out.

The only valid reason I could imagine is if an AnyEvent dependency were
impossible for policy reasons, in which case you could possibly have
AnyEvent as an optional dependency - as long as you would prefer AnyEvent
over your native event loop (if available) and would not block it would be
compatible with other AnyEvent users. That is, as long as AnyEvent does
*not* have an Impl::Mojo.

If Mojo absolutely *must* have its own event loop that AnyEvent should
use, then I would suggest keeping the AnyEvent glue code in Mojo::IOLoop
and extending it to handle the AnyEvent functions.

You can find an example on how to do this in rxvt-unicode (which
uses libev, but is not compatible to EV): urxvt.pm has a "package
urxvt::anyevent" which does a partial implementation (it misses _poll, as
blocking is not allowed in rxvt-unicode, but would have to be provided for
a generic implementation).

Note also that getting semantics right might be a bit problematic. For
example, AnyEvent supports both fds and filehandles and multiple watchers
for the same fd. Passing the AnyEvent testsute with
PERL_ANYEVENT_MODEL=Mojo::IOLoop might be helpful.

However, I am already weary to write so much about implementing what I
think is a bad solution from a user perspective. At least doing this
kind of hakc on the Mojo side means Mojo keeps the door open to a more
user-friendly solution in the future. Nevertheless, if you really,
absolutely, *must* do this, I can help you with it.

Or in short: you don't need to ask AnyEvent for help to make your own
AnyEvent backend, but think of the users, who would then be forces to
choose between Mojo and something else, while having AnyEvent at the
bottom where it belongs would let them have both :)

If anything is still clear, I am happy to confuse you further :)

Greetings,
Marc

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at schmorp.de
      -=====/_/_//_/\_,_/ /_/\_\



More information about the anyevent mailing list