[zeromq-dev] External Event Loop

Jonathan Rockway jon at jrock.us
Sun Jan 2 02:57:32 CET 2011


Apologies if this is a dupe; the zmq-dev mail server did not like my
mail server's HELO command and rejected my previous post :)

* On Sat, Jan 01 2011, Praveen Baratam wrote:
> Is there anything wrong with the TestCase I have submitted in my
> previous mail?
>
> Me and my team are eagerly waiting for a reply from ZeroMQ team. 

I took a look at your test case, and am confused as to what you are
trying to achieve.  So I am going to describe how I implemented the
non-blocking Perl binding for ZMQ, which I am using with libev without
problems.  It the new ZMQ_EVENTS socktopt in the development version.

I'm going to cover reads, but writes work the same way.  When something
wants to read a message, it supplies a callback.  The idea is to call
the callback with the message when it's ready.

When we get a request to read, we start by checking readability of the
socket via ZMQ_EVENTS.  If the ZMQ_POLLIN is set we do a read (with
ZMQ_NONBLOCK), and call the callback with the message.  (If a message is
not read, perhaps due to non-readability of the socket, an exception is
thrown.  But this has never happened with any socket type, so I'm
guessing that ZMQ_EVENTS is accurate.)

If ZMQ_POLLIN is not set, then we can't read immediately. In that case,
we get the ZMQ_FD, and create an IO watcher (ev_io, specifically) on
that fd.  When the fd becomes readable, we check ZMQ_EVENTS again, and
do the read if possible.  We then remove the read watcher when we don't
care about reading anymore.

For reading multiple messages, we just do this in a loop -- check
readability; if readable: read the message, else: create IO watcher;
repeat.

This makes sense to me and has worked in all my testing, but I've seen
various people on the Internet discussing how they do this differently,
so I'm interested in any feedback as to how this approach is wrong.

Here is my code; a small library providing a function to probe for
readability ("probe"), and a function to actually create the IO watcher
and call a callback when the fd is ready ("io").

https://github.com/jrockway/anyevent-zeromq/blob/master/lib/AnyEvent/ZeroMQ.pm

I use that at a higher level to write AnyEvent::ZeroMQ::Handle, which is
how I tie together ZMQ_EVENTS and an IO watcher.

https://github.com/jrockway/anyevent-zeromq/blob/master/lib/AnyEvent/ZeroMQ/Handle.pm

The relevant algorithm is in "read":

https://github.com/jrockway/anyevent-zeromq/blob/master/lib/AnyEvent/ZeroMQ/Handle.pm#L134

The support function "_read_once" actually does the read,
"_has_read_todo" returns true if the user of AnyEvent::Handle wants to
read something (i.e., there are pending callbacks that need messages),
and "readable", which returns true if ZMQ_EVENTS says the socket is
readable.

Hope this helps, or that someone can tell me how I've botched this
terribly :)

Regards,
Jonathan Rockway



More information about the zeromq-dev mailing list