AnyEvent driver for Prima

Dmitry Karasik dmitry at karasik.eu.org
Tue Dec 13 20:50:35 CET 2016


Hi all,

It gets a bit messy with everyone answering everone's mail, but I'll try to answer my best,
and mix answers from different mails.

> 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.

Prima doesn't accept fd, and AFAIK there's not easy perl way to extract that
(other way around though, yes, with fileno()). If necessary, I think it is possible
to extend Prima so it can work with FDs, but it seems to me that if that is the common
problem with event loop backends, it might be a good idea for AnyEvent to provide some
sort of function (_dupfh possible does it already?) to make an inverse call to fileno().

> 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.  

Indeed there's no idle method in Prima, but could you possibly elaborate how that method
is supposed to work? Does it fire every so-and-so seconds while a program is idle, or
it only does so when there are no more events, and then sleeps? 

> 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.

I see. I wasn't aware of such a semantics, but I think I could export 
something along application.poll() for doing this. I'll see how far I can go.

> == 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.

With Prima::File it is easy - it does that. With Prima::Timer it is
complicated, because it is not, and the only way to stop the events from
happening is to call destroy() explicitly on the timer.

This however, is a really old design on Prima, which was based on the idea that
Prima::Application should be a root/container for all objects, and on the end
of application's life all object would die too (hence the class name,
Application). With time though the design changed - I added Prima::Image
functionality for application-less mode, and the application itself became a
root/container for all widgets, while non-widgets, at least in theory, should
be OK without it.

Realizing that, I just now committed an experimental patch to make it possible
for Prima::Timer to live without application as well. You can try it from the
latest github snapshot, and if nothing changes, will be part of 1.50 release.

> 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?  

This for sure won't happen for x11 backend, but for win32 backend I cannot
answer that. The timer is implemented using standard SetTimer() function, which
might or might not send more events in the system message queue. I just wrote a
script to test this on my Windows 7, all seems ok, but I cannot give you a
guarantee.

Also, the windows timer is rather imprecise, and can also eat up events (and it
does, actually, the missed events do not accumulate).

> 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.

stop() will depend on win32 message queue, which seems to do the right thing,
but if you want the bullet proof code, call destroy() instead.


-- 
Sincerely,
	Dmitry Karasik




More information about the anyevent mailing list