lib/ffi-rzmq/socket.rb in ffi-rzmq-0.9.2 vs lib/ffi-rzmq/socket.rb in ffi-rzmq-0.9.3
- old
+ new
@@ -80,11 +80,13 @@
end
else
raise ContextError.new 'zmq_socket', 0, ETERM, "Context pointer was null"
end
- @sockopt_cache = {}
+ @more_parts_array = []
+ @option_lookup = []
+ populate_option_lookup
define_finalizer
end
# Set the queue options on this socket.
@@ -121,21 +123,21 @@
#
# rc = socket.setsockopt(ZMQ::LINGER, 1_000)
# ZMQ::Util.resultcode_ok?(rc) ? puts("succeeded") : puts("failed")
#
def setsockopt name, value, length = nil
- if long_long_option?(name)
+ if 1 == @option_lookup[name]
length = 8
pointer = LibC.malloc length
pointer.write_long_long value
- elsif int_option?(name)
+ elsif 0 == @option_lookup[name]
length = 4
pointer = LibC.malloc length
pointer.write_int value
- elsif string_option?(name)
+ elsif 2 == @option_lookup[name]
length ||= value.size
# note: not checking errno for failed memory allocations :(
pointer = LibC.malloc length
pointer.write_string value
@@ -164,14 +166,13 @@
# message_parts.push(message) if resulcode_ok?(rc)
# end
# end
#
def more_parts?
- array = []
- rc = getsockopt ZMQ::RCVMORE, array
+ rc = getsockopt ZMQ::RCVMORE, @more_parts_array
- Util.resultcode_ok?(rc) ? array.at(0) : false
+ Util.resultcode_ok?(rc) ? @more_parts_array.at(0) : false
end
# Binds the socket to an +address+.
#
# socket.bind("tcp://127.0.0.1:5555")
@@ -211,105 +212,87 @@
private
def __getsockopt__ name, array
- value, length = sockopt_buffers name
+ # a small optimization so we only have to determine the option
+ # type a single time; gives approx 5% speedup to do it this way.
+ option_type = @option_lookup[name]
+
+ value, length = sockopt_buffers option_type
rc = LibZMQ.zmq_getsockopt @socket, name, value, length
if Util.resultcode_ok?(rc)
- result = if int_option?(name)
- value.read_int
- elsif long_long_option?(name)
+ array[0] = if 1 == option_type
value.read_long_long
- elsif string_option?(name)
+ elsif 0 == option_type
+ value.read_int
+ elsif 2 == option_type
value.read_string(length.read_int)
end
-
- array << result
end
rc
end
# Calls to ZMQ.getsockopt require us to pass in some pointers. We can cache and save those buffers
# for subsequent calls. This is a big perf win for calling RCVMORE which happens quite often.
# Cannot save the buffer for the IDENTITY.
- def sockopt_buffers name
- if long_long_option?(name)
+ def sockopt_buffers option_type
+ if 1 == option_type
# int64_t or uint64_t
- unless @sockopt_cache[:int64]
+ unless @longlong_cache
length = FFI::MemoryPointer.new :size_t
length.write_int 8
- @sockopt_cache[:int64] = [FFI::MemoryPointer.new(:int64), length]
+ @longlong_cache = [FFI::MemoryPointer.new(:int64), length]
end
- @sockopt_cache[:int64]
+ @longlong_cache
- elsif int_option?(name)
+ elsif 0 == option_type
# int, 0mq assumes int is 4-bytes
- unless @sockopt_cache[:int32]
+ unless @int_cache
length = FFI::MemoryPointer.new :size_t
length.write_int 4
- @sockopt_cache[:int32] = [FFI::MemoryPointer.new(:int32), length]
+ @int_cache = [FFI::MemoryPointer.new(:int32), length]
end
- @sockopt_cache[:int32]
+ @int_cache
- elsif string_option?(name)
+ elsif 2 == option_type
length = FFI::MemoryPointer.new :size_t
# could be a string of up to 255 bytes
length.write_int 255
[FFI::MemoryPointer.new(255), length]
else
# uh oh, someone passed in an unknown option; use a slop buffer
- unless @sockopt_cache[:unknown]
+ unless @int_cache
length = FFI::MemoryPointer.new :size_t
length.write_int 4
- @sockopt_cache[:unknown] = [FFI::MemoryPointer.new(:int32), length]
+ @int_cache = [FFI::MemoryPointer.new(:int32), length]
end
- @sockopt_cache[:unknown]
+ @int_cache
end
end
+
+ def populate_option_lookup
+ # integer options
+ [EVENTS, LINGER, RECONNECT_IVL, FD, TYPE, BACKLOG].each { |option| @option_lookup[option] = 0 }
- def supported_option? name
- int_option?(name) || long_long_option?(name) || string_option?(name)
+ # long long options
+ [RCVMORE, AFFINITY].each { |option| @option_lookup[option] = 1 }
+
+ # string options
+ [SUBSCRIBE, UNSUBSCRIBE].each { |option| @option_lookup[option] = 2 }
end
- def int_option? name
- EVENTS == name ||
- LINGER == name ||
- RECONNECT_IVL == name ||
- FD == name ||
- TYPE == name ||
- BACKLOG == name
- end
-
- def string_option? name
- SUBSCRIBE == name ||
- UNSUBSCRIBE == name
- end
-
- def long_long_option? name
- RCVMORE == name ||
- AFFINITY == name
- end
-
- def unsupported_setsock_option? name
- RCVMORE == name
- end
-
- def unsupported_getsock_option? name
- UNSUBSCRIBE == name ||
- SUBSCRIBE == name
- end
-
def release_cache
- @sockopt_cache.clear
+ @longlong_cache = nil
+ @int_cache = nil
end
end # module CommonSocketBehavior
module IdentitySupport
@@ -328,15 +311,18 @@
setsockopt IDENTITY, value.to_s
end
private
-
- def string_option? name
- super ||
- IDENTITY == name
+
+ def populate_option_lookup
+ super()
+
+ # string options
+ [IDENTITY].each { |option| @option_lookup[option] = 2 }
end
+
end # module IdentitySupport
if LibZMQ.version2?
@@ -656,28 +642,21 @@
private
def noblock? flags
(NOBLOCK & flags) == NOBLOCK
end
+
+ def populate_option_lookup
+ super()
+
+ # integer options
+ [RECONNECT_IVL_MAX].each { |option| @option_lookup[option] = 0 }
- def int_option? name
- super ||
- RECONNECT_IVL_MAX == name
- end
+ # long long options
+ [HWM, SWAP, RATE, RECOVERY_IVL, RECOVERY_IVL_MSEC, MCAST_LOOP, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 1 }
+ end
- def long_long_option? name
- super ||
- HWM == name ||
- SWAP == name ||
- RATE == name ||
- RECOVERY_IVL == name ||
- RECOVERY_IVL_MSEC == name ||
- MCAST_LOOP == name ||
- SNDBUF == name ||
- RCVBUF == name
- end
-
# these finalizer-related methods cannot live in the CommonSocketBehavior
# module; they *must* be in the class definition directly
def define_finalizer
ObjectSpace.define_finalizer(self, self.class.close(@socket))
@@ -984,18 +963,25 @@
(DONTWAIT & flags) == DONTWAIT
end
alias :noblock? :dontwait?
def int_option? name
- super ||
+ super(name) ||
RECONNECT_IVL_MAX == name ||
RCVHWM == name ||
SNDHWM == name ||
RATE == name ||
RECOVERY_IVL == name ||
SNDBUF == name ||
RCVBUF == name
end
+
+ def populate_option_lookup
+ super()
+
+ # integer options
+ [RECONNECT_IVL_MAX, RCVHWM, SNDHWM, RATE, RECOVERY_IVL, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 0 }
+ end
# these finalizer-related methods cannot live in the CommonSocketBehavior
# module; they *must* be in the class definition directly
def define_finalizer