ffi-rzmq 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.bnsignore +22 -0
- data/History.txt +36 -0
- data/README.rdoc +18 -22
- data/Rakefile +22 -5
- data/examples/local_lat_poll.rb +54 -0
- data/ffi-rzmq.gemspec +9 -9
- data/lib/ffi-rzmq/context.rb +1 -1
- data/lib/ffi-rzmq/poll.rb +7 -1
- data/lib/ffi-rzmq/socket.rb +75 -21
- data/lib/ffi-rzmq/wrapper.rb +8 -6
- data/lib/ffi-rzmq/zmq.rb +27 -1
- data/spec/context_spec.rb +7 -34
- data/spec/pushpull_spec.rb +16 -19
- data/spec/reqrep_spec.rb +5 -0
- data/spec/socket_spec.rb +249 -109
- data/spec/spec_helper.rb +3 -13
- data/version.txt +1 -1
- metadata +10 -10
- data/.gitignore +0 -2
- data/examples/xreqxrep_poll.rb +0 -82
data/.bnsignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# The list of files that should be ignored by Mr Bones.
|
2
|
+
# Lines that start with '#' are comments.
|
3
|
+
#
|
4
|
+
# A .gitignore file can be used instead by setting it as the ignore
|
5
|
+
# file in your Rakefile:
|
6
|
+
#
|
7
|
+
# Bones {
|
8
|
+
# ignore_file '.gitignore'
|
9
|
+
# }
|
10
|
+
#
|
11
|
+
# For a project with a C extension, the following would be a good set of
|
12
|
+
# exclude patterns (uncomment them if you want to use them):
|
13
|
+
# *.[oa]
|
14
|
+
# *~
|
15
|
+
announcement.txt
|
16
|
+
coverage
|
17
|
+
doc
|
18
|
+
pkg
|
19
|
+
*.tmproj
|
20
|
+
*.gem
|
21
|
+
*.rbc
|
22
|
+
*.html
|
data/History.txt
CHANGED
@@ -1,3 +1,39 @@
|
|
1
|
+
== 0.7.0 / 20101222
|
2
|
+
* Improved performance of calls to Socket#getsockopt. There are usually
|
3
|
+
a lot of calls passing RCVMORE, so we now cache those buffers instead
|
4
|
+
of reallocating them every time.
|
5
|
+
|
6
|
+
* Updated the docs on Poller#poll to warn about a possible busy-loop
|
7
|
+
condition.
|
8
|
+
|
9
|
+
* Fixed some more specs to conform with the 0mq 2.1 requirement that
|
10
|
+
all sockets must be closed explicitly otherwise the program may
|
11
|
+
hang on exit.
|
12
|
+
|
13
|
+
== 0.6.1 / 20101127
|
14
|
+
* API Change!
|
15
|
+
Moved the #version method from the Util module and made it a class
|
16
|
+
method instead. Invoke as ZMQ::Util.version. Used for conditionally
|
17
|
+
enabling certain features based upon the 0mq version that is loaded.
|
18
|
+
|
19
|
+
* Preliminary support for the Windows platform. Patches supplied
|
20
|
+
by arvicco.
|
21
|
+
|
22
|
+
* Added support for FD and EVENTS socket options. These were added
|
23
|
+
in 0mq 2.1.0. Patches + specs supplied by andrewvc.
|
24
|
+
|
25
|
+
* Added support for LINGER, RECONNECT_IVL, BACKLOG and
|
26
|
+
RECOVERY_IVL_MSEC socket options.
|
27
|
+
|
28
|
+
* Conditionally re-enable the socket finalizer when we are running
|
29
|
+
with 0mq 2.1.0 or later.
|
30
|
+
|
31
|
+
* Drop support for MRI 1.8.x since the 'ffi' gem has dropped it as a
|
32
|
+
supported Ruby runtime with its 1.0 release. No action is taken to
|
33
|
+
prevent running with MRI 1.8.x but it won't be supported.
|
34
|
+
|
35
|
+
* Misc. spec fixes. Need more specs!
|
36
|
+
|
1
37
|
== 0.6.0 / 20100911
|
2
38
|
* API Change! Modified ZMQ::Message by removing automatic memory
|
3
39
|
management. While doing some performance tests I saw that
|
data/README.rdoc
CHANGED
@@ -7,10 +7,10 @@ ffi-rzmq
|
|
7
7
|
This gem wraps the ZeroMQ networking library using the ruby FFI (foreign
|
8
8
|
function interface). It's a pure ruby wrapper so this gem can be loaded
|
9
9
|
and run by any ruby runtime that supports FFI. That's all of them:
|
10
|
-
MRI 1.
|
10
|
+
MRI 1.9.x, Rubinius and JRuby.
|
11
11
|
|
12
12
|
The impetus behind this library was to provide support for ZeroMQ in
|
13
|
-
JRuby which has native threads. Unlike MRI,
|
13
|
+
JRuby which has native threads. Unlike MRI, IronRuby and
|
14
14
|
Rubinius which all have a GIL, JRuby allows for threaded access to ruby
|
15
15
|
code from outside extensions. ZeroMQ is heavily threaded, so until the
|
16
16
|
other runtimes remove their GIL, JRuby will likely be the best
|
@@ -28,18 +28,9 @@ This gem needs more tests. I'm certain there are a
|
|
28
28
|
ton of bugs, so please open issues for them here or fork this project,
|
29
29
|
fix them, and send me a pull request.
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
Ruby FFI project) so tread carefully.
|
35
|
-
|
36
|
-
Running this gem with MRI 1.9.x may also exhibit some hangs particularly at
|
37
|
-
shutdown. This is due to a signaling interaction between the 0mq library
|
38
|
-
and MRI. If the 0mq library is blocked on a call and the program receives
|
39
|
-
a signal (e.g. SIGINT), the Ruby runtime has no opportunity to run its signal
|
40
|
-
handler and process it. The 2.1.x branch of 0mq resolves this problem by
|
41
|
-
interrupting the blocking call and returning EINTR. The 2.0.x branch will
|
42
|
-
not get this fix because the API change breaks backward compatibility.
|
31
|
+
The 'ffi' gem has dropped support for MRI 1.8.x. Since this project relies
|
32
|
+
on that gem to load and run this code, then this project also no longer
|
33
|
+
supports MRI 1.8.x.
|
43
34
|
|
44
35
|
All features are implemented with the exception of the 0mq devices
|
45
36
|
(forwarder, queue, streamer). For implementations of these devices, see
|
@@ -104,10 +95,18 @@ Server code:
|
|
104
95
|
msg = s.recv_string 0
|
105
96
|
raise "Message size doesn't match, expected [#{message_size}] but received [#{msg.size}]" if message_size != msg.size
|
106
97
|
end
|
98
|
+
|
99
|
+
== Better Examples
|
100
|
+
|
101
|
+
I highly recommend visiting the Learn Ruby 0mq project for a bunch of good code examples.
|
102
|
+
|
103
|
+
http://github.com/andrewvc/learn-ruby-zeromq
|
104
|
+
|
105
|
+
|
107
106
|
|
108
107
|
== REQUIREMENTS:
|
109
108
|
|
110
|
-
* 0mq 2.0.
|
109
|
+
* 0mq 2.0.10 or 2.1+
|
111
110
|
|
112
111
|
The ZeroMQ library must be installed on your system in a well-known location
|
113
112
|
like /usr/local/lib. This is the default for new ZeroMQ installs.
|
@@ -115,15 +114,12 @@ like /usr/local/lib. This is the default for new ZeroMQ installs.
|
|
115
114
|
Future releases may include the library as a C extension built at
|
116
115
|
time of installation.
|
117
116
|
|
118
|
-
* ffi (
|
117
|
+
* ffi (>= 1.0.0)
|
119
118
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
Code and installation instructions can be found on github:
|
119
|
+
This is a requirement for MRI only. Both Rubinius and JRuby have FFI support built
|
120
|
+
in as a standard component. Do *not* run this gem under MRI with an old 'ffi' gem.
|
121
|
+
It will crash randomly and you will be sad.
|
125
122
|
|
126
|
-
http://github.com/ffi/ffi
|
127
123
|
|
128
124
|
== INSTALL:
|
129
125
|
|
data/Rakefile
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
begin
|
3
2
|
require 'bones'
|
4
3
|
rescue LoadError
|
@@ -8,12 +7,30 @@ end
|
|
8
7
|
task :default => 'test:run'
|
9
8
|
task 'gem:release' => 'test:run'
|
10
9
|
|
10
|
+
namespace :win do
|
11
|
+
|
12
|
+
desc 'Build and install gem under Windows. Mr Bones just has to break things using tar.'
|
13
|
+
task :install do
|
14
|
+
PKG_PATH = File.join(File.dirname(__FILE__), 'pkg')
|
15
|
+
NAME = File.basename(File.dirname(__FILE__))
|
16
|
+
rm_rf PKG_PATH
|
17
|
+
system "gem build #{NAME}.gemspec"
|
18
|
+
mkdir_p PKG_PATH
|
19
|
+
mv "#{NAME}-0.6.0.gem", PKG_PATH
|
20
|
+
system "gem install #{PKG_PATH}/#{NAME}-0.6.0.gem"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
11
24
|
Bones {
|
12
|
-
name
|
13
|
-
authors
|
14
|
-
email
|
15
|
-
url
|
25
|
+
name 'ffi-rzmq'
|
26
|
+
authors 'Chuck Remes'
|
27
|
+
email 'cremes@mac.com'
|
28
|
+
url 'http://github.com/chuckremes/ffi-rzmq'
|
16
29
|
readme_file 'README.rdoc'
|
17
30
|
ruby_opts.clear # turn off warnings
|
31
|
+
|
32
|
+
# necessary for MRI; unnecessary for JRuby and RBX
|
33
|
+
# can't enable this until JRuby & RBX have a way of dealing with it cleanly
|
34
|
+
#depend_on 'ffi', '>= 1.0.0'
|
18
35
|
}
|
19
36
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ffi-rzmq'
|
3
|
+
|
4
|
+
if ARGV.length < 3
|
5
|
+
puts "usage: local_lat <connect-to> <message-size> <roundtrip-count>"
|
6
|
+
exit
|
7
|
+
end
|
8
|
+
|
9
|
+
link = ARGV[0]
|
10
|
+
message_size = ARGV[1].to_i
|
11
|
+
roundtrip_count = ARGV[2].to_i
|
12
|
+
|
13
|
+
#link = "tcp://127.0.0.1:5555"
|
14
|
+
|
15
|
+
ctx = ZMQ::Context.new
|
16
|
+
s1 = ctx.socket ZMQ::REQ
|
17
|
+
s2 = ctx.socket ZMQ::REP
|
18
|
+
|
19
|
+
s1.connect link
|
20
|
+
s2.bind link
|
21
|
+
|
22
|
+
poller = ZMQ::Poller.new
|
23
|
+
poller.register_readable s2
|
24
|
+
poller.register_readable s1
|
25
|
+
|
26
|
+
|
27
|
+
start_time = Time.now
|
28
|
+
|
29
|
+
# kick it off
|
30
|
+
message = ZMQ::Message.new("a" * message_size)
|
31
|
+
s1.send message, ZMQ::NOBLOCK
|
32
|
+
i = roundtrip_count
|
33
|
+
|
34
|
+
until i.zero?
|
35
|
+
i -= 1
|
36
|
+
|
37
|
+
begin
|
38
|
+
poller.poll_nonblock
|
39
|
+
rescue ZMQ::PollError => e
|
40
|
+
puts "efault? [#{e.efault?}]"
|
41
|
+
raise
|
42
|
+
end
|
43
|
+
|
44
|
+
poller.readables.each do |socket|
|
45
|
+
received_message = socket.recv_string ZMQ::NOBLOCK
|
46
|
+
socket.send ZMQ::Message.new(received_message), ZMQ::NOBLOCK
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
elapsed_usecs = (Time.now.to_f - start_time.to_f) * 1_000_000
|
51
|
+
latency = elapsed_usecs / roundtrip_count / 2
|
52
|
+
|
53
|
+
puts "mean latency: %.3f [us]" % latency
|
54
|
+
puts "received all messages in %.3f seconds" % (elapsed_usecs / 1_000_000)
|
data/ffi-rzmq.gemspec
CHANGED
@@ -2,42 +2,42 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{ffi-rzmq}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.7.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Chuck Remes"]
|
9
|
-
s.date = %q{2010-
|
9
|
+
s.date = %q{2010-12-22}
|
10
10
|
s.description = %q{This gem wraps the ZeroMQ networking library using the ruby FFI (foreign
|
11
11
|
function interface). It's a pure ruby wrapper so this gem can be loaded
|
12
12
|
and run by any ruby runtime that supports FFI. That's all of them:
|
13
|
-
MRI 1.
|
13
|
+
MRI 1.9.x, Rubinius and JRuby.
|
14
14
|
|
15
15
|
The impetus behind this library was to provide support for ZeroMQ in
|
16
|
-
JRuby which has native threads. Unlike MRI,
|
16
|
+
JRuby which has native threads. Unlike MRI, IronRuby and
|
17
17
|
Rubinius which all have a GIL, JRuby allows for threaded access to ruby
|
18
18
|
code from outside extensions. ZeroMQ is heavily threaded, so until the
|
19
19
|
other runtimes remove their GIL, JRuby will likely be the best
|
20
20
|
environment to run this library.}
|
21
21
|
s.email = %q{cremes@mac.com}
|
22
22
|
s.extra_rdoc_files = ["History.txt", "README.rdoc", "examples/README.rdoc", "version.txt"]
|
23
|
-
s.files = [".
|
23
|
+
s.files = [".bnsignore", "History.txt", "README.rdoc", "Rakefile", "examples/README.rdoc", "examples/local_lat.rb", "examples/local_lat_poll.rb", "examples/local_lat_zerocopy.rb", "examples/local_throughput.rb", "examples/publish_subscribe.rb", "examples/remote_lat.rb", "examples/remote_lat_zerocopy.rb", "examples/remote_throughput.rb", "examples/reqrep_poll.rb", "examples/request_response.rb", "ffi-rzmq.gemspec", "lib/ffi-rzmq.rb", "lib/ffi-rzmq/context.rb", "lib/ffi-rzmq/exceptions.rb", "lib/ffi-rzmq/message.rb", "lib/ffi-rzmq/poll.rb", "lib/ffi-rzmq/poll_items.rb", "lib/ffi-rzmq/socket.rb", "lib/ffi-rzmq/wrapper.rb", "lib/ffi-rzmq/zmq.rb", "spec/context_spec.rb", "spec/message_spec.rb", "spec/pushpull_spec.rb", "spec/reqrep_spec.rb", "spec/socket_spec.rb", "spec/spec_helper.rb", "version.txt"]
|
24
24
|
s.homepage = %q{http://github.com/chuckremes/ffi-rzmq}
|
25
25
|
s.rdoc_options = ["--main", "README.rdoc"]
|
26
26
|
s.require_paths = ["lib"]
|
27
27
|
s.rubyforge_project = %q{ffi-rzmq}
|
28
28
|
s.rubygems_version = %q{1.3.7}
|
29
|
-
s.summary = %q{This gem wraps the ZeroMQ networking library using the ruby FFI (foreign function interface)}
|
29
|
+
s.summary = %q{This gem wraps the ZeroMQ networking library using the ruby FFI (foreign function interface).}
|
30
30
|
|
31
31
|
if s.respond_to? :specification_version then
|
32
32
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
33
33
|
s.specification_version = 3
|
34
34
|
|
35
35
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
36
|
-
s.add_development_dependency(%q<bones>, [">= 3.4
|
36
|
+
s.add_development_dependency(%q<bones>, [">= 3.5.4"])
|
37
37
|
else
|
38
|
-
s.add_dependency(%q<bones>, [">= 3.4
|
38
|
+
s.add_dependency(%q<bones>, [">= 3.5.4"])
|
39
39
|
end
|
40
40
|
else
|
41
|
-
s.add_dependency(%q<bones>, [">= 3.4
|
41
|
+
s.add_dependency(%q<bones>, [">= 3.5.4"])
|
42
42
|
end
|
43
43
|
end
|
data/lib/ffi-rzmq/context.rb
CHANGED
data/lib/ffi-rzmq/poll.rb
CHANGED
@@ -28,6 +28,12 @@ module ZMQ
|
|
28
28
|
# registered sockets belongs to an application thread in another
|
29
29
|
# Context.
|
30
30
|
#
|
31
|
+
# This method will return *immediately* when there are no registered
|
32
|
+
# sockets. In that case, the +timeout+ parameter is not honored. To
|
33
|
+
# prevent a CPU busy-loop, the caller of this method should detect
|
34
|
+
# this possible condition (via #size) and throttle the call
|
35
|
+
# frequency.
|
36
|
+
#
|
31
37
|
def poll timeout = :blocking
|
32
38
|
unless @items.empty?
|
33
39
|
timeout = adjust timeout
|
@@ -178,7 +184,7 @@ module ZMQ
|
|
178
184
|
if :blocking == timeout || -1 == timeout
|
179
185
|
-1
|
180
186
|
else
|
181
|
-
timeout
|
187
|
+
(timeout * 1000).to_i
|
182
188
|
end
|
183
189
|
end
|
184
190
|
end
|
data/lib/ffi-rzmq/socket.rb
CHANGED
@@ -27,7 +27,7 @@ module ZMQ
|
|
27
27
|
#
|
28
28
|
# sock = Socket.new(Context.new, ZMQ::REQ, :receiver_class => ZMQ::ManagedMessage)
|
29
29
|
#
|
30
|
-
# Advanced users may want to replace the receiver class with their
|
30
|
+
# Advanced users may want to replace the receiver class with their
|
31
31
|
# own custom class. The custom class must conform to the same public API
|
32
32
|
# as ZMQ::Message.
|
33
33
|
#
|
@@ -43,13 +43,19 @@ module ZMQ
|
|
43
43
|
|
44
44
|
unless context_ptr.null?
|
45
45
|
@socket = LibZMQ.zmq_socket context_ptr, type
|
46
|
-
|
47
|
-
|
46
|
+
if @socket
|
47
|
+
error_check ZMQ_SOCKET_STR, @socket.null? ? 1 : 0
|
48
|
+
@name = SocketTypeNameMap[type]
|
49
|
+
else
|
50
|
+
raise ContextError.new ZMQ_SOCKET_STR, 0, ETERM, "Socket pointer was null"
|
51
|
+
end
|
48
52
|
else
|
49
53
|
raise ContextError.new ZMQ_SOCKET_STR, 0, ETERM, "Context pointer was null"
|
50
54
|
end
|
51
55
|
|
52
|
-
|
56
|
+
@sockopt_cache = {}
|
57
|
+
|
58
|
+
define_finalizer
|
53
59
|
end
|
54
60
|
|
55
61
|
# Set the queue options on this socket.
|
@@ -61,6 +67,10 @@ module ZMQ
|
|
61
67
|
# ZMQ::RATE
|
62
68
|
# ZMQ::RECOVERY_IVL
|
63
69
|
# ZMQ::MCAST_LOOP
|
70
|
+
# ZMQ::LINGER
|
71
|
+
# ZMQ::RECONNECT_IVL
|
72
|
+
# ZMQ::BACKLOG
|
73
|
+
# ZMQ::RECOVER_IVL_MSEC
|
64
74
|
#
|
65
75
|
# Valid +option_name+ values that take a string +option_value+ are:
|
66
76
|
# ZMQ::IDENTITY
|
@@ -75,13 +85,18 @@ module ZMQ
|
|
75
85
|
def setsockopt option_name, option_value, option_len = nil
|
76
86
|
option_value = sanitize_value option_name, option_value
|
77
87
|
option_len ||= option_value.size
|
78
|
-
|
88
|
+
|
79
89
|
begin
|
80
90
|
case option_name
|
81
|
-
when HWM, SWAP, AFFINITY, RATE, RECOVERY_IVL, MCAST_LOOP, SNDBUF, RCVBUF
|
91
|
+
when HWM, SWAP, AFFINITY, RATE, RECOVERY_IVL, MCAST_LOOP, SNDBUF, RCVBUF, RECOVERY_IVL_MSEC
|
82
92
|
option_value_ptr = LibC.malloc option_len
|
83
93
|
option_value_ptr.write_long option_value
|
84
94
|
|
95
|
+
when LINGER, RECONNECT_IVL, BACKLOG
|
96
|
+
option_len = 4 # hard-code "int" length to 4 bytes
|
97
|
+
option_value_ptr = LibC.malloc option_len
|
98
|
+
option_value_ptr.write_int option_value
|
99
|
+
|
85
100
|
when IDENTITY, SUBSCRIBE, UNSUBSCRIBE
|
86
101
|
# note: not checking errno for failed memory allocations :(
|
87
102
|
option_value_ptr = LibC.malloc option_len
|
@@ -114,6 +129,12 @@ module ZMQ
|
|
114
129
|
# ZMQ::MCAST_LOOP - boolean
|
115
130
|
# ZMQ::SNDBUF - integer
|
116
131
|
# ZMQ::RCVBUF - integer
|
132
|
+
# ZMQ::FD - fd in an integer
|
133
|
+
# ZMQ::EVENTS - bitmap integer
|
134
|
+
# ZMQ::LINGER - integer measured in milliseconds
|
135
|
+
# ZMQ::RECONNECT_IVL - integer measured in milliseconds
|
136
|
+
# ZMQ::BACKLOG - integer
|
137
|
+
# ZMQ::RECOVER_IVL_MSEC - integer measured in milliseconds
|
117
138
|
#
|
118
139
|
# Can raise two kinds of exceptions depending on the error.
|
119
140
|
# ContextError:: Raised when a socket operation is attempted on a terminated
|
@@ -125,8 +146,10 @@ module ZMQ
|
|
125
146
|
option_value = FFI::MemoryPointer.new :pointer
|
126
147
|
option_length = FFI::MemoryPointer.new :size_t
|
127
148
|
|
128
|
-
unless [
|
129
|
-
|
149
|
+
unless [
|
150
|
+
RCVMORE, HWM, SWAP, AFFINITY, RATE, RECOVERY_IVL, MCAST_LOOP, IDENTITY,
|
151
|
+
SNDBUF, RCVBUF, FD, EVENTS, LINGER, RECONNECT_IVL, BACKLOG, RECOVERY_IVL_MSEC
|
152
|
+
].include? option_name
|
130
153
|
# we didn't understand the passed option argument
|
131
154
|
# will force a raise
|
132
155
|
error_check ZMQ_SETSOCKOPT_STR, -1
|
@@ -142,8 +165,10 @@ module ZMQ
|
|
142
165
|
when RCVMORE, MCAST_LOOP
|
143
166
|
# boolean return
|
144
167
|
ret = option_value.read_long_long != 0
|
145
|
-
when HWM, SWAP, AFFINITY, RATE, RECOVERY_IVL, SNDBUF, RCVBUF
|
168
|
+
when HWM, SWAP, AFFINITY, RATE, RECOVERY_IVL, SNDBUF, RCVBUF, RECOVERY_IVL_MSEC
|
146
169
|
ret = option_value.read_long_long
|
170
|
+
when LINGER, RECONNECT_IVL, BACKLOG, FD, EVENTS
|
171
|
+
ret = option_value.read_int
|
147
172
|
when IDENTITY
|
148
173
|
ret = option_value.read_string(option_length.read_long_long)
|
149
174
|
end
|
@@ -192,12 +217,16 @@ module ZMQ
|
|
192
217
|
error_check ZMQ_CONNECT_STR, result_code
|
193
218
|
end
|
194
219
|
|
195
|
-
# Closes the socket. Any unprocessed messages in queue are dropped
|
220
|
+
# Closes the socket. Any unprocessed messages in queue are sent or dropped
|
221
|
+
# depending upon the value of the socket option ZMQ::LINGER.
|
196
222
|
#
|
197
223
|
def close
|
198
|
-
|
199
|
-
|
200
|
-
|
224
|
+
if @socket
|
225
|
+
remove_finalizer
|
226
|
+
result_code = LibZMQ.zmq_close @socket
|
227
|
+
error_check ZMQ_CLOSE_STR, result_code
|
228
|
+
@socket = nil
|
229
|
+
end
|
201
230
|
end
|
202
231
|
|
203
232
|
# Queues the message for transmission. Message is assumed to conform to the
|
@@ -326,21 +355,37 @@ module ZMQ
|
|
326
355
|
flags != NOBLOCK ? error_check(ZMQ_RECV_STR, result_code) : error_check_nonblock(result_code)
|
327
356
|
end
|
328
357
|
|
358
|
+
# Calls to ZMQ.getsockopt require us to pass in some pointers. We can cache and save those buffers
|
359
|
+
# for subsequent calls. This is a big perf win for calling RCVMORE which happens quite often.
|
360
|
+
# Cannot save the buffer for the IDENTITY.
|
329
361
|
def alloc_temp_sockopt_buffers option_name
|
330
|
-
length = FFI::MemoryPointer.new :int64
|
331
|
-
|
332
362
|
case option_name
|
333
|
-
when RCVMORE, MCAST_LOOP, HWM, SWAP, AFFINITY, RATE, RECOVERY_IVL, SNDBUF, RCVBUF
|
363
|
+
when RCVMORE, MCAST_LOOP, HWM, SWAP, AFFINITY, RATE, RECOVERY_IVL, SNDBUF, RCVBUF, RECOVERY_IVL_MSEC
|
334
364
|
# int64_t
|
335
|
-
|
336
|
-
|
365
|
+
unless @sockopt_cache[:int64]
|
366
|
+
length = FFI::MemoryPointer.new :int64
|
367
|
+
length.write_long_long 8
|
368
|
+
@sockopt_cache[:int64] = [FFI::MemoryPointer.new(:int64), length]
|
369
|
+
end
|
370
|
+
@sockopt_cache[:int64]
|
371
|
+
|
372
|
+
when LINGER, RECONNECT_IVL, BACKLOG, FD, EVENTS
|
373
|
+
# int, 0mq assumes int is 4-bytes
|
374
|
+
unless @sockopt_cache[:int32]
|
375
|
+
length = FFI::MemoryPointer.new :int32
|
376
|
+
length.write_int 4
|
377
|
+
@sockopt_cache[:int32] = [FFI::MemoryPointer.new(:int32), length]
|
378
|
+
end
|
379
|
+
@sockopt_cache[:int32]
|
380
|
+
|
337
381
|
when IDENTITY
|
382
|
+
length = FFI::MemoryPointer.new :int64
|
338
383
|
# could be a string of up to 255 bytes
|
339
384
|
length.write_long_long 255
|
340
385
|
[FFI::MemoryPointer.new(255), length]
|
341
386
|
end
|
342
387
|
end
|
343
|
-
|
388
|
+
|
344
389
|
def sanitize_value option_name, option_value
|
345
390
|
case option_name
|
346
391
|
when HWM, AFFINITY, SNDBUF, RCVBUF
|
@@ -352,8 +397,17 @@ module ZMQ
|
|
352
397
|
end
|
353
398
|
end
|
354
399
|
|
355
|
-
|
356
|
-
|
400
|
+
# require a minimum of 0mq 2.1.0 to support socket finalizers; it contains important
|
401
|
+
# fixes for sockets and threads so that a garbage collector thread can successfully
|
402
|
+
# reap this resource without crashing
|
403
|
+
if Util.minimum_api?([2, 1, 0])
|
404
|
+
def define_finalizer
|
405
|
+
ObjectSpace.define_finalizer(self, self.class.close(@socket))
|
406
|
+
end
|
407
|
+
else
|
408
|
+
def define_finalizer
|
409
|
+
# no op
|
410
|
+
end
|
357
411
|
end
|
358
412
|
|
359
413
|
def remove_finalizer
|