richardhundt / luv

libuv bindings for Lua
Apache License 2.0
118 stars 19 forks source link

optional parameter to ZMQ send() [ZMQ_SNDMORE] #12

Open miko opened 11 years ago

miko commented 11 years ago

Hello, in order to send a multi-part zmq messages, the ZMQ_SNDMORE flag should be set. I understand that in luv send() should be non-blocking, so ZMQ_DONTWAIT is mandatory, but it would be nice to have option for ZMQ_SNDMORE also. So my proposal is: socket:send(mesg[, flags]) (to be future-proof in case zmq adds more flags here), with the comment that the flags will be ORed with ZMQ_DONTWAIT (or not, if that is not mandatory in luv), with default value of ZMQ_DONTWAIT.

dvv commented 11 years ago

or-ed means integer constants, not string ones, as in #11 is mentioned, right?

miko commented 11 years ago

Yes, even if you give it as a string, it is internally transformed to integer, so this integer can be ORed with (the integer value of) ZMQ_DONTWAIT.

richardhundt commented 11 years ago

On Oct 10, 2012, at 11:10 AM, miko wrote:

Hello, in order to send a multi-part zmq messages, the ZMQ_SNDMORE flag should be set. I understand that in luv send() should be non-blocking, so ZMQ_DONTWAIT is mandatory, but it would be nice to have option for ZMQ_SNDMORE also. So my proposal is: socket:send(mesg[, flags]) (to be future-proof in case zmq adds more flags here), with the comment that the flags will be ORed with ZMQ_DONTWAIT (or not, if that is not mandatory in luv), with default value of ZMQ_DONTWAIT.

I was thinking of handling ZMQ_SNDMORE transparently like so:

socket:send(frame1, …, frameN)

and then

local frame1, …, frameN = socket:recv()

but maybe that's too much abstraction? Perhaps do as you suggest for socket:send and socket:recv and then add socket:get and socket:put which deals with tuples?

What do you guys think?

miko commented 11 years ago

When receiving the multipart message, the original design is to do this in a loop:

more=true
while more do
  msg=socket:receive()
  more=socket:getsockopt('RCVMORE')
end

The nice thing is that if you want to discard the whole message based on its first part, you don't need to read (and create possibly large, useless objects for) remaining parts.

For sending messages, you need to create all the objects (message parts), but you still could prefer to do it sequentially in order to conserve the memory (the objects could be generated in different moments of a state, i.e. while yielding out of a coroutine).

In such case there would be no point to create :get() and :put(), you just would have to call getsockopt() for each part of a read-in message (and SNDMORE would be an option of send() ). This would be parallel to original zeromq examples, so it is already documented like so: http://zguide.zeromq.org/page:all#Multi-part-Messages.

Anyways, I would prefer send(frame1, ..., frameN) than dealing with "alien" :put()/:get().

dvv commented 11 years ago

sounds good. i'd also think of unifying file:write(x1, x2, ...) with socket:send() -- we could use uv_write feature of taking multiple chunks and avoid concats with are slow in lua