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


16
17
18
19
# File 'lib/cztop/frame.rb', line 16

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:


69
70
71
# File 'lib/cztop/frame.rb', line 69

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


132
133
134
# File 'lib/cztop/frame.rb', line 132

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)


75
76
77
# File 'lib/cztop/frame.rb', line 75

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)

88
89
90
91
92
93
# File 'lib/cztop/frame.rb', line 88

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


97
98
99
# File 'lib/cztop/frame.rb', line 97

def dup
  from_ffi_delegate(ffi_delegate.dup)
end

#empty?Boolean

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

Returns:


81
82
83
# File 'lib/cztop/frame.rb', line 81

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


163
164
165
166
167
# File 'lib/cztop/frame.rb', line 163

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


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

def group=(new_group)
  rc = ffi_delegate.set_group(new_group)
  raise_zmq_err("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:


113
114
115
# File 'lib/cztop/frame.rb', line 113

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


104
105
106
# File 'lib/cztop/frame.rb', line 104

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


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

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


151
152
153
154
155
156
# File 'lib/cztop/frame.rb', line 151

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 < 0
  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.


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

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
    if dontwait && FFI.errno == Errno::EAGAIN::Errno
      raise IO::EAGAINWaitWritable
    end

    raise_zmq_err
  end
end

#sizeInteger

Returns content length in bytes.

Returns:

  • (Integer)

    content length in bytes


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

ffi_delegate :size