[zeromq-dev] "Wakeup call" to a thread blocked inside zmq_poll()?

Michel Pelletier pelletier.michel at gmail.com
Mon Aug 13 21:04:27 CEST 2012


Ah, but this is probably not thread safe, sorry for the distraction,
use the PUSH/PULL pair. :)

-Michel

On Mon, Aug 13, 2012 at 11:59 AM, Michel Pelletier
<pelletier.michel at gmail.com> wrote:
> Using a waker socket is a great approach like MinRK said, FWIW it's
> not necessary to create a push and a pull socket, a single DEALER
> socket can connect to itself.  Here's a tweak of MinRK's diff:
>
> https://gist.github.com/3343232
>
> Lately I've been on a tirade of deprecating PUSH/PULL in my code in
> favor of DEALER in all cases, this looks like another nice case.
>
> -Michel
>
> On Mon, Aug 13, 2012 at 11:49 AM, MinRK <benjaminrk at gmail.com> wrote:
>>
>> On Mon, Aug 13, 2012 at 11:05 AM, Arthur O'Dwyer <arthur at push.am> wrote:
>>>
>>> Hi all,
>>>
>>> I'm trying to use ZMQ in what I guess (surprisingly to me) is an
>>> unconventional way. The salient points of our protocol are:
>>>
>>> - The connection has only two ends: exactly one client and exactly one
>>> server.
>>>
>>> - In fact, the labels "client" and "server" are mostly unnecessary;
>>> requests can originate on either side. Sometimes the client asks the
>>> server something, and sometimes the server asks the client something.
>>>
>>> - Answers to questions don't come right away (requests and replies are
>>> not nicely nested). If the client has two things to ask the server, it
>>> can do both requests at once, and the server can spawn two worker
>>> threads to compute the answers in parallel.
>>>
>>> I believe the architecture we need is a work queue on each side: when
>>> a client thread asks a question, it puts a request packet P_a and a
>>> timeout value T_a into the "outbox" and then waits on a condition
>>> variable associated with that transaction-ID. There's a master ZMQ
>>> thread with three responsibilies:
>>>
>>>     - Whenever the outbox is non-empty, pull a message from it and
>>> send it over the wire.
>>>     - Whenever a request comes in over the wire, spawn a new worker
>>> thread to handle that request.
>>>     - Whenever a reply comes in over the wire, match its
>>> transaction-ID to our list of waiting workers and notify the worker
>>> who's waiting for this particular reply.
>>>     - T_a seconds after the request P_a goes out over the wire, if the
>>> reply hasn't come yet, notify the waiting worker that the reply has
>>> timed out.
>>>
>>> Also, we'd like to have a "heartbeat" in both directions. But I
>>> believe that can easily be handled as a special kind of worker thread
>>> on each side, whose only job is to send a request every N seconds and
>>> complain if the reply times out.
>>>
>>> This feels like a really simple and common architecture, and I also
>>> believe it would work out of the box if ZMQ supported calling
>>> zmq_poll() from multiple threads (because then we wouldn't even need
>>> the master thread; all of this queuing ickiness would happen inside
>>> ZMQ itself). But for the life of me I can't figure out how to get ZMQ
>>> to wait on "something is incoming over the wire *or*
>>> some-other-event", without just polling every millisecond inside a
>>> loop.
>>>
>>> Suppose Thread A is waiting inside zmq_poll(); is there any way for
>>> Thread B to say "Hey! Wake up right now! I need to send a message!"?
>>
>>
>> You can do this by creating a waker socket just for this purpose, and always
>> including it in the poll set:
>>
>> https://gist.github.com/3343165
>>
>> -MinRK
>>
>>
>>>
>>>
>>> Thanks much,
>>> -Arthur
>>> _______________________________________________
>>> zeromq-dev mailing list
>>> zeromq-dev at lists.zeromq.org
>>> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>>
>>
>>
>> _______________________________________________
>> zeromq-dev mailing list
>> zeromq-dev at lists.zeromq.org
>> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>>



More information about the zeromq-dev mailing list