Class: ZMQ::Message
Overview
The constructor optionally takes a string as an argument. It will copy this string to native memory in preparation for transmission. So, don’t pass a string unless you intend to send it. Internally it calls #copy_in_string.
Call #close to release buffers when you have not passed this on to Socket#send or Socket#recv. Those methods call #close on your behalf.
(This class is not really zero-copy. Ruby makes this near impossible.)
Message represents ruby equivalent of the zmq_msg_t
C struct. Access the underlying memory buffer and the buffer size using the #data and #size methods respectively.
It is recommended that this class be composed inside another class for access to the underlying buffer. The outer wrapper class can provide nice accessors for the information in the data buffer; a clever implementation can probably lazily encode/decode the data buffer on demand. Lots of protocols send more information than is strictly necessary, so only decode (copy from the 0mq buffer to Ruby) that which is necessary.
When you are done using a received message object, just let it go out of scope to release the memory. During the next garbage collection run it will call the equivalent of #LibZMQ.zmq_msg_close to release all buffers. Obviously, this automatic collection of message objects comes at the price of a larger memory footprint (for the finalizer proc object) and lower performance. If you wanted blistering performance, Ruby isn’t there just yet.
As noted above, for sent objects the underlying library will call close for you.
class MyMessage
def initialize msg_struct = nil
@msg_t = msg_struct ? msg_struct : ZMQ::Message.new
end
def size() @size = @msg_t.size; end
def decode
@decoded_data = JSON.parse(@msg_t.copy_out_string)
end
def field1
@field1 ||= decode[:field1]
end
def field2
@field2 ||= decode[:field2]
end
= Message.new
successful_read = socket.recv
= MyMessage.new if successful_read
puts "field1 is #{.field1}"
Instance Method Summary collapse
-
#address ⇒ Object
(also: #pointer)
Provides the memory address of the
zmq_msg_t
struct. -
#close ⇒ Object
Manually release the message struct and its associated data buffer.
- #copy(source) ⇒ Object
-
#copy_in_bytes(bytes, len) ⇒ Object
Makes a copy of
len
bytes from the ruby stringbytes
. -
#copy_in_string(string) ⇒ Object
Makes a copy of the ruby
string
into a native memory buffer so that libzmq can send it. -
#copy_out_string ⇒ Object
Returns the data buffer as a string.
-
#data ⇒ Object
Returns a pointer to the data buffer.
-
#initialize(message = nil) ⇒ Message
constructor
A new instance of Message.
- #move(source) ⇒ Object
-
#size ⇒ Object
Provides the size of the data buffer for this
zmq_msg_t
C struct.
Methods included from Util
#errno, #error_string, #version
Constructor Details
#initialize(message = nil) ⇒ Message
Returns a new instance of Message.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/ffi-rzmq/message.rb', line 74 def initialize = nil @state = :uninitialized # allocate our own pointer so that we can tell it to *not* zero out # the memory; it's pointless work since the library is going to # overwrite it anyway. @pointer = FFI::MemoryPointer.new LibZMQ::Msg.size, 1, false @struct = LibZMQ::Msg.new @pointer if copy_in_string else # initialize an empty message structure to receive a message result_code = LibZMQ.zmq_msg_init @struct error_check ZMQ_MSG_INIT_STR, result_code @state = :initialized end end |
Instance Method Details
#address ⇒ Object Also known as: pointer
Provides the memory address of the zmq_msg_t
struct. Used mostly for passing to other methods accessing the underlying library that require a real data address.
131 132 133 |
# File 'lib/ffi-rzmq/message.rb', line 131 def address @struct.pointer end |
#close ⇒ Object
Manually release the message struct and its associated data buffer.
The Message object is still valid after this call and can be used again for sending or receiving.
177 178 179 180 181 |
# File 'lib/ffi-rzmq/message.rb', line 177 def close LibZMQ.zmq_msg_close @struct.pointer remove_finalizer @state = :uninitialized end |
#copy(source) ⇒ Object
136 137 138 139 140 |
# File 'lib/ffi-rzmq/message.rb', line 136 def copy source result_code = LibZMQ.zmq_msg_copy @struct.pointer, source.address error_check ZMQ_MSG_COPY_STR, result_code @state = :initialized end |
#copy_in_bytes(bytes, len) ⇒ Object
Makes a copy of len
bytes from the ruby string bytes
. Library handles deallocation of the native memory buffer.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/ffi-rzmq/message.rb', line 104 def copy_in_bytes bytes, len # release any associated buffers if this Message object is being # reused close unless uninitialized? # FIXME: this is a bug waiting to happen data_buffer = LibC.malloc len # writes the exact number of bytes, no null byte to terminate string data_buffer.write_string bytes, len # make sure we have a way to deallocate this memory if the object goes # out of scope define_finalizer unless RBX result_code = LibZMQ.zmq_msg_init_data @struct.pointer, data_buffer, len, LibZMQ::MessageDeallocator, nil else # no callback for freeing up memory; memory leak! result_code = LibZMQ.zmq_msg_init_data @struct.pointer, data_buffer, len, nil, nil end error_check ZMQ_MSG_INIT_DATA_STR, result_code @state = :initialized end |
#copy_in_string(string) ⇒ Object
Makes a copy of the ruby string
into a native memory buffer so that libzmq can send it. The underlying library will handle deallocation of the native memory buffer.
97 98 99 |
# File 'lib/ffi-rzmq/message.rb', line 97 def copy_in_string string copy_in_bytes string, string.size if string end |
#copy_out_string ⇒ Object
Returns the data buffer as a string.
Note: If this is binary data, it won’t print very prettily.
167 168 169 |
# File 'lib/ffi-rzmq/message.rb', line 167 def copy_out_string data.read_string(size) end |
#data ⇒ Object
Returns a pointer to the data buffer. This pointer should never be freed. It will automatically be freed when the message
object goes out of scope and gets garbage collected.
159 160 161 |
# File 'lib/ffi-rzmq/message.rb', line 159 def data LibZMQ.zmq_msg_data @struct.pointer end |
#move(source) ⇒ Object
142 143 144 145 146 |
# File 'lib/ffi-rzmq/message.rb', line 142 def move source result_code = LibZMQ.zmq_msg_copy @struct.pointer, source.address error_check ZMQ_MSG_MOVE_STR, result_code @state = :initialized end |
#size ⇒ Object
Provides the size of the data buffer for this zmq_msg_t
C struct.
150 151 152 |
# File 'lib/ffi-rzmq/message.rb', line 150 def size LibZMQ.zmq_msg_size @struct.pointer end |