AnyEvent driver for Prima
ambrus
ambrus at math.bme.hu
Tue Dec 13 14:47:21 CET 2016
Hello Dmitry Karasik, Corion, and Schmorp.
Corion is making an AnyEvent driver for Prima. In this email, I'll
first try to recap what's happened, because the communication about this
was fragmented to multiple forums. I'll then ask some questions to
Dmitry about Prima that are connected to this, and also questions to
schmorp about AnyEvent.
== Recap ==
Prima is a GUI toolkit with a perl interface, homepage
"http://www.prima.eu.org/" and available from CPAN. Corion was trying
to use Prima and do some HTTP requests from the same perl interpreter on
win32. This needs some event loop integration, so I pushed Corion into
using AnyEvent for that.
So Corion is working on an AnyEvent driver for Prima. This is in an
early stage, visible at "https://github.com/Corion/AnyEvent-Impl-Prima".
When he fixes it and tests it properly, he will release it, and then
schmorp might move it into the AnyEvent CPAN distribution.
In the AnyEvent docs, schmorp tells the basic idea of what an AnyEvent
driver needs to do, and he has told a bit more about this case. An
AnyEvent driver is a module that can override certain methods of the
AnyEvent module.
The two most important methods to override are io, which implements a
file descriptor watcher, and timer, which implements a timer watcher.
Prima provides watchers suitable for these, exposed in Prima::File and
Prima::Timer, so Corion already has implementations of these methods.
The implementation are not perfect, but there's no big problems that
can't be fixed easily. In particular, the io method should accept
either a perl IO handle or a unix file descriptor number as the fd
parameter. Corion's implementation doesn't yet do that, but this can be
fixed, and the AnyEvent::_dupfh undocumented function might help.
Ideally there should also be an idle method, which creates a watcher
such that whenever the event loop would sleep waiting for new events to
happen, the callback of the watcher is called instead of sleeping.
Prima doesn't expose this function, and it seems that a proper
implementation isn't possible without modifying at least the unix event
loop of Prima. This isn't urgent though, because Corion's application
of a HTTP client won't be using this watcher at all.
The driver does not need to override the signal and child watchers,
because AnyEvent already provides implementations for those. The
default implementations should work fine. The implementation could fail
if some other code tries to wait for child processes already,
interfering with AnyEvent, but Prima doesn't seem to ever do that. The
driver also doesn't need to override condvar watchers, because the
default implementation always works, and is only ever overrided for
performance.
The module should also override the _poll method. This method is
expected to call into the main loop of the event loop, to sleep until
some events are triggered, handle at least one event, and then return.
It isn't strictly necessary to implement this, because the driver can
still be used in Prima programs fine without, but it helps a lot when
testing the driver. Prima doesn't seem to expose a suitable function
for this: it only has the yield method of Prima::Application, which
doesn't sleep if no events are available, and the go method, which
doesn't return until the application exits.
== Questions to Dmitry ==
I'd like some clarifications because I'm not sure I understand how the
Prima API works.
The AnyEvent API expects that watchers can be cancelled by getting the
perl watcher object garbage collected. After the caller frees the last
reference to the watcher, the callbacks should no longer get invoked.
The event loop thus shouldn't keep references to the watcher or
callbacks when the perl watcher object is destroyed. (Also, obviously,
the DESTROY method of the perl watcher object shouldn't revive the
object.) I'd like to know if the Prima::File and Prima::Timer behave
this way already. In particular, if multiple events are queued, and
then the callback for one of the events destroys the watcher for the
second event, will Prima discard the second event? If it doesn't,
that's no problem, we can handle destroying the perl object specifically
in the driver, but the driver doesn't currently do that.
The Prima::Timer watcher is always in periodic repeating mode. If the
timeout is small, is it possible that the timeout fires twice before the
event loop gets a chance to execute the callback the first time?
Corion's implementation of the timer calls the stop method of the timer
from the callback, but I'd like to know if that's enough to make sure
that the callback can't be called again.
== Questions to schmorp ==
Prima::Utils->post is a function that corresponds to AnyEvent::postpone.
It arranges that the event loop calls a callback later, without having
to bother to set up a watcher object. Can a driver override this
function by just defining postpone in the driver package? Should the
driver override it?
In the API of AnyEvent, when a watcher is destroyed, is the DESTROY
method allowed to call the callback right then? EV certainly doesn't do
that, but I'm asking about AnyEvent in general.
-- Ambrus
More information about the anyevent
mailing list