[zeromq-dev] How to get buffer out of zmq_msg
john skaller
skaller at users.sourceforge.net
Wed Feb 8 02:04:18 CET 2012
On 08/02/2012, at 11:09 AM, Martin Sustrik wrote:
> Hi John,
>
>> If you initialise the message empty, zmq_recvmsg will allocate
>> exactly the right amount of space for you. This is ideal.
>> But there's no way to get the buffer out of the msg, you have
>> to copy it. This is wastes a memcpy, and wastes storage temporarily.
>> You have to copy it because zmq_close will deallocate the buffer.
>
> The problem is that 0mq messages are reference counted, so you may be
> sharing the message buffer with others.
A solution for zmq_release function would be:
(a) if the buffer isn't shared, return it, and clear the msg_t object
(i.e. set pointer to NULL)
(b) if the reference count is 2 or more:
copy the buffer, decrement the count,
clear the msg_t object
>
>> Of course .. you can *cheat* and simply not close the zmq_msg_t,
>> and in the current implementation I am guessing this would work.
>
> Yes. That should work.
OK, I have committed zmq_recvmmsg to my clone now.
Not sure about the name!
This is as close to an XSI compliant
interface as I can think of. This function is for receiving 0MQ multi-part
messages only. If used on a non-multi-part message it just reads a single
message.
The semantics differ from XSI readv() function in that the 0MQ variant
allocates and sets the length of the buffers according to the
0MQ multi-part message part length.
If the vector is too short to hold all the message parts, the function
simply returns with ZMQ_RCVMORE set on the socket,
therefore the behaviour is identical to zmq_recv if you
set *count_=1.
Note carefully the assumptions, please let me know if any of these
assumptions are wrong in the current implementation, if there's
a better way, or whatever. The fragility is unfortunate and can easily
be avoided by copying the buffers but this is inefficient.
(a) It is safe to simply forget a zmq_msg we allocated and initialised,
and filled in by zmq_recv. There cannot be any sharing.
(b) zmq_recv allocates a msg buffer with malloc family function so it
is safe to allow the client to free these buffers with free()
// Receive a multi-part message
//
// Receives up to *count_ parts of a multi-part message.
// Sets *count_ to the actual number of parts read.
// ZMQ_RCVMORE is set to indicate if a complete multi-part message was read.
// Returns number of message parts read, or -1 on error.
//
// Note: even if -1 is returned, some parts of the message
// may have been read. Therefore the client must consult
// *count_ to retrieve message parts successfully read,
// even if -1 is returned.
//
// The iov_base* buffers of each iovec *a_ filled in by this
// function may be freed using free().
//
// Implementation note: We assume zmq::msg_t buffer allocated
// by zmq::recvmsg can be freed by free().
// We assume it is safe to steal these buffers by simply
// not closing the zmq::msg_t.
//
int zmq_recvmmsg (void *s_, iovec *a_, size_t *count_, int flags_)
--
john skaller
skaller at users.sourceforge.net
More information about the zeromq-dev
mailing list