ffi-rzmq 0.9.6 → 0.9.7

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/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ script: bundle exec rspec
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - ruby-head
7
+ - jruby-18mode
8
+ - jruby-19mode
9
+ - jruby-head
10
+ - rbx-18mode
11
+ - rbx-19mode
12
+
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: ruby-head
16
+ - rvm: jruby-head
data/AUTHORS.txt CHANGED
@@ -17,3 +17,9 @@ Stefan Kaes, github: skaes
17
17
  Dmitry Ustalov, github: eveel
18
18
 
19
19
  Patrik Sundberg, github: sundbp
20
+
21
+ Pawel Pacana, github: pawelpacana
22
+
23
+ Brian Ford, github: brixen
24
+
25
+ Nilson Santos F. Jr., github: nilsonfsj
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem "jruby-openssl", :platform => :jruby
data/History.txt CHANGED
@@ -1,3 +1,37 @@
1
+ == 0.9.7 / 20121221
2
+ * BROKE THE API.
3
+ ZMQ::Poller#register and ZMQ::Poller#deregister don't take fd argument
4
+ anymore. ZMQ::Poller#readables and ZMQ::Poller#writables return pollables
5
+ instead of just fd when pollable is other than ZMQ socket.
6
+ ZMQ::Poller#register now returns nil instead of false when no pollable
7
+ or events to register to are given, which is consistent with rest of api.
8
+ Thanks to Pawel Pacana for this code contribution.
9
+
10
+ * Added support in ZMQ::Poller for pollables responding to fileno and socket.
11
+ Standard Ruby Sockets and IOs can be now registered in poller to listen for
12
+ events. Thanks to Pawel Pacana for this code contribution.
13
+
14
+ * Fixed a bug in ZMQ::Poller#deregister where it would raise exception
15
+ when trying to deregister already closed ZMQ socket. Issue 59.
16
+
17
+ * Improved specs to use random inproc socket address to avoid race conditions
18
+ between tests under same context.
19
+
20
+ * Added continous integration for all supported platforms on Travis-CI.
21
+ Thanks to Pawel Pacana for this code contribution.
22
+
23
+ * Signed up for codeclimate.com and made some code changes to get a better
24
+ "grade" from it.
25
+
26
+ * Modified the library to *always* load the 'ffi' library upon startup. It
27
+ used to be conditional for Rubinius. Thanks to brixen for the change.
28
+
29
+ * There was a little bit of churn on the zmq "monitor" api. Thanks to
30
+ Nilson Santos F. Jr. for some code to conditionally attach to the
31
+ appropriate api depending on library version.
32
+
33
+
34
+
1
35
  == 0.9.6 / 20120808
2
36
  * Never released 0.9.5 as a gem. It was available via github only.
3
37
 
data/README.rdoc CHANGED
@@ -13,56 +13,18 @@ This single gem supports 0mq 2.x and 3.1.x 0mq APIs. The 0mq project started
13
13
  making backward-incompatible changes to the API with the 3.1.x release.
14
14
  The gem auto-configures itself to expose the API conforming to the loaded
15
15
  C library. 0mq API 3.0 is *not* supported; the 0mq community voted to
16
- abandon it.
16
+ abandon it.
17
17
 
18
18
  The impetus behind this library was to provide support for ZeroMQ in
19
19
  JRuby which has native threads. Unlike MRI, which has a GIL, JRuby and
20
- Rubinius allow for threaded access to Ruby code from outside extensions.
21
- ZeroMQ is heavily threaded, so until the MRI runtime removes its GIL,
20
+ Rubinius allow for threaded access to Ruby code from outside extensions.
21
+ ZeroMQ is heavily threaded, so until the MRI runtime removes its GIL,
22
22
  JRuby and Rubinius will likely be the best environments to run this library.
23
23
 
24
- == Breaking API Changes from 0.8.x to 0.9.0
24
+ Please read the History.txt file for a description of all changes, including
25
+ API changes, since the last release!
25
26
 
26
- There has been a major change in API from the 0.8.x series to 0.9.0.
27
- Previously the Socket#send and Socket#recv methods could raise exceptions
28
- when there was an error. They also returned true or false depending on
29
- the success or failure of the operation. The exceptions were also used
30
- for managing flow control when doing non-blocking send/recv.
31
-
32
- Mixing and matching return codes and exceptions is a terrible idea in
33
- practice. Using them for flow control is an even worse sin. So all of
34
- the exception code from Socket has been removed.
35
-
36
- The Poller and Message class have also had their exceptions removed for
37
- returning errors on instance methods.
38
-
39
- Unfortunately, it isn't possible to indicate that a call to #new has failed
40
- by returning nil. A call to #new that fails needs to raise an exception to
41
- indicate failure. (This isn't strictly true; this behavior can be changed
42
- but it is not a standard Ruby idiom and is therefore a surprising, and
43
- poor, thing to do.) Classes that formerly raised exceptions during allocation
44
- now offer a factory method #create that will either return a successfully
45
- constructed object or nil. Code should check for nil returns before using
46
- the object.
47
-
48
- This is a *breaking* change. I'm sorry but the old API's inconsistency was
49
- causing too many problems. It now more closely mimics the 0mq C API. IF YOU
50
- PREFER THE ORIGINAL API WHICH WAS CLOSER TO IDIOMATIC RUBY, IT SHOULD BE
51
- EASY TO WRAP THESE CLASSES UP TO PROVIDE A MORE IDIOMATIC API. I SUGGEST
52
- YOU CREATE A PATCH *OR* CREATE A SEPARATE GEM TO WRAP THIS ONE. Sorry for
53
- shouting but I wanted to make sure this stood out.
54
-
55
- All example code has been updated to use the new Ruby API.
56
-
57
- == Breaking API Change from 0.9.3 to 0.9.5
58
-
59
- The 0mq library functions zmq_send() and zmq_recv() were changed to
60
- zmq_sendmsg() and zmq_recvmsg() with the 0mq 3.x API change. I have changed
61
- the binding to always use #sendmsg and #recvmsg. This breaks existing code.
62
- This should be the last breaking change heading into the 1.0 release of these
63
- bindings.
64
-
65
- == PERFORMANCE
27
+ == PERFORMANCE:
66
28
 
67
29
  Check out the latest performance results:
68
30
 
@@ -72,7 +34,7 @@ Check out the latest performance results:
72
34
 
73
35
  This gem needs more tests. This gem has been battle tested by myself
74
36
  and others for over a year, so I am fairly confident that it is solid.
75
- However, it is inevitable that there will be bugs, so please open
37
+ However, it is inevitable that there will be bugs, so please open
76
38
  issues for them here or fork this project, fix them, and send me a pull
77
39
  request.
78
40
 
@@ -83,76 +45,82 @@ stability.
83
45
 
84
46
  All features are implemented.
85
47
 
48
+ == BUILD STATUS:
49
+
50
+ {<img src="https://secure.travis-ci.org/chuckremes/ffi-rzmq.png?branch=master" alt="Build Status" />}[http://travis-ci.org/chuckremes/ffi-rzmq]
51
+
52
+ {<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/chuckremes/ffi-rzmq]
53
+
86
54
  == SYNOPSIS:
87
55
 
88
56
  0mq API v2 client code:
89
-
57
+
90
58
  require 'rubygems'
91
59
  require 'ffi-rzmq'
92
-
60
+
93
61
  if ARGV.length < 3
94
62
  puts "usage: local_lat <connect-to> <message-size> <roundtrip-count>"
95
63
  exit
96
64
  end
97
-
65
+
98
66
  bind_to = ARGV[0]
99
67
  message_size = ARGV[1].to_i
100
68
  roundtrip_count = ARGV[2].to_i
101
-
69
+
102
70
  ctx = ZMQ::Context.new
103
71
  s = ctx.socket ZMQ::REP
104
72
  rc = s.setsockopt(ZMQ::HWM, 100)
105
73
  rc = s.bind(bind_to)
106
-
74
+
107
75
  msg = ""
108
76
  roundtrip_count.times do
109
77
  rc = s.recv_string msg
110
78
  raise "Message size doesn't match, expected [#{message_size}] but received [#{msg.size}]" if message_size != msg.size
111
79
  rc = s.send_string msg, 0
112
80
  end
113
-
81
+
114
82
 
115
83
  0mq API v2 server code:
116
84
 
117
85
  require 'rubygems'
118
86
  require 'ffi-rzmq'
119
-
87
+
120
88
  if ARGV.length < 3
121
89
  puts "usage: remote_lat <connect-to> <message-size> <roundtrip-count>"
122
90
  exit
123
91
  end
124
-
92
+
125
93
  connect_to = ARGV[0]
126
94
  message_size = ARGV[1].to_i
127
95
  roundtrip_count = ARGV[2].to_i
128
-
96
+
129
97
  ctx = ZMQ::Context.new
130
98
  s = ctx.socket ZMQ::REQ
131
99
  rc = s.connect(connect_to)
132
-
100
+
133
101
  msg = "#{ '3' * message_size }"
134
-
102
+
135
103
  start_time = Time.now
136
-
104
+
137
105
  msg = ""
138
106
  roundtrip_count.times do
139
107
  rc = s.send_string msg, 0
140
108
  rc = s.recv_string msg
141
109
  raise "Message size doesn't match, expected [#{message_size}] but received [#{msg.size}]" if message_size != msg.size
142
110
  end
143
-
111
+
144
112
  == Better Examples
145
113
 
146
114
  I highly recommend visiting the Learn Ruby 0mq project for a bunch of good code examples.
147
115
 
148
116
  http://github.com/andrewvc/learn-ruby-zeromq
149
-
117
+
150
118
 
151
119
 
152
120
  == REQUIREMENTS:
153
121
 
154
- * 0mq 2.1.x, 3.1.x or later; 2.0.x and 3.0.x are no longer supported
155
-
122
+ * 0mq 2.2.x, 3.2.x or later; 2.0.x, 3.0.x and 3.1.x are no longer supported
123
+
156
124
  The ZeroMQ library must be installed on your system in a well-known location
157
125
  like /usr/local/lib. This is the default for new ZeroMQ installs.
158
126
 
@@ -162,7 +130,7 @@ Future releases may include the library as a C extension built at
162
130
  time of installation.
163
131
 
164
132
  * ffi (>= 1.0.0)
165
-
133
+
166
134
  This is a requirement for MRI only. Both Rubinius and JRuby have FFI support built
167
135
  in as a standard component. Do *not* run this gem under MRI with an old 'ffi' gem.
168
136
  It will crash randomly and you will be sad.
@@ -182,18 +150,18 @@ To build from git master:
182
150
  % cd ffi-rzmq
183
151
  % gem build ffi-rzmq.gemspec
184
152
  % gem install ffi-rzmq-*.gem
185
-
153
+
186
154
 
187
155
  NOTE for Windows users!
188
156
  In order for this gem to find the libzmq.dll, it *must* be on the Windows PATH. Google
189
157
  for "modify windows path" for instructions on how to do that if you are unfamiliar with
190
- that activity.
158
+ that activity. That DLL also requires that you copy libstdc++-6.dll and libgcc_s_sjlj-1.dll from DevKit MinGW into the same folder that you copied libzmq.dll.
191
159
 
192
160
  == LICENSE:
193
161
 
194
162
  (The MIT License)
195
163
 
196
- Copyright (c) 2011 Chuck Remes
164
+ Copyright (c) 2013 Chuck Remes
197
165
 
198
166
  Permission is hereby granted, free of charge, to any person obtaining
199
167
  a copy of this software and associated documentation files (the
data/ffi-rzmq.gemspec CHANGED
@@ -11,8 +11,8 @@ Gem::Specification.new do |s|
11
11
  s.summary = %q{This gem wraps the ZeroMQ (0mq) networking library using Ruby FFI (foreign function interface).}
12
12
  s.description = %q{This gem wraps the ZeroMQ networking library using the ruby FFI (foreign
13
13
  function interface). It's a pure ruby wrapper so this gem can be loaded
14
- and run by any ruby runtime that supports FFI. That's all of them -
15
- MRI 1.9.x, Rubinius and JRuby.}
14
+ and run by any ruby runtime that supports FFI. That's all of the major ones -
15
+ MRI, Rubinius and JRuby.}
16
16
 
17
17
  s.rubyforge_project = "ffi-rzmq"
18
18
 
data/lib/ffi-rzmq.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  module ZMQ
3
2
 
4
3
  # :stopdoc:
@@ -64,12 +63,10 @@ end # module ZMQ
64
63
  # some code is conditionalized based upon what ruby engine we are
65
64
  # executing
66
65
 
67
- RBX = defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/ ? true : false
68
-
69
- require 'ffi' unless RBX
66
+ require 'ffi'
70
67
 
71
68
  # the order of files is important
72
69
  #%w(wrapper zmq exceptions context message socket poll_items poll device).each do |file|
73
- %w(libc libzmq constants util exceptions context message socket poll_items poll device).each do |file|
70
+ %w(libc libzmq constants util exceptions context message socket poll_items poll_item poll device).each do |file|
74
71
  require ZMQ.libpath(['ffi-rzmq', file])
75
72
  end
@@ -215,10 +215,17 @@ module ZMQ
215
215
  attach_function :zmq_msg_get, [:pointer, :int], :int
216
216
  @blocking = true
217
217
  attach_function :zmq_msg_set, [:pointer, :int, :int], :int
218
-
218
+
219
219
  # Monitoring API
220
- @blocking = true
221
- attach_function :zmq_ctx_set_monitor, [:pointer, :pointer], :int
220
+ # zmq_ctx_set_monitor is no longer supported as of version >= 3.2.1
221
+ # replaced by zmq_socket_monitor
222
+ if LibZMQ.version[:minor] > 2 || (LibZMQ.version[:minor] == 2 && LibZMQ.version[:patch] >= 1)
223
+ @blocking = true
224
+ attach_function :zmq_socket_monitor, [:pointer, :pointer, :int], :int
225
+ else
226
+ @blocking = true
227
+ attach_function :zmq_ctx_set_monitor, [:pointer, :pointer], :int
228
+ end
222
229
 
223
230
  # Socket API
224
231
  @blocking = true
@@ -233,7 +240,7 @@ module ZMQ
233
240
  attach_function :zmq_sendmsg, [:pointer, :pointer, :int], :int
234
241
  @blocking = true
235
242
  attach_function :zmq_send, [:pointer, :pointer, :size_t, :int], :int
236
-
243
+
237
244
  module EventDataLayout
238
245
  def self.included(base)
239
246
  base.class_eval do
@@ -259,7 +266,7 @@ module ZMQ
259
266
 
260
267
  def to_s; inspect; end
261
268
  end # class EventData
262
-
269
+
263
270
  end
264
271
  end
265
272
 
data/lib/ffi-rzmq/poll.rb CHANGED
@@ -1,14 +1,14 @@
1
+ require 'forwardable'
1
2
 
2
3
  module ZMQ
3
-
4
4
  class Poller
5
+ extend Forwardable
5
6
 
7
+ def_delegators :@poll_items, :size, :inspect
6
8
  attr_reader :readables, :writables
7
9
 
8
10
  def initialize
9
- @items = ZMQ::PollItems.new
10
- @raw_to_socket = {}
11
- @sockets = []
11
+ @poll_items = ZMQ::PollItems.new
12
12
  @readables = []
13
13
  @writables = []
14
14
  end
@@ -28,8 +28,8 @@ module ZMQ
28
28
  # frequency.
29
29
  #
30
30
  # Returns 0 when there are no registered sockets that are readable
31
- # or writable.
32
- #
31
+ # or writable.
32
+ #
33
33
  # Return 1 (or greater) to indicate the number of readable or writable
34
34
  # sockets. These sockets should be processed using the #readables and
35
35
  # #writables accessors.
@@ -38,14 +38,11 @@ module ZMQ
38
38
  # error number.
39
39
  #
40
40
  def poll timeout = :blocking
41
- unless @items.empty?
41
+ unless @poll_items.empty?
42
42
  timeout = adjust timeout
43
- items_triggered = LibZMQ.zmq_poll @items.address, @items.size, timeout
44
-
45
- if Util.resultcode_ok?(items_triggered)
46
- update_selectables
47
- end
48
-
43
+ items_triggered = LibZMQ.zmq_poll @poll_items.address, @poll_items.size, timeout
44
+
45
+ update_selectables if Util.resultcode_ok?(items_triggered)
49
46
  items_triggered
50
47
  else
51
48
  0
@@ -62,131 +59,85 @@ module ZMQ
62
59
  poll 0
63
60
  end
64
61
 
65
- # Register the +sock+ for +events+. This method is idempotent meaning
62
+ # Register the +pollable+ for +events+. This method is idempotent meaning
66
63
  # it can be called multiple times with the same data and the socket
67
64
  # will only get registered at most once. Calling multiple times with
68
65
  # different values for +events+ will OR the event information together.
69
66
  #
70
- def register sock, events = ZMQ::POLLIN | ZMQ::POLLOUT, fd = 0
71
- return false if (sock.nil? && fd.zero?) || events.zero?
67
+ def register pollable, events = ZMQ::POLLIN | ZMQ::POLLOUT
68
+ return if pollable.nil? || events.zero?
72
69
 
73
- item = @items.get(@sockets.index(sock))
74
-
75
- unless item
76
- @sockets << sock
77
- item = LibZMQ::PollItem.new
78
-
79
- if sock.kind_of?(ZMQ::Socket) || sock.kind_of?(Socket)
80
- item[:socket] = sock.socket
81
- item[:fd] = 0
82
- else
83
- item[:socket] = FFI::MemoryPointer.new(0)
84
- item[:fd] = fd
85
- end
86
-
87
- @raw_to_socket[item.socket.address] = sock
88
- @items << item
70
+ unless item = @poll_items[pollable]
71
+ item = PollItem.from_pollable(pollable)
72
+ @poll_items << item
89
73
  end
90
74
 
91
- item[:events] |= events
75
+ item.events |= events
92
76
  end
93
77
 
94
- # Deregister the +sock+ for +events+. When there are no events left,
95
- # this also deletes the socket from the poll items.
78
+ # Deregister the +pollable+ for +events+. When there are no events left
79
+ # or socket has been closed this also deletes the socket from the poll items.
96
80
  #
97
- def deregister sock, events, fd = 0
98
- return unless sock || !fd.zero?
99
-
100
- item = @items.get(@sockets.index(sock))
81
+ def deregister pollable, events
82
+ return unless pollable
101
83
 
102
- if item && (item[:events] & events) > 0
103
- # change the value in place
104
- item[:events] ^= events
105
-
106
- delete sock if item[:events].zero?
84
+ item = @poll_items[pollable]
85
+ if item && (item.events & events) > 0
86
+ item.events ^= events
87
+ delete(pollable) if item.events.zero? || item.closed?
107
88
  true
108
89
  else
109
90
  false
110
91
  end
111
92
  end
112
93
 
113
- # A helper method to register a +sock+ as readable events only.
94
+ # A helper method to register a +pollable+ as readable events only.
114
95
  #
115
- def register_readable sock
116
- register sock, ZMQ::POLLIN, 0
96
+ def register_readable pollable
97
+ register pollable, ZMQ::POLLIN
117
98
  end
118
99
 
119
- # A helper method to register a +sock+ for writable events only.
100
+ # A helper method to register a +pollable+ for writable events only.
120
101
  #
121
- def register_writable sock
122
- register sock, ZMQ::POLLOUT, 0
102
+ def register_writable pollable
103
+ register pollable, ZMQ::POLLOUT
123
104
  end
124
105
 
125
- # A helper method to deregister a +sock+ for readable events.
106
+ # A helper method to deregister a +pollable+ for readable events.
126
107
  #
127
- def deregister_readable sock
128
- deregister sock, ZMQ::POLLIN, 0
108
+ def deregister_readable pollable
109
+ deregister pollable, ZMQ::POLLIN
129
110
  end
130
111
 
131
- # A helper method to deregister a +sock+ for writable events.
112
+ # A helper method to deregister a +pollable+ for writable events.
132
113
  #
133
- def deregister_writable sock
134
- deregister sock, ZMQ::POLLOUT, 0
114
+ def deregister_writable pollable
115
+ deregister pollable, ZMQ::POLLOUT
135
116
  end
136
117
 
137
- # Deletes the +sock+ for all subscribed events. Called internally
118
+ # Deletes the +pollable+ for all subscribed events. Called internally
138
119
  # when a socket has been deregistered and has no more events
139
120
  # registered anywhere.
140
121
  #
141
122
  # Can also be called directly to remove the socket from the polling
142
123
  # array.
143
124
  #
144
- def delete sock
145
- unless (size = @sockets.size).zero?
146
- @sockets.delete_if { |socket| socket.socket.address == sock.socket.address }
147
- socket_deleted = size != @sockets.size
148
-
149
- item_deleted = @items.delete sock
150
-
151
- raw_deleted = @raw_to_socket.delete(sock.socket.address)
152
-
153
- socket_deleted && item_deleted && raw_deleted
154
-
155
- else
156
- false
157
- end
125
+ def delete pollable
126
+ return false if @poll_items.empty?
127
+ @poll_items.delete(pollable)
158
128
  end
159
129
 
160
- def size(); @items.size; end
161
-
162
- def inspect
163
- @items.inspect
164
- end
165
-
166
- def to_s(); inspect; end
167
-
130
+ def to_s inspect; end
168
131
 
169
132
  private
170
133
 
171
- def items_hash hash
172
- @items.each do |poll_item|
173
- hash[@raw_to_socket[poll_item.socket.address]] = poll_item
174
- end
175
- end
176
-
177
134
  def update_selectables
178
135
  @readables.clear
179
136
  @writables.clear
180
137
 
181
- @items.each do |poll_item|
182
- #FIXME: spec for sockets *and* file descriptors
183
- if poll_item.readable?
184
- @readables << (poll_item.socket.address.zero? ? poll_item.fd : @raw_to_socket[poll_item.socket.address])
185
- end
186
-
187
- if poll_item.writable?
188
- @writables << (poll_item.socket.address.zero? ? poll_item.fd : @raw_to_socket[poll_item.socket.address])
189
- end
138
+ @poll_items.each do |poll_item|
139
+ @readables << poll_item.pollable if poll_item.readable?
140
+ @writables << poll_item.pollable if poll_item.writable?
190
141
  end
191
142
  end
192
143
 
@@ -198,6 +149,7 @@ module ZMQ
198
149
  # Users will pass in values measured as
199
150
  # milliseconds, so we need to convert that value to
200
151
  # microseconds for the library.
152
+ #
201
153
  if LibZMQ.version2?
202
154
  def adjust timeout
203
155
  if :blocking == timeout || -1 == timeout
@@ -216,6 +168,6 @@ module ZMQ
216
168
  end
217
169
  end
218
170
  end
219
- end
220
171
 
221
- end # module ZMQ
172
+ end
173
+ end