Class: CZTop::Frame

Inherits:
Object
  • Object
show all
Extended by:
HasFFIDelegate::ClassMethods
Includes:
HasFFIDelegate
Defined in:
lib/cztop/frame.rb

Overview

Note:

Dealing with frames (parts of a message) is pretty low-level. You’ll probably not really need this functionality. It’s only useful when you need to be able to receive and send single frames. Just use Message instead.

Represents a CZMQ::FFI::Zframe, a part of a message.

Constant Summary collapse

FLAG_MORE =
1
FLAG_REUSE =
2
FLAG_DONTWAIT =
4

Instance Attribute Summary

Attributes included from HasFFIDelegate

#ffi_delegate

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HasFFIDelegate::ClassMethods

ffi_delegate, from_ffi_delegate

Methods included from HasFFIDelegate

#attach_ffi_delegate, #from_ffi_delegate, raise_zmq_err, #raise_zmq_err, #to_ptr

Constructor Details

#initialize(content = nil) ⇒ Frame

Initialize a new CZTop::Frame.

Parameters:

  • content (String) (defaults to: nil)

    initial content



19
20
21
22
# File 'lib/cztop/frame.rb', line 19

def initialize(content = nil)
  attach_ffi_delegate(CZMQ::FFI::Zframe.new_empty)
  self.content = content if content
end

Class Method Details

.receive_from(source) ⇒ Frame

Note:

This is low-level. Consider just receiving a Message.

Receive CZTop::Frame from a Socket/Actor.

Returns:



71
72
73
# File 'lib/cztop/frame.rb', line 71

def self.receive_from(source)
  from_ffi_delegate(CZMQ::FFI::Zframe.recv(source))
end

Instance Method Details

#==(other) ⇒ Boolean

Note:

If you need to compare to a string, as zframe_streq() would do, just get this frame’s content first and compare that to the string.

frame = CZTop::Frame.new("foobar")
frame.to_s == "foobar" #=> true
Note:

The #more? flag and the #routing_id are ignored.

Compare to another frame.

Examples:

frame1 = Frame.new("foo")
frame2 = Frame.new("foo")
frame3 = Frame.new("bar")
frame1 == frame2    #=> true
frame1 == frame3    #=> false

Parameters:

Returns:

  • (Boolean)

    if this and the other frame have identical size and data



140
141
142
# File 'lib/cztop/frame.rb', line 140

def ==(other)
  ffi_delegate.eq(other.ffi_delegate)
end

#contentString Also known as: to_s

Note:

This string is always binary. Use String#force_encoding if needed.

Returns content as string (encoding = Encoding::BINARY).

Returns:

  • (String)

    content as string (encoding = Encoding::BINARY)



78
79
80
# File 'lib/cztop/frame.rb', line 78

def content
  ffi_delegate.data.read_string(size)
end

#content=(new_content) ⇒ new_content

Sets new content of this CZTop::Frame.

Parameters:

  • new_content (String)

Returns:

  • (new_content)


92
93
94
95
96
97
# File 'lib/cztop/frame.rb', line 92

def content=(new_content)
  content_ptr = ::FFI::MemoryPointer.new(new_content.bytesize)
  content_ptr.write_bytes(new_content)
  ffi_delegate.reset(content_ptr, content_ptr.size)
  # NOTE: FFI::MemoryPointer will autorelease
end

#dupFrame

Duplicates a frame.

Returns:

  • (Frame)

    new frame with same content



102
103
104
# File 'lib/cztop/frame.rb', line 102

def dup
  from_ffi_delegate(ffi_delegate.dup)
end

#empty?Boolean

Returns if this CZTop::Frame has zero-sized content.

Returns:



84
85
86
# File 'lib/cztop/frame.rb', line 84

def empty?
  size.zero?
end

#groupString?

Note:

This is only set when the frame has been read from a Socket::DISH socket.

Gets the group (radio/dish pattern).

Returns:

  • (String)

    the group

  • (nil)

    when no group has been set



173
174
175
176
177
178
# File 'lib/cztop/frame.rb', line 173

def group
  group = ffi_delegate.group
  return nil if group.nil? || group.empty?

  group
end

#group=(new_group) ⇒ new_group

Note:

This is used when the frame is sent via a Socket::RADIO socket.

Sets a new group (radio/dish pattern).

Parameters:

  • new_group (String)

    new group

Returns:

  • (new_group)

Raises:

  • (ArgumentError)

    if new group name is too long



187
188
189
190
# File 'lib/cztop/frame.rb', line 187

def group=(new_group)
  rc = ffi_delegate.set_group(new_group)
  raise_zmq_err(format('unable to set group to %p', new_group)) if rc == -1
end

#more=(indicator) ⇒ indicator

Note:

This is NOT used when sending frame to socket.

Sets the MORE indicator.

Parameters:

  • indicator (Boolean)

Returns:

  • (indicator)

See Also:



120
121
122
# File 'lib/cztop/frame.rb', line 120

def more=(indicator)
  ffi_delegate.set_more(indicator ? 1 : 0)
end

#more?Boolean

Note:

This happens when reading a frame from a Socket or using #more=.

Returns if the MORE indicator is set.

Returns:

  • (Boolean)

    if the MORE indicator is set



110
111
112
# File 'lib/cztop/frame.rb', line 110

def more?
  ffi_delegate.more == 1
end

#routing_idInteger

Note:

This only set when the frame has been read from a Socket::SERVER socket.

Gets the routing ID.

Returns:

  • (Integer)

    the routing ID, or 0 if unset



151
# File 'lib/cztop/frame.rb', line 151

ffi_delegate :routing_id

#routing_id=(new_routing_id) ⇒ new_routing_id

Note:

This is used when the frame is sent via a Socket::CLIENT socket.

Sets a new routing ID.

Parameters:

  • new_routing_id (Integer)

    new routing ID

Returns:

  • (new_routing_id)

Raises:

  • (RangeError)

    if new routing ID is out of uint32_t range



159
160
161
162
163
164
165
# File 'lib/cztop/frame.rb', line 159

def routing_id=(new_routing_id)
  # need to raise manually, as FFI lacks this feature.
  # @see https://github.com/ffi/ffi/issues/473
  raise RangeError if new_routing_id.negative?

  ffi_delegate.set_routing_id(new_routing_id)
end

#send_to(destination, more: false, reuse: false, dontwait: false) ⇒ void

Note:

If you don’t specify reuse: true, do NOT use this CZTop::Frame anymore afterwards. Its native counterpart will have been destroyed.

Note:

This is low-level. Consider just sending a Message.

This method returns an undefined value.

Send Message to a Socket/Actor.

Parameters:

  • destination (Socket, Actor)

    where to send this Message to

  • more (Boolean) (defaults to: false)

    whether there are more CZTop::Frames to come for the same Message

  • reuse (Boolean) (defaults to: false)

    whether this CZTop::Frame will be used to send to other destinations later

  • dontwait (Boolean) (defaults to: false)

    whether the operation should be performed in non-blocking mode

Raises:

  • (IO::EAGAINWaitWritable)

    if dontwait was set and the operation would have blocked right now

  • (SystemCallError)

    if there was some error. In that case, the native counterpart still exists and this CZTop::Frame can be reused.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/cztop/frame.rb', line 44

def send_to(destination, more: false, reuse: false, dontwait: false)
  flags  = 0
  flags |= FLAG_MORE if more
  flags |= FLAG_REUSE if reuse
  flags |= FLAG_DONTWAIT if dontwait

  # remember pointer, in case the zframe_t won't be destroyed
  zframe_ptr = ffi_delegate.to_ptr
  ret        = CZMQ::FFI::Zframe.send(ffi_delegate, destination, flags)

  if reuse || ret == -1
    # zframe_t hasn't been destroyed yet: avoid memory leak.
    attach_ffi_delegate(CZMQ::FFI::Zframe.__new(zframe_ptr, true))
    # OPTIMIZE: reuse existing Zframe object by redefining its finalizer
  end

  if ret == -1
    raise IO::EAGAINWaitWritable if dontwait && FFI.errno == Errno::EAGAIN::Errno

    raise_zmq_err
  end
end

#sizeInteger

Returns content length in bytes.

Returns:

  • (Integer)

    content length in bytes



145
# File 'lib/cztop/frame.rb', line 145

ffi_delegate :size