ffi-rzmq 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/History.txt +35 -0
- data/README.rdoc +14 -30
- data/examples/README.rdoc +163 -0
- data/examples/local_throughput.rb +43 -0
- data/examples/remote_throughput.rb +27 -0
- data/examples/xreqxrep_poll.rb +1 -1
- data/ffi-rzmq.gemspec +8 -8
- data/lib/ffi-rzmq/context.rb +18 -8
- data/lib/ffi-rzmq/message.rb +112 -48
- data/lib/ffi-rzmq/poll_items.rb +1 -1
- data/lib/ffi-rzmq/socket.rb +43 -19
- data/lib/ffi-rzmq/wrapper.rb +4 -7
- data/lib/ffi-rzmq/zmq.rb +16 -3
- data/spec/context_spec.rb +10 -2
- data/spec/message_spec.rb +42 -0
- data/spec/pushpull_spec.rb +70 -0
- data/spec/socket_spec.rb +192 -13
- data/spec/spec_helper.rb +2 -0
- data/version.txt +1 -1
- metadata +75 -68
- data/.bnsignore +0 -22
- data/examples/async_req_rep.rb +0 -42
- data/examples/t +0 -5228
data/.gitignore
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,38 @@
|
|
1
|
+
== 0.6.0 / 20100911
|
2
|
+
* API Change! Modified ZMQ::Message by removing automatic memory
|
3
|
+
management. While doing some performance tests I saw that
|
4
|
+
defining/undefining the finalizer added 15-30% processing
|
5
|
+
overhead on the latency test. So, I split this functionality
|
6
|
+
out to a subclass called ZMQ::ManagedMemory. Any existing code
|
7
|
+
that relies on the default Message class to clean up after itself
|
8
|
+
will now have a memory leak. Explicitly call #close on these
|
9
|
+
received messages *unless* they are sent out again. The #send
|
10
|
+
method automatically closes call on your behalf.
|
11
|
+
|
12
|
+
* Rubinius/rbx compatibility! Requires an rbx code pull from git
|
13
|
+
from 20100911 or later to get the necessary code fixes.
|
14
|
+
|
15
|
+
* Modify Message to use the @pointer directly rather than indirectly
|
16
|
+
via the @struct object. Provides better compatibility for rbx
|
17
|
+
since rbx does not yet support the FFI pointer protocol for structs
|
18
|
+
like the FFI gem.
|
19
|
+
|
20
|
+
* Modify Message to pass libC's free function for disposing of message
|
21
|
+
data buffers rather than trying to callback into ruby code to
|
22
|
+
do the same thing. External thread callbacks into ruby code will
|
23
|
+
never be supported in rbx; this also improves compatibility and
|
24
|
+
performance with MRI and JRuby. (In particular, MRI enqueues these
|
25
|
+
kinds of callbacks and spawns a *new* thread to execute each one.
|
26
|
+
Avoiding the ruby callback entirely eliminates this extra work
|
27
|
+
for MRI.)
|
28
|
+
|
29
|
+
* Modify FFI wrapper to capture the libC dynamic library to fetch
|
30
|
+
a pointer to the free function.
|
31
|
+
|
32
|
+
* Modify FFI wrapper to remove the FFI::Function callback used
|
33
|
+
by Message. It's no longer necessary since we now use free
|
34
|
+
directly.
|
35
|
+
|
1
36
|
== 0.5.1 / 20100830
|
2
37
|
* Works with 0mq 2.0.8 release.
|
3
38
|
|
data/README.rdoc
CHANGED
@@ -6,8 +6,8 @@ ffi-rzmq
|
|
6
6
|
|
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
|
-
and run by any ruby runtime that supports FFI.
|
10
|
-
MRI 1.9.x and JRuby.
|
9
|
+
and run by any ruby runtime that supports FFI. That's all of them:
|
10
|
+
MRI 1.8.7+, 1.9.x, Rubinius and JRuby.
|
11
11
|
|
12
12
|
The impetus behind this library was to provide support for ZeroMQ in
|
13
13
|
JRuby which has native threads. Unlike MRI, MacRuby, IronRuby and
|
@@ -18,31 +18,13 @@ environment to run this library.
|
|
18
18
|
|
19
19
|
== PERFORMANCE
|
20
20
|
|
21
|
-
|
22
|
-
I was unable to detect any measurable performance drop due to FFI
|
23
|
-
regardless of which ruby runtime was tested. JRuby had the best overall
|
24
|
-
performance (with --server) once it warmed up. MRI behaved quite well
|
25
|
-
too and has a much lower memory footprint than JRuby (use the trunk
|
26
|
-
version of the FFI bindings to fix several threading issues affecting
|
27
|
-
MRI).
|
21
|
+
Check out the latest performance results:
|
28
22
|
|
29
|
-
|
30
|
-
Lock), I recommend using JRuby 1.5.1 or later. JRuby has no GIL.
|
31
|
-
|
32
|
-
The hope is that in a multi-threaded environment that JRuby's native
|
33
|
-
threads and lack of GIL will provide the best ZeroMQ performance using
|
34
|
-
the ruby language.
|
35
|
-
|
36
|
-
Unfortunately, there is really no reasonable way to support zero-copy
|
37
|
-
using Ruby. Any time data needs to be accessible by the Ruby runtime,
|
38
|
-
it must be copied out of native memory to the Ruby heap. The same is
|
39
|
-
true for the reverse. I am investigating ways to "pin" primitive arrays
|
40
|
-
in memory for Rubinius and JRuby to achieve zero-copy, but that is
|
41
|
-
a ways off.
|
23
|
+
http://www.zeromq.org/bindings:ruby-ffi
|
42
24
|
|
43
25
|
== FEATURES/PROBLEMS:
|
44
26
|
|
45
|
-
This gem
|
27
|
+
This gem needs more tests. I'm certain there are a
|
46
28
|
ton of bugs, so please open issues for them here or fork this project,
|
47
29
|
fix them, and send me a pull request.
|
48
30
|
|
@@ -52,10 +34,12 @@ in MRI 1.8.x is irrevocably broken (according to the brains behind the
|
|
52
34
|
Ruby FFI project) so tread carefully.
|
53
35
|
|
54
36
|
Running this gem with MRI 1.9.x may also exhibit some hangs particularly at
|
55
|
-
shutdown. This is due to a
|
56
|
-
and MRI
|
57
|
-
|
58
|
-
|
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.
|
59
43
|
|
60
44
|
All features are implemented with the exception of the 0mq devices
|
61
45
|
(forwarder, queue, streamer). For implementations of these devices, see
|
@@ -79,7 +63,7 @@ Client code:
|
|
79
63
|
message_size = ARGV[1].to_i
|
80
64
|
roundtrip_count = ARGV[2].to_i
|
81
65
|
|
82
|
-
ctx = ZMQ::Context.new
|
66
|
+
ctx = ZMQ::Context.new
|
83
67
|
s = ctx.socket ZMQ::REP
|
84
68
|
s.setsockopt(ZMQ::HWM, 100)
|
85
69
|
s.bind(bind_to)
|
@@ -107,7 +91,7 @@ Server code:
|
|
107
91
|
message_size = ARGV[1].to_i
|
108
92
|
roundtrip_count = ARGV[2].to_i
|
109
93
|
|
110
|
-
ctx = ZMQ::Context.new
|
94
|
+
ctx = ZMQ::Context.new
|
111
95
|
s = ctx.socket ZMQ::REQ
|
112
96
|
s.connect(connect_to)
|
113
97
|
|
@@ -123,7 +107,7 @@ Server code:
|
|
123
107
|
|
124
108
|
== REQUIREMENTS:
|
125
109
|
|
126
|
-
* 0mq 2.0.
|
110
|
+
* 0mq 2.0.8 or 2.0.9
|
127
111
|
|
128
112
|
The ZeroMQ library must be installed on your system in a well-known location
|
129
113
|
like /usr/local/lib. This is the default for new ZeroMQ installs.
|
@@ -0,0 +1,163 @@
|
|
1
|
+
= Examples
|
2
|
+
|
3
|
+
== Requirements
|
4
|
+
|
5
|
+
1. Installed gem
|
6
|
+
|
7
|
+
All of the examples assume the gem has been successfully installed.
|
8
|
+
|
9
|
+
2. Installed libzmq library
|
10
|
+
|
11
|
+
The ZeroMQ C libraries need to be downloaded, compiled and installed separately from the gem. Please see http://www.zeromq.org/area:download for links to the downloadable files along with some simple installation instructions. Also, be sure to check the FAQ if you run into problems with compiling.
|
12
|
+
|
13
|
+
3. Two terminal windows
|
14
|
+
|
15
|
+
ZeroMQ is used to build network applications. At minimum, there is a "client" application and a "server" application that talk to each other over the network, IPC or an internal thread queue. For the sake of code simplicity, these programs are in separate files and need to be executed in different windows.
|
16
|
+
|
17
|
+
== Latency Test
|
18
|
+
|
19
|
+
The examples include a latency performance test. The example sets up a pair of REQ/REP sockets and send a message back and forth as fast as possible. There is only a single message in flight at any given moment. The time required to send the message the requested number of times determines overall single-message latency for this type of socket.
|
20
|
+
|
21
|
+
==== Files
|
22
|
+
|
23
|
+
* local_lat.rb
|
24
|
+
* remote_lat.rb
|
25
|
+
|
26
|
+
==== Arguments
|
27
|
+
|
28
|
+
The remote_lat.rb program takes 3 arguments:
|
29
|
+
|
30
|
+
[bind_to] Requires a transport string of the format "transport"://"endpoint"<:><port>. For example, tcp://127.0.0.1:5555
|
31
|
+
|
32
|
+
[message size] Size of each message measured in bytes. Allowable range is 1 to 2^(64-1).
|
33
|
+
|
34
|
+
[message count] The number of round-trips used for the latency measurements. Allowable range is 1 to 2^(64-1).
|
35
|
+
|
36
|
+
|
37
|
+
The local_lat.rb program also takes 3 arguments. They should exactly mirror the arguments given to remote_lat.rb.
|
38
|
+
|
39
|
+
|
40
|
+
==== Execution
|
41
|
+
|
42
|
+
In one of the terminals, start up the remote_lat.rb program first. It *must* be launched first so that it can be ready and waiting for the first message sent by the local_lat.rb program.
|
43
|
+
|
44
|
+
% ruby remote_lat.rb tcp://127.0.0.1:5555 1024 100_000
|
45
|
+
|
46
|
+
In the second terminal window, start up the local_lat.rb program too.
|
47
|
+
|
48
|
+
% ruby local_lat.rb tcp://127.0.0.1:5555 1024 100_000
|
49
|
+
|
50
|
+
On a relatively new system, it can run 100k messages in under 30 seconds. When complete, the remote_lat.rb program prints out a few statistics and exits. The local_lat.rb program does not print any message when it exits.
|
51
|
+
|
52
|
+
Running with a larger "message count" will yield a more accurate latency measurement since nearly all Ruby runtimes require a little warm up time to hit their stride. I recommend 100k as a minimum while 10 million is better for determining a true measure.
|
53
|
+
|
54
|
+
On a desktop computer purchased in 2007, all of the Ruby runtimes report a latency of approximately 110 microseconds per message. For comparison, the pure C latency test reports approximately 88 microseconds of latency.
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
== Zero Copy Latency Test
|
59
|
+
|
60
|
+
The examples include a zero copy latency performance test. The example sets up a pair of REQ/REP sockets and send a message back and forth as fast as possible. There is only a single message in flight at any given moment. The time required to send the message the requested number of times determines overall single-message latency for this type of socket.
|
61
|
+
|
62
|
+
The difference between this test and the first latency test has to do with the management of the sent and received messages. This test does not examine or copy the contents of the message at all. Instead, its mere presence is sufficient to echo it back to the other program. Therefore, this test is doing a lot less work for each message send & receive than the first latency test. Also, this test more perfectly mirrors the work being performed by the C latency test.
|
63
|
+
|
64
|
+
==== Files
|
65
|
+
|
66
|
+
* local_lat_zerocopy.rb
|
67
|
+
* remote_lat_zerocopy.rb
|
68
|
+
|
69
|
+
==== Arguments
|
70
|
+
|
71
|
+
The remote_lat_zerocopy.rb program takes 3 arguments:
|
72
|
+
|
73
|
+
[bind_to] Requires a transport string of the format "transport"://"endpoint"<:><port>. For example, tcp://127.0.0.1:5555
|
74
|
+
|
75
|
+
[message size] Size of each message measured in bytes. Allowable range is 1 to 2^(64-1).
|
76
|
+
|
77
|
+
[message count] The number of round-trips used for the latency measurements. Allowable range is 1 to 2^(64-1).
|
78
|
+
|
79
|
+
|
80
|
+
The local_lat_zerocopy.rb program also takes 3 arguments. They should exactly mirror the arguments given to remote_lat_zerocopy.rb.
|
81
|
+
|
82
|
+
|
83
|
+
==== Execution
|
84
|
+
|
85
|
+
In one of the terminals, start up the remote_lat_zerocopy.rb program first. It *must* be launched first so that it can be ready and waiting for the first message sent by the local_lat_zerocopy.rb program.
|
86
|
+
|
87
|
+
% ruby remote_lat_zerocopy.rb tcp://127.0.0.1:5555 1024 100_000
|
88
|
+
|
89
|
+
In the second terminal window, start up the local_lat.rb program too.
|
90
|
+
|
91
|
+
% ruby local_lat_zerocopy.rb tcp://127.0.0.1:5555 1024 100_000
|
92
|
+
|
93
|
+
On a relatively new system, it can run 100k messages in under 30 seconds. When complete, the remote_lat_zerocopy.rb program prints out a few statistics and exits. The local_lat_zerocopy.rb program does not print any message when it exits.
|
94
|
+
|
95
|
+
Running with a larger "message count" will yield a more accurate latency measurement since nearly all Ruby runtimes require a little warm up time to hit their stride. I recommend 100k as a minimum while 10 million is better for determining a true measure.
|
96
|
+
|
97
|
+
On a desktop computer purchased in 2007, all of the Ruby runtimes report a latency of approximately 95 microseconds per message. For comparison, the pure C latency test reports approximately 88 microseconds of latency.
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
== Throughput Test
|
102
|
+
|
103
|
+
The examples include a throughput performance test. The example sets up a pair of PUB/SUB sockets and publish messages as fast as possible to a subscriber listening for every message. The publisher can send much faster than the subscriber can retrieve messages.
|
104
|
+
|
105
|
+
Since the publisher completes first, that program contains a "sleep" statement to keep the program alive and active which gives the subscriber more time to consume the queued messages. When the publisher exits, the socket closes and discards all remaining messages.
|
106
|
+
|
107
|
+
The subscriber prints some statistics when it exits.
|
108
|
+
|
109
|
+
==== Files
|
110
|
+
|
111
|
+
* local_throughput.rb
|
112
|
+
* remote_throughput.rb
|
113
|
+
|
114
|
+
==== Arguments
|
115
|
+
|
116
|
+
The local_throughput.rb program takes 3 arguments:
|
117
|
+
|
118
|
+
[bind_to] Requires a transport string of the format "transport"://"endpoint"<:><port>. For example, tcp://127.0.0.1:5555
|
119
|
+
|
120
|
+
[message size] Size of each message measured in bytes. Allowable range is 1 to 2^(64-1).
|
121
|
+
|
122
|
+
[message count] The number of round-trips used for the latency measurements. Allowable range is 1 to 2^(64-1).
|
123
|
+
|
124
|
+
|
125
|
+
The remote_throughput.rb program also takes 3 arguments. They should exactly mirror the arguments given to local_throughput.rb.
|
126
|
+
|
127
|
+
|
128
|
+
==== Execution
|
129
|
+
|
130
|
+
In one of the terminals, start up the local_throughput.rb program first. It *must* be launched first so that it can be ready and waiting for the first message published by the remote_throughput.rb program.
|
131
|
+
|
132
|
+
% ruby local_throughput.rb tcp://127.0.0.1:5555 1024 100_000
|
133
|
+
|
134
|
+
In the second terminal window, start up the second program.
|
135
|
+
|
136
|
+
% ruby remote_throughput.rb tcp://127.0.0.1:5555 1024 100_000
|
137
|
+
|
138
|
+
On a relatively new system, it can run 100k messages in under 10 seconds. When complete, the local_throughput.rb program prints out a few statistics and exits. The remote_throughput.rb program does not print any message when it exits.
|
139
|
+
|
140
|
+
Running with a larger "message count" will yield a more accurate latency measurement since nearly all Ruby runtimes require a little warm up time to hit their stride. I recommend 100k as a minimum while 1 million is better for determining a true measure. NOTE! The publisher can send much faster than the subscriber so the publisher's queue will grow very rapidly in RAM. For 1 million messages (or more) this can consume hundreds of megabytes or gigabytes of RAM. On my system, sending 10 million messages requires 10 GB of RAM before the subscriber can catch up.
|
141
|
+
|
142
|
+
On a desktop computer purchased in 2007, all of the Ruby runtimes report a throughput of approximately 150k messages per second. For comparison, the pure C throughput test reports approximately 260k messages per second.
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
== Poll
|
147
|
+
|
148
|
+
For a reasonable example of using zmq_poll(), take a look at the reqrep_poll.rb program. It illustrates the use of zmq_poll(), as wrapped by the Ruby library, for detecting and responding to read and write events recorded on sockets. It also shows how to use ZMQ::NO_BLOCK for non-blocking send and receive.
|
149
|
+
|
150
|
+
==== Files
|
151
|
+
|
152
|
+
* reqrep_poll.rb
|
153
|
+
|
154
|
+
==== Arguments
|
155
|
+
|
156
|
+
None.
|
157
|
+
|
158
|
+
==== Execution
|
159
|
+
|
160
|
+
This program is completely self-contained, so it only requires a single terminal window for execution.
|
161
|
+
|
162
|
+
% ruby reqrep_poll.rb
|
163
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ffi-rzmq'
|
3
|
+
|
4
|
+
if ARGV.length != 3
|
5
|
+
puts "usage: local_thr <bind-to> <message-size> <message-count>"
|
6
|
+
Process.exit
|
7
|
+
end
|
8
|
+
|
9
|
+
bind_to = ARGV[0]
|
10
|
+
message_size = ARGV[1].to_i
|
11
|
+
message_count = ARGV[2].to_i
|
12
|
+
|
13
|
+
ctx = ZMQ::Context.new
|
14
|
+
s = ZMQ::Socket.new ctx.pointer, ZMQ::SUB
|
15
|
+
s.setsockopt ZMQ::SUBSCRIBE, ""
|
16
|
+
|
17
|
+
s.bind bind_to
|
18
|
+
|
19
|
+
msg = ZMQ::Message.new
|
20
|
+
rc = s.recv msg
|
21
|
+
|
22
|
+
start_time = Time.now
|
23
|
+
|
24
|
+
i = 1
|
25
|
+
while i < message_count
|
26
|
+
result_code = s.recv msg
|
27
|
+
i += 1
|
28
|
+
end
|
29
|
+
|
30
|
+
end_time = Time.now
|
31
|
+
|
32
|
+
elapsed = (end_time.to_f - start_time.to_f) * 1000000
|
33
|
+
if elapsed == 0
|
34
|
+
elapsed = 1
|
35
|
+
end
|
36
|
+
|
37
|
+
throughput = message_count * 1000000 / elapsed
|
38
|
+
megabits = throughput * message_size * 8 / 1000000
|
39
|
+
|
40
|
+
puts "message size: %i [B]" % message_size
|
41
|
+
puts "message count: %i" % message_count
|
42
|
+
puts "mean throughput: %i [msg/s]" % throughput
|
43
|
+
puts "mean throughput: %.3f [Mb/s]" % megabits
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ffi-rzmq'
|
3
|
+
|
4
|
+
if ARGV.length != 3
|
5
|
+
puts "usage: remote_thr <connect-to> <message-size> <message-count>"
|
6
|
+
Process.exit
|
7
|
+
end
|
8
|
+
|
9
|
+
connect_to = ARGV[0]
|
10
|
+
message_size = ARGV[1].to_i
|
11
|
+
message_count = ARGV[2].to_i
|
12
|
+
|
13
|
+
ctx = ZMQ::Context.new
|
14
|
+
s = ZMQ::Socket.new ctx.pointer, ZMQ::PUB
|
15
|
+
|
16
|
+
s.connect connect_to
|
17
|
+
|
18
|
+
contents = "#{'0'*message_size}"
|
19
|
+
|
20
|
+
i = 0
|
21
|
+
while i < message_count
|
22
|
+
msg = ZMQ::Message.new contents
|
23
|
+
s.send msg
|
24
|
+
i += 1
|
25
|
+
end
|
26
|
+
|
27
|
+
sleep 10
|
data/examples/xreqxrep_poll.rb
CHANGED
data/ffi-rzmq.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{ffi-rzmq}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.6.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-09-21}
|
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
|
-
and run by any ruby runtime that supports FFI.
|
13
|
-
MRI 1.9.x and JRuby.
|
12
|
+
and run by any ruby runtime that supports FFI. That's all of them:
|
13
|
+
MRI 1.8.7+, 1.9.x, Rubinius and JRuby.
|
14
14
|
|
15
15
|
The impetus behind this library was to provide support for ZeroMQ in
|
16
16
|
JRuby which has native threads. Unlike MRI, MacRuby, IronRuby and
|
@@ -19,20 +19,20 @@ 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
|
-
s.extra_rdoc_files = ["History.txt", "README.rdoc", "version.txt"]
|
23
|
-
s.files = [".
|
22
|
+
s.extra_rdoc_files = ["History.txt", "README.rdoc", "examples/README.rdoc", "version.txt"]
|
23
|
+
s.files = [".gitignore", "History.txt", "README.rdoc", "Rakefile", "examples/README.rdoc", "examples/local_lat.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", "examples/xreqxrep_poll.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
|
-
s.rubygems_version = %q{1.3.
|
28
|
+
s.rubygems_version = %q{1.3.7}
|
29
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
|
-
if Gem::Version.new(Gem::
|
35
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
36
36
|
s.add_development_dependency(%q<bones>, [">= 3.4.7"])
|
37
37
|
else
|
38
38
|
s.add_dependency(%q<bones>, [">= 3.4.7"])
|
data/lib/ffi-rzmq/context.rb
CHANGED
@@ -11,10 +11,12 @@ module ZMQ
|
|
11
11
|
|
12
12
|
attr_reader :context, :pointer
|
13
13
|
|
14
|
-
# Recommended to
|
15
|
-
# since most programs
|
16
|
-
#
|
17
|
-
#
|
14
|
+
# Recommended to use the default for +io_threads+
|
15
|
+
# since most programs will not saturate I/O.
|
16
|
+
#
|
17
|
+
# The rule of thumb is to make +io_threads+ equal to the number
|
18
|
+
# gigabits per second that the application will produce.
|
19
|
+
#
|
18
20
|
# The +io_threads+ number specifies the size of the thread pool
|
19
21
|
# allocated by 0mq for processing incoming/outgoing messages.
|
20
22
|
#
|
@@ -23,12 +25,19 @@ module ZMQ
|
|
23
25
|
# live within a context. Sockets in one context may not be accessed
|
24
26
|
# from another context; doing so raises an exception.
|
25
27
|
#
|
28
|
+
# Also, Sockets should *only* be accessed from the thread where they
|
29
|
+
# were first created. Do *not* pass sockets between threads; pass
|
30
|
+
# in the context and allocate a new socket per thread.
|
31
|
+
#
|
26
32
|
# To connect sockets between contexts, use +inproc+ or +ipc+
|
27
|
-
# transport and set up a 0mq socket between them.
|
33
|
+
# transport and set up a 0mq socket between them. This is also the
|
34
|
+
# recommended technique for allowing sockets to communicate between
|
35
|
+
# threads.
|
28
36
|
#
|
29
|
-
#
|
37
|
+
# Will raise a #ContextError when the native library context cannot be
|
38
|
+
# be allocated.
|
30
39
|
#
|
31
|
-
def initialize io_threads
|
40
|
+
def initialize io_threads = 1
|
32
41
|
@sockets ||= []
|
33
42
|
@context = LibZMQ.zmq_init io_threads
|
34
43
|
@pointer = @context
|
@@ -44,7 +53,8 @@ module ZMQ
|
|
44
53
|
#
|
45
54
|
# Returns nil.
|
46
55
|
#
|
47
|
-
#
|
56
|
+
# Will raise a #ContextError when the call fails. Failures occur when
|
57
|
+
# the context has somehow become null (indicates a libzmq bug).
|
48
58
|
#
|
49
59
|
def terminate
|
50
60
|
unless @context.nil? || @context.null?
|