ffi-rzmq 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,23 @@
1
+ == 0.8.0 / 20110307
2
+ * API change!
3
+ Socket#send_message no longer automatically calls
4
+ Message#close on behalf of the user. The user is completely
5
+ responsible for the lifecycle management of all buffers associated
6
+ with the ZMQ::Message objects.
7
+ This is a breaking change.
8
+ If you want the old behavior (auto-close messages on send) then
9
+ use the new Socket#send_and_close method which does as its name
10
+ implies.
11
+ * Fixed bug with type :size_t on Windows (thank you to arvicco)
12
+
13
+ == 0.7.3 / 20110304
14
+ * Fixed a bug where we had a small memory leak. When closing a socket
15
+ I forgot to release a small amount of native memory used as a cache
16
+ for doing #getsockopt calls.
17
+ * Util.minimum_api? didn't work. Fixed.
18
+ * Added ROUTER/DEALER constants to reflect new naming for XREQ/XREP.
19
+ XREQ and XREP remain aliased for backward compatibility.
20
+
1
21
  == 0.7.2 / 20110224
2
22
  * Several minor refactorings to make the code intent clearer and to allow
3
23
  for better testing. In particular, the error condition checking for
@@ -12,10 +32,10 @@
12
32
  * Improved performance of calls to Socket#getsockopt. There are usually
13
33
  a lot of calls passing RCVMORE, so we now cache those buffers instead
14
34
  of reallocating them every time.
15
-
35
+
16
36
  * Updated the docs on Poller#poll to warn about a possible busy-loop
17
37
  condition.
18
-
38
+
19
39
  * Fixed some more specs to conform with the 0mq 2.1 requirement that
20
40
  all sockets must be closed explicitly otherwise the program may
21
41
  hang on exit.
@@ -28,26 +48,26 @@
28
48
 
29
49
  * Preliminary support for the Windows platform. Patches supplied
30
50
  by arvicco.
31
-
51
+
32
52
  * Added support for FD and EVENTS socket options. These were added
33
53
  in 0mq 2.1.0. Patches + specs supplied by andrewvc.
34
-
54
+
35
55
  * Added support for LINGER, RECONNECT_IVL, BACKLOG and
36
56
  RECOVERY_IVL_MSEC socket options.
37
-
57
+
38
58
  * Conditionally re-enable the socket finalizer when we are running
39
59
  with 0mq 2.1.0 or later.
40
-
60
+
41
61
  * Drop support for MRI 1.8.x since the 'ffi' gem has dropped it as a
42
62
  supported Ruby runtime with its 1.0 release. No action is taken to
43
63
  prevent running with MRI 1.8.x but it won't be supported.
44
-
64
+
45
65
  * Misc. spec fixes. Need more specs!
46
66
 
47
67
  == 0.6.0 / 20100911
48
68
  * API Change! Modified ZMQ::Message by removing automatic memory
49
69
  management. While doing some performance tests I saw that
50
- defining/undefining the finalizer added 15-30% processing
70
+ defining/undefining the finalizer added 15-30% processing
51
71
  overhead on the latency test. So, I split this functionality
52
72
  out to a subclass called ZMQ::ManagedMemory. Any existing code
53
73
  that relies on the default Message class to clean up after itself
@@ -57,7 +77,7 @@
57
77
 
58
78
  * Rubinius/rbx compatibility! Requires an rbx code pull from git
59
79
  from 20100911 or later to get the necessary code fixes.
60
-
80
+
61
81
  * Modify Message to use the @pointer directly rather than indirectly
62
82
  via the @struct object. Provides better compatibility for rbx
63
83
  since rbx does not yet support the FFI pointer protocol for structs
@@ -76,38 +96,38 @@
76
96
  a pointer to the free function.
77
97
 
78
98
  * Modify FFI wrapper to remove the FFI::Function callback used
79
- by Message. It's no longer necessary since we now use free
99
+ by Message. It's no longer necessary since we now use free
80
100
  directly.
81
101
 
82
102
  == 0.5.1 / 20100830
83
103
  * Works with 0mq 2.0.8 release.
84
-
104
+
85
105
  * Removed the socket finalizer. The current 0mq framework cannot
86
106
  handle the case where zmq_close is called on a socket that was
87
107
  created from another thread. Therefore, the garbage collection
88
108
  thread causes the framework to break. Version 2.1 (or later)
89
109
  should fix this 0mq limitation.
90
-
110
+
91
111
  * Misc fixes. See commits.
92
112
 
93
113
  == 0.5.0 / 20100606
94
114
  * Updated the bindings to conform to the 0mq 2.0.7 release.
95
115
  Several parts of the API changed.
96
-
116
+
97
117
  * Updated all examples to use the new Context api.
98
-
118
+
99
119
  * Added Socket#getsockopt.
100
-
120
+
101
121
  * Added a Socket#identity and Socket#identity= method pair to
102
122
  allow for easy get/put on socket identities. Useful for async
103
123
  request/reply using XREQ/XREP sockets.
104
-
124
+
105
125
  * Added more specs (slowly but surely).
106
-
126
+
107
127
  * Support multi-part messages (new as of 2.0.7). I am unsure how
108
128
  to best support multi-part messages so the Message (and related)
109
129
  API may change in the future. Added Socket#more_parts?.
110
-
130
+
111
131
  * Lots of fixes. Many classes use finalizers to deallocate native
112
132
  memory when they go out of scope; be sure to use JRuby 1.5.1 or
113
133
  later to get important finalizer fixes.
@@ -120,41 +140,41 @@
120
140
  == 0.4.0 / 20100510
121
141
  * Changed the Socket#recv method signature to take an optional
122
142
  message object as its first argument. This allows the library
123
- user to allocate and pass in their own message object for the
143
+ user to allocate and pass in their own message object for the
124
144
  purposes of zero-copy. Original behavior was for the library to
125
145
  *always* allocate a new message object to receive a message into.
126
146
  Hopefully this is the last change required.
127
-
147
+
128
148
  * Modified the Socket constructor to take an optional hash as its
129
149
  final argument. It honors two keys; :receiver_klass and
130
150
  :sender_klass. Passing in a new constant for either (or both) keys
131
151
  will override the class used by Socket for allocating new
132
- Message objects.
152
+ Message objects.
133
153
 
134
154
  == 0.3.1 / 20100509
135
155
  * Modified ZMQ::Message so we have both an UnmanagedMessage where
136
156
  memory management is manual via the #close method, and Message where
137
157
  memory management is automated via a finalizer method run during
138
158
  garbage collection.
139
-
159
+
140
160
  * Updated ZMQ::Message docs to make it clearer how to use a subclass
141
161
  and FFI::Struct to lazily access the message buffer. This gets us as
142
162
  close to zero-copy as possible for performance.
143
-
163
+
144
164
  * Fixed a memory leak in Message where the FFI::Struct backing the
145
165
  C struct was not being freed.
146
-
166
+
147
167
  * Tested the FFI code against MRI 1.8.x and 1.9.x. It works!
148
-
168
+
149
169
  * Patched a potential problem in LibZMQ::MessageDeallocator. It was
150
170
  crashing under MRI because it complained that FFI::Pointer did not
151
- have a free method. It now checks for :free before calling it.
171
+ have a free method. It now checks for :free before calling it.
152
172
  Need to investigate this further because it never happened under
153
173
  JRuby.
154
-
174
+
155
175
  * Modified the Socket constructor slightly to allow for using
156
176
  unmanaged or managed messages.
157
-
177
+
158
178
  * Changed the /examples to print a throughput (msgs/s) number upon
159
179
  completion.
160
180
 
@@ -164,20 +184,20 @@
164
184
  However, to do so requires lots of copying to and from buffers which
165
185
  greatly impacts performance. These methods now return a ZMQ::Message
166
186
  object which can be subclassed to do lazy evaluation of the buffer.
167
-
187
+
168
188
  * Added ZMQ::Socket#send_string and ZMQ::Socket#recv_string. They
169
189
  automatically convert the messages to strings just like the official
170
190
  0mq ruby bindings.
171
191
 
172
192
  * Fixed bug in ZMQ::Util#error_string
173
-
193
+
174
194
  * Split the ZMQ::Message class into two classes. The base class called
175
195
  UnmanagedMessage requires manual memory management. The Message
176
196
  class (used by default by Socket) has a finalizer defined to
177
197
  automatically release memory when the message object gets garbage
178
198
  collected.
179
-
180
-
199
+
200
+
181
201
  == 0.2.0 / 20100505
182
202
 
183
203
  * 1 major enhancement
data/ffi-rzmq.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{ffi-rzmq}
5
- s.version = "0.7.2"
5
+ s.version = "0.8.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"]
@@ -10,17 +10,10 @@ Gem::Specification.new do |s|
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.9.x, Rubinius and JRuby.
14
-
15
- The impetus behind this library was to provide support for ZeroMQ in
16
- JRuby which has native threads. Unlike MRI, IronRuby and
17
- Rubinius which all have a GIL, JRuby allows for threaded access to ruby
18
- code from outside extensions. ZeroMQ is heavily threaded, so until the
19
- other runtimes remove their GIL, JRuby will likely be the best
20
- environment to run this library.}
13
+ MRI 1.9.x, Rubinius and JRuby.}
21
14
  s.email = %q{cremes@mac.com}
22
15
  s.extra_rdoc_files = ["History.txt", "README.rdoc", "examples/README.rdoc", "version.txt"]
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"]
16
+ 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/device.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/device_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
17
  s.homepage = %q{http://github.com/chuckremes/ffi-rzmq}
25
18
  s.rdoc_options = ["--main", "README.rdoc"]
26
19
  s.require_paths = ["lib"]
data/lib/ffi-rzmq.rb CHANGED
@@ -67,6 +67,6 @@ end # module ZMQ
67
67
  RBX = defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/ ? true : false
68
68
 
69
69
  # the order of files is important
70
- %w(wrapper zmq exceptions context message socket poll_items poll).each do |file|
70
+ %w(wrapper zmq exceptions context message socket poll_items poll device).each do |file|
71
71
  require ZMQ.libpath(['ffi-rzmq', file])
72
72
  end
@@ -77,8 +77,8 @@ module ZMQ
77
77
  # #ZMQ::PAIR
78
78
  # #ZMQ::PULL
79
79
  # #ZMQ::PUSH
80
- # #ZMQ::XREQ
81
- # #ZMQ::XREP
80
+ # #ZMQ::DEALER
81
+ # #ZMQ::ROUTER
82
82
  #
83
83
  # Returns a #ZMQ::Socket.
84
84
  #
@@ -0,0 +1,15 @@
1
+ module ZMQ
2
+ class Device
3
+ attr_reader :device
4
+
5
+ def initialize(device_type,frontend,backend)
6
+ [["frontend", frontend],["backend", backend]].each do |name,socket|
7
+ unless socket.is_a?(ZMQ::Socket)
8
+ raise ArgumentError, "Expected a ZMQ::Socket, not a #{socket.class} as the #{name}"
9
+ end
10
+ end
11
+
12
+ LibZMQ.zmq_device(device_type, frontend.socket, backend.socket)
13
+ end
14
+ end
15
+ end
@@ -189,8 +189,14 @@ module ZMQ
189
189
  # Manually release the message struct and its associated data
190
190
  # buffer.
191
191
  #
192
+ # Only releases the buffer a single time. Subsequent calls are
193
+ # no ops.
194
+ #
192
195
  def close
193
- LibZMQ.zmq_msg_close @pointer
196
+ if @pointer
197
+ LibZMQ.zmq_msg_close @pointer
198
+ @pointer = nil
199
+ end
194
200
  end
195
201
 
196
202
 
data/lib/ffi-rzmq/poll.rb CHANGED
@@ -67,7 +67,6 @@ module ZMQ
67
67
  def register sock, events = ZMQ::POLLIN | ZMQ::POLLOUT, fd = 0
68
68
  return false if (sock.nil? && fd.zero?) || events.zero?
69
69
 
70
- @poll_items_dirty = true
71
70
  item = @items.get(@sockets.index(sock))
72
71
 
73
72
  unless item
@@ -78,7 +77,7 @@ module ZMQ
78
77
  item[:socket] = sock.socket
79
78
  item[:fd] = 0
80
79
  else
81
- item[:socket] = 0
80
+ item[:socket] = FFI::MemoryPointer.new(0)
82
81
  item[:fd] = fd
83
82
  end
84
83
 
@@ -132,14 +131,28 @@ module ZMQ
132
131
 
133
132
  # Deletes the +sock+ for all subscribed events.
134
133
  #
134
+ # def delete sock
135
+ # removed = false
136
+ #
137
+ # if index = @sockets.index(sock)
138
+ # removed = @items.delete_at(index) and @sockets.delete(sock) and @raw_to_socket.delete(sock.socket.address)
139
+ # end
140
+ #
141
+ # removed
142
+ # end
135
143
  def delete sock
136
144
  removed = false
145
+ size = @sockets.size
146
+ @sockets.delete_if { |socket| socket.socket.address == sock.socket.address }
147
+ socket_deleted = size != @sockets.size
137
148
 
138
- if index = @sockets.index(sock)
139
- removed = @items.delete_at(index) and @sockets.delete(sock) and @raw_to_socket.delete(sock.socket.address)
140
- end
149
+ item_deleted = @items.delete sock
150
+
151
+ size = @raw_to_socket.size
152
+ @raw_to_socket.delete(sock.socket.address)
153
+ raw_deleted = size != @raw_to_socket.size
141
154
 
142
- removed
155
+ socket_deleted && item_deleted && raw_deleted
143
156
  end
144
157
 
145
158
  def size(); @items.size; end
@@ -37,6 +37,25 @@ module ZMQ
37
37
  end
38
38
  alias :push :<<
39
39
 
40
+ def delete sock
41
+ address = sock.socket.address
42
+ found = false
43
+
44
+ each_with_index do |item, index|
45
+ if address == item[:socket].address
46
+ @items.delete_at index
47
+ found = true
48
+ @dirty = true
49
+ clean
50
+ break
51
+ end
52
+ end
53
+
54
+ # these semantics are different from the usual Array#delete; returns a
55
+ # boolean instead of the actual item or nil
56
+ found
57
+ end
58
+
40
59
  def delete_at index
41
60
  value = nil
42
61
  unless @items.empty?
@@ -84,7 +103,7 @@ module ZMQ
84
103
  # it is garbage collected that native memory should be automatically freed.
85
104
  def clean
86
105
  if @dirty
87
- @store = FFI::MemoryPointer.new @element_size, @items.size, false
106
+ @store = FFI::MemoryPointer.new @element_size, @items.size, true
88
107
 
89
108
  # copy over
90
109
  offset = 0
@@ -19,7 +19,7 @@ module ZMQ
19
19
  #
20
20
  # +type+ can be one of ZMQ::REQ, ZMQ::REP, ZMQ::PUB,
21
21
  # ZMQ::SUB, ZMQ::PAIR, ZMQ::PULL, ZMQ::PUSH,
22
- # ZMQ::XREQ or ZMQ::XREP.
22
+ # ZMQ::DEALER or ZMQ::ROUTER.
23
23
  #
24
24
  # By default, this class uses ZMQ::Message for manual
25
25
  # memory management. For automatic garbage collection of received messages,
@@ -144,7 +144,7 @@ module ZMQ
144
144
  def getsockopt option_name
145
145
  begin
146
146
  option_value = FFI::MemoryPointer.new :pointer
147
- option_length = FFI::MemoryPointer.new :size_t
147
+ option_length = FFI::MemoryPointer.new(:size_t) rescue FFI::MemoryPointer.new(:ulong)
148
148
 
149
149
  unless [
150
150
  RCVMORE, HWM, SWAP, AFFINITY, RATE, RECOVERY_IVL, MCAST_LOOP, IDENTITY,
@@ -226,6 +226,7 @@ module ZMQ
226
226
  result_code = LibZMQ.zmq_close @socket
227
227
  error_check ZMQ_CLOSE_STR, result_code
228
228
  @socket = nil
229
+ release_cache
229
230
  end
230
231
  end
231
232
 
@@ -242,13 +243,8 @@ module ZMQ
242
243
  # 1. The message could not be enqueued
243
244
  # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
244
245
  #
245
- # The application code is *not* responsible for handling the +message+ object
246
- # lifecycle when #send returns successfully or it raises an exception. The
247
- # #send method takes ownership of the +message+ and its associated buffers.
248
- # Both successful and failed calls will release the +message+ data buffer.
249
- #
250
- # Again, once a +message+ object has been passed to this method,
251
- # do not try to access its #data buffer anymore. The 0mq library now owns it.
246
+ # The application code is responsible for handling the +message+ object
247
+ # lifecycle when #send returns.
252
248
  #
253
249
  # Can raise two kinds of exceptions depending on the error.
254
250
  # ContextError:: Raised when a socket operation is attempted on a terminated
@@ -262,8 +258,6 @@ module ZMQ
262
258
  # when the flag isn't set, do a normal error check
263
259
  # when set, check to see if the message was successfully queued
264
260
  queued = flags != NOBLOCK ? error_check(ZMQ_SEND_STR, result_code) : error_check_nonblock(result_code)
265
- ensure
266
- message.close
267
261
  end
268
262
 
269
263
  # true if sent, false if failed/EAGAIN
@@ -281,10 +275,24 @@ module ZMQ
281
275
  # SocketError:: See all of the possibilities in the docs for #SocketError.
282
276
  #
283
277
  def send_string message_string, flags = 0
284
- message = Message.new
285
- message.copy_in_string message_string
286
- result = send message, flags
287
- result
278
+ message = Message.new message_string
279
+ result_code = send_and_close message, flags
280
+
281
+ result_code
282
+ end
283
+
284
+ # Sends a message. This will automatically close the +message+ for both successful
285
+ # and failed sends.
286
+ #
287
+ # Raises the same exceptions as Socket#send
288
+ #
289
+ def send_and_close message, flags = 0
290
+ begin
291
+ result_code = send message, flags
292
+ ensure
293
+ message.close
294
+ end
295
+ result_code
288
296
  end
289
297
 
290
298
  # Dequeues a message from the underlying queue. By default, this is a blocking operation.
@@ -404,6 +412,10 @@ module ZMQ
404
412
  option_value
405
413
  end
406
414
  end
415
+
416
+ def release_cache
417
+ @sockopt_cache.clear
418
+ end
407
419
 
408
420
  # require a minimum of 0mq 2.1.0 to support socket finalizers; it contains important
409
421
  # fixes for sockets and threads so that a garbage collector thread can successfully
@@ -78,6 +78,9 @@ module LibZMQ
78
78
  attach_function :zmq_recv, [:pointer, :pointer, :int], :int
79
79
  attach_function :zmq_close, [:pointer], :int
80
80
 
81
+ #experimental zmq_devices support
82
+ attach_function :zmq_device, [:int, :pointer, :pointer], :int
83
+
81
84
  # Poll api
82
85
  @blocking = true
83
86
  attach_function :zmq_poll, [:pointer, :int, :long], :int
@@ -117,4 +120,4 @@ module LibZMQ
117
120
  def to_s; inspect; end
118
121
  end # class PollItem
119
122
 
120
- end # module ZMQ
123
+ end # module LibZMQ
data/lib/ffi-rzmq/zmq.rb CHANGED
@@ -7,19 +7,19 @@ module ZMQ
7
7
  SUB = 2
8
8
  REQ = 3
9
9
  REP = 4
10
- XREQ = 5
11
- XREP = 6
10
+ ROUTER = XREQ = 5
11
+ DEALER = XREP = 6
12
12
  PULL = UPSTREAM = 7
13
13
  PUSH = DOWNSTREAM = 8
14
-
14
+
15
15
  SocketTypeNameMap = {
16
16
  PAIR => "PAIR",
17
17
  PUB => "PUB",
18
18
  SUB => "SUB",
19
19
  REQ => "REQ",
20
20
  REP => "REP",
21
- XREQ => "XREQ",
22
- XREP => "XREP",
21
+ ROUTER => "ROUTER",
22
+ DEALER => "DEALER",
23
23
  PULL => "PULL",
24
24
  PUSH => "PUSH"
25
25
  }
@@ -63,6 +63,11 @@ module ZMQ
63
63
  ENODEV = Errno::ENODEV::Errno
64
64
  EFAULT = Errno::EFAULT::Errno
65
65
 
66
+ # Device Types
67
+ STREAMER = 1
68
+ FORWARDER = 2
69
+ QUEUE = 3
70
+
66
71
  # ZMQ errors
67
72
  HAUSNUMERO = 156384712
68
73
  EMTHREAD = (HAUSNUMERO + 50)
@@ -114,7 +119,7 @@ module ZMQ
114
119
  LibZMQ.zmq_version major, minor, patch
115
120
  [major.read_int, minor.read_int, patch.read_int]
116
121
  end
117
-
122
+
118
123
  # Compares the 0mq library API version to a minimal version tuple. Returns
119
124
  # true if it meets the minimum requirement, false otherwise.
120
125
  #
@@ -125,11 +130,11 @@ module ZMQ
125
130
  #
126
131
  def self.minimum_api? tuple
127
132
  api_version = Util.version
128
-
133
+
129
134
  # call #to_i to convert nil entries to 0 so the comparison is valid
130
- tuple[0].to_i >= api_version[0] &&
131
- tuple[1].to_i >= api_version[1] &&
132
- tuple[2].to_i >= api_version[2]
135
+ result = tuple[0].to_i <= api_version[0] &&
136
+ tuple[1].to_i <= api_version[1] &&
137
+ tuple[2].to_i <= api_version[2]
133
138
  end
134
139
 
135
140
 
@@ -180,7 +185,7 @@ module ZMQ
180
185
  when ZMQ_MSG_INIT_STR, ZMQ_MSG_INIT_DATA_STR, ZMQ_MSG_COPY_STR, ZMQ_MSG_MOVE_STR
181
186
  raise MessageError.new source, result_code, errno, error_string
182
187
  else
183
- raise ZeroMQError.new source, result_code, -1,
188
+ raise ZeroMQError.new source, result_code, -1,
184
189
  "Source [#{source}] does not match any zmq_* strings, rc [#{result_code}], errno [#{errno}], error_string [#{error_string}]"
185
190
  end
186
191
  end
@@ -0,0 +1,68 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ module ZMQ
5
+ describe Device do
6
+ include APIHelper
7
+
8
+ def create_streamer
9
+ @back_addr = "tcp://127.0.0.1:#{random_port}"
10
+ @front_addr = "tcp://127.0.0.1:#{random_port}"
11
+ Thread.new do
12
+ back = SPEC_CTX.socket(ZMQ::PULL)
13
+ back.bind(@back_addr)
14
+ front = SPEC_CTX.socket(ZMQ::PUSH)
15
+ front.bind(@front_addr)
16
+ Device.new(ZMQ::STREAMER, back, front)
17
+ end
18
+ end
19
+
20
+ it "should create a streamer device without error given valid opts" do
21
+ create_streamer
22
+ end
23
+
24
+ it "should be able to send messages through the device" do
25
+ create_streamer
26
+
27
+ pusher = SPEC_CTX.socket(ZMQ::PUSH)
28
+ pusher.connect(@back_addr)
29
+ puller = SPEC_CTX.socket(ZMQ::PULL)
30
+ puller.connect(@front_addr)
31
+
32
+ pusher.send_string("hello")
33
+ sleep 0.5
34
+ res = puller.recv_string(ZMQ::NOBLOCK)
35
+ res.should == "hello"
36
+ end
37
+
38
+ it "should raise an ArgumentError when trying to pass non-socket objects into the device" do
39
+ lambda {
40
+ Device.new(ZMQ::STREAMER, 1,2)
41
+ }.should raise_exception(ArgumentError)
42
+ end
43
+
44
+ it "should be able to create a forwarder device without error" do
45
+ back_addr = "tcp://127.0.0.1:#{random_port}"
46
+ front_addr = "tcp://127.0.0.1:#{random_port}"
47
+ Thread.new do
48
+ back = SPEC_CTX.socket(ZMQ::SUB)
49
+ back.bind(back_addr)
50
+ front = SPEC_CTX.socket(ZMQ::PUB)
51
+ front.bind(front_addr)
52
+ Device.new(ZMQ::FORWARDER, back, front)
53
+ end
54
+ end
55
+
56
+ it "should be able to create a queue device without error" do
57
+ back_addr = "tcp://127.0.0.1:#{random_port}"
58
+ front_addr = "tcp://127.0.0.1:#{random_port}"
59
+ Thread.new do
60
+ back = SPEC_CTX.socket(ZMQ::ROUTER)
61
+ back.bind(back_addr)
62
+ front = SPEC_CTX.socket(ZMQ::DEALER)
63
+ front.bind(front_addr)
64
+ Device.new(ZMQ::QUEUE, back, front)
65
+ end
66
+ end
67
+ end
68
+ end
data/spec/socket_spec.rb CHANGED
@@ -15,7 +15,7 @@ module ZMQ
15
15
  lambda { Socket.new(FFI::Pointer.new(0), ZMQ::REQ) }.should raise_exception(ZMQ::ContextError)
16
16
  end
17
17
 
18
- [ZMQ::REQ, ZMQ::REP, ZMQ::XREQ, ZMQ::XREP, ZMQ::PUB, ZMQ::SUB, ZMQ::PUSH, ZMQ::PULL, ZMQ::PAIR].each do |socket_type|
18
+ [ZMQ::REQ, ZMQ::REP, ZMQ::DEALER, ZMQ::ROUTER, ZMQ::PUB, ZMQ::SUB, ZMQ::PUSH, ZMQ::PULL, ZMQ::PAIR].each do |socket_type|
19
19
 
20
20
  it "should not raise an error for a #{ZMQ::SocketTypeNameMap[socket_type]} socket type" do
21
21
  sock = nil
@@ -99,7 +99,7 @@ module ZMQ
99
99
  end # context identity=
100
100
 
101
101
 
102
- [ZMQ::REQ, ZMQ::REP, ZMQ::XREQ, ZMQ::XREP, ZMQ::PUB, ZMQ::SUB, ZMQ::PUSH, ZMQ::PULL, ZMQ::PAIR].each do |socket_type|
102
+ [ZMQ::REQ, ZMQ::REP, ZMQ::DEALER, ZMQ::ROUTER, ZMQ::PUB, ZMQ::SUB, ZMQ::PUSH, ZMQ::PULL, ZMQ::PAIR].each do |socket_type|
103
103
 
104
104
  context "#setsockopt for a #{ZMQ::SocketTypeNameMap[socket_type]} socket" do
105
105
  before(:all) { @ctx = Context.new }
data/version.txt CHANGED
@@ -1 +1 @@
1
- 0.7.2
1
+ 0.8.0
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-rzmq
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
5
- prerelease: false
4
+ hash: 63
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
- - 7
9
- - 2
10
- version: 0.7.2
8
+ - 8
9
+ - 0
10
+ version: 0.8.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Chuck Remes
@@ -39,13 +39,6 @@ description: |-
39
39
  function interface). It's a pure ruby wrapper so this gem can be loaded
40
40
  and run by any ruby runtime that supports FFI. That's all of them:
41
41
  MRI 1.9.x, Rubinius and JRuby.
42
-
43
- The impetus behind this library was to provide support for ZeroMQ in
44
- JRuby which has native threads. Unlike MRI, IronRuby and
45
- Rubinius which all have a GIL, JRuby allows for threaded access to ruby
46
- code from outside extensions. ZeroMQ is heavily threaded, so until the
47
- other runtimes remove their GIL, JRuby will likely be the best
48
- environment to run this library.
49
42
  email: cremes@mac.com
50
43
  executables: []
51
44
 
@@ -75,6 +68,7 @@ files:
75
68
  - ffi-rzmq.gemspec
76
69
  - lib/ffi-rzmq.rb
77
70
  - lib/ffi-rzmq/context.rb
71
+ - lib/ffi-rzmq/device.rb
78
72
  - lib/ffi-rzmq/exceptions.rb
79
73
  - lib/ffi-rzmq/message.rb
80
74
  - lib/ffi-rzmq/poll.rb
@@ -83,6 +77,7 @@ files:
83
77
  - lib/ffi-rzmq/wrapper.rb
84
78
  - lib/ffi-rzmq/zmq.rb
85
79
  - spec/context_spec.rb
80
+ - spec/device_spec.rb
86
81
  - spec/message_spec.rb
87
82
  - spec/pushpull_spec.rb
88
83
  - spec/reqrep_spec.rb
@@ -120,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
115
  requirements: []
121
116
 
122
117
  rubyforge_project: ffi-rzmq
123
- rubygems_version: 1.3.7
118
+ rubygems_version: 1.5.2
124
119
  signing_key:
125
120
  specification_version: 3
126
121
  summary: This gem wraps the ZeroMQ networking library using the ruby FFI (foreign function interface).