zmqmachine 0.3.2 → 0.4.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,19 @@
1
+ == 0.4.0 / 2010-12-16
2
+ * Replaced SortedSet in Timers with an Array and a custom routine
3
+ for finding the in-order index for an insert. The routine
4
+ uses a binary search algo so it can find the proper index in
5
+ O(nlog n) time. This resulted in a 2 order of magnitude perf
6
+ increase when using more than a handful of timers.
7
+ * Modified the default reactor poll interval to 10ms from 100usec.
8
+ Also, fixed the poll routine so that it sleeps for poll_interval
9
+ when there are no procs scheduled and there are no sockets
10
+ registered. With no sockets, the call to Poller#poll returns
11
+ immediately. This was showing as a busy loop and pushing CPU
12
+ to 100% for some users.
13
+ With this change, timers now have a minimum *default* resolution
14
+ of 10 milliseconds. The poll interval can be overridden and set to
15
+ a minimum of 1ms for better timing controls.
16
+
1
17
  == 0.3.2 / 2010-08-25
2
18
  * Fixed a bug in Timers where the timers were never getting removed
3
19
  after they fired. Bug was caused by a Ruby bug with #delete_if. While
data/README.rdoc CHANGED
@@ -20,7 +20,7 @@ descriptors. This isn't on my roadmap but patches are accepted.
20
20
 
21
21
  == FEATURES/PROBLEMS:
22
22
 
23
- * No specs yet.
23
+ * Very few specs.
24
24
 
25
25
  * Documentation is limited. I need to write up a lot more detail on the Handler classes passed
26
26
  to socket instances and how this differs from the Eventmachine way.
@@ -41,18 +41,20 @@ Read and execute the examples in the examples directory.
41
41
 
42
42
  Requires the 0mq library
43
43
 
44
- * 0mq 2.0.7
44
+ * 0mq 2.0.10 or 2.1 and later
45
45
 
46
46
  Depends on 2 external gems.
47
47
 
48
- * ffi-rzmq (>= 0.5.0)
49
- * ffi (> 0.6.3) (built from master for threading fixes)
48
+ * ffi-rzmq (>= 0.7.0)
49
+ * ffi (>= 1.0.0)
50
50
 
51
51
  == INSTALL:
52
52
 
53
53
  Make sure the 0MQ library is already installed on your system. Secondly,
54
- make sure the FFI gem is built from its project master (see Requirements).
55
- Lastly, verify the ffi-rzmq gem is built from its project master.
54
+ verify the ffi-rzmq gem is installed (available from rubygems.org).
55
+
56
+ Lastly, install the zmqmachine gem from rubygems.org. Alternately, build
57
+ and install directly from a cloned git repository.
56
58
 
57
59
  % git clone github.com/chuckremes/zmqmachine.git
58
60
  % cd zmqmachine
data/Rakefile CHANGED
@@ -16,6 +16,6 @@ Bones {
16
16
  ignore_file '.gitignore'
17
17
  readme_file 'README.rdoc'
18
18
 
19
- depend_on 'ffi-rzmq', '>= 0.5.0'
19
+ depend_on 'ffi-rzmq', '>= 0.7.0'
20
20
  }
21
21
 
@@ -21,11 +21,9 @@ class PublisherHandler
21
21
  def on_attach socket
22
22
  address = ZM::Address.new '127.0.0.1', @port, :tcp
23
23
  rc = socket.connect address
24
- # puts "publisher on_attach rc [#{rc}]"
25
24
  end
26
25
 
27
26
  def on_writable socket
28
- # puts "publisher writing..."
29
27
  topic = @topics[rand(@topics.size)]
30
28
  symbol = topic.split('.').first
31
29
 
@@ -56,7 +54,6 @@ class SubscriberHandler
56
54
  @ports.each do |port|
57
55
  address = ZM::Address.new '127.0.0.1', port, :tcp
58
56
  rc = socket.connect address
59
- # puts "subscriber on_attach rc [#{rc}]"
60
57
 
61
58
  @topics.each do |topic|
62
59
  puts "subscribe to [#{topic}]"
@@ -83,12 +80,6 @@ ctx1 = ZM::Reactor.new(:A).run do |context|
83
80
 
84
81
  forwarder = ZM::Device::Forwarder.new context, incoming, outgoing
85
82
  puts "forwarder started"
86
-
87
- # context.oneshot_timer(3000) do
88
- # puts "reactor one shutting down..."
89
- # context.stop
90
- # puts "reactor one shut down"
91
- # end
92
83
  end
93
84
 
94
85
  # Or, run each handler in separate contexts each with its
@@ -118,12 +109,6 @@ ctx2 = ZM::Reactor.new(:B).run do |context|
118
109
  @sub5_handler = SubscriberHandler.new context, [5556], 'futures.us.'
119
110
  context.sub_socket @sub5_handler
120
111
  end
121
-
122
- # context.oneshot_timer(sleep_time * 1000) do
123
- # puts "reactor two shutting down..."
124
- # context.stop
125
- # puts "reactor two shut down"
126
- # end
127
112
  end
128
113
 
129
114
  # let's see how many messages we can publish in this many seconds
@@ -65,10 +65,10 @@ module ZMQMachine
65
65
  class Handler
66
66
  attr_accessor :socket_out
67
67
 
68
- def initialize reactor, address, debug = false
68
+ def initialize reactor, address, verbose = false
69
69
  @reactor = reactor
70
70
  @address = address
71
- @debug = debug
71
+ @verbose = verbose
72
72
  end
73
73
 
74
74
  def on_attach socket
@@ -84,7 +84,7 @@ module ZMQMachine
84
84
  end
85
85
 
86
86
  def on_readable socket, messages
87
- messages.each { |msg| p msg.copy_out_string } if @debug
87
+ messages.each { |msg| puts "[fwd] [#{msg.copy_out_string}]" } if @verbose
88
88
 
89
89
  socket_out.send_messages messages if @socket_out
90
90
  end
@@ -96,13 +96,13 @@ module ZMQMachine
96
96
  #
97
97
  # Forwards all messages received by the +incoming+ address to the +outgoing+ address.
98
98
  #
99
- def initialize reactor, incoming, outgoing, debug = false
99
+ def initialize reactor, incoming, outgoing, verbose = false
100
100
  incoming = Address.from_string incoming if incoming.kind_of? String
101
101
  outgoing = Address.from_string outgoing if outgoing.kind_of? String
102
102
 
103
103
  # setup the handlers for processing messages
104
- @handler_in = Handler.new reactor, incoming, debug
105
- @handler_out = Handler.new reactor, outgoing, debug
104
+ @handler_in = Handler.new reactor, incoming, verbose
105
+ @handler_out = Handler.new reactor, outgoing, verbose
106
106
 
107
107
  # create each socket and pass in the appropriate handler
108
108
  @incoming = reactor.sub_socket @handler_in
@@ -67,10 +67,10 @@ module ZMQMachine
67
67
  class Handler
68
68
  attr_accessor :socket_out
69
69
 
70
- def initialize reactor, address, debug = false, dir = 0
70
+ def initialize reactor, address, verbose = false, dir = 0
71
71
  @reactor = reactor
72
72
  @address = address
73
- @debug = debug
73
+ @verbose = verbose
74
74
  @dir = dir
75
75
  end
76
76
 
@@ -85,10 +85,11 @@ module ZMQMachine
85
85
  end
86
86
 
87
87
  def on_readable socket, messages
88
- messages.each { |msg| puts "[#{@dir}] [#{msg.copy_out_string}]" } if @debug
88
+ messages.each { |msg| puts "[Q#{@dir}] [#{msg.copy_out_string}]" } if @verbose
89
89
 
90
90
  if @socket_out
91
- socket_out.send_messages messages
91
+ # FIXME: need to be able to handle EAGAIN/failed send
92
+ rc = socket_out.send_messages messages
92
93
  end
93
94
  end
94
95
  end # class Handler
@@ -99,13 +100,13 @@ module ZMQMachine
99
100
  #
100
101
  # Routes all messages received by either address to the other address.
101
102
  #
102
- def initialize reactor, incoming, outgoing, debug = false
103
+ def initialize reactor, incoming, outgoing, verbose = false
103
104
  incoming = Address.from_string incoming if incoming.kind_of? String
104
105
  outgoing = Address.from_string outgoing if outgoing.kind_of? String
105
106
 
106
107
  # setup the handlers for processing messages
107
- @handler_in = Handler.new reactor, incoming, debug, :in
108
- @handler_out = Handler.new reactor, outgoing, debug, :out
108
+ @handler_in = Handler.new reactor, incoming, verbose, :in
109
+ @handler_out = Handler.new reactor, outgoing, verbose, :out
109
110
 
110
111
  # create each socket and pass in the appropriate handler
111
112
  @incoming = reactor.xrep_socket @handler_in
data/lib/zm/reactor.rb CHANGED
@@ -40,9 +40,9 @@ module ZMQMachine
40
40
  attr_reader :name
41
41
 
42
42
  # +poll_interval+ is the number of milliseconds to block while
43
- # waiting for new 0mq socket events; default is 0
43
+ # waiting for new 0mq socket events; default is 10
44
44
  #
45
- def initialize name, poll_interval = 0
45
+ def initialize name, poll_interval = 10
46
46
  @name = name
47
47
  @running = false
48
48
  @thread = nil
@@ -80,7 +80,7 @@ module ZMQMachine
80
80
  @thread = Thread.new do
81
81
  blk.call self if blk
82
82
 
83
- while !@stopping && @running do
83
+ while !@stopping && running? do
84
84
  run_once
85
85
  end
86
86
 
@@ -114,7 +114,7 @@ module ZMQMachine
114
114
  def join delay = nil
115
115
  # don't allow the thread to try and join itself and only worry about
116
116
  # joining for live threads
117
- if @thread.alive? && @thread != Thread.current
117
+ if running? && @thread.alive? && @thread != Thread.current
118
118
  if delay
119
119
  # convert to seconds to meet the argument expectations of Thread#join
120
120
  seconds = delay / 1000.0
@@ -131,9 +131,11 @@ module ZMQMachine
131
131
  # and kill any pending I/O.
132
132
  #
133
133
  def kill
134
- @stopping = true
135
- @thread.kill
136
- cleanup
134
+ if running?
135
+ @stopping = true
136
+ @thread.kill
137
+ cleanup
138
+ end
137
139
  end
138
140
 
139
141
  # Schedules a proc or block to execute on the next trip through the
@@ -342,6 +344,13 @@ module ZMQMachine
342
344
  @timers.reschedule
343
345
  end
344
346
 
347
+ def list_timers
348
+ @timers.list.each do |timer|
349
+ name = timer.respond_to?(:name) ? timer.timer_proc.name : timer.timer_proc.to_s
350
+ puts "fire time [#{Time.at(timer.fire_time / 1000)}], method [#{name}]"
351
+ end
352
+ end
353
+
345
354
 
346
355
  private
347
356
 
@@ -379,7 +388,16 @@ module ZMQMachine
379
388
  end
380
389
 
381
390
  def poll
382
- @poller.poll @poll_interval
391
+ if (@proc_queue.empty? && @sockets.empty?) || @poller.size.zero?
392
+ # when there are no sockets registered, @poller.poll would return immediately;
393
+ # the same is true when sockets are registered but *not* for any events;
394
+ # doing so spikes the CPU even though there is no work to do
395
+ # take a short nap here (10ms by default) unless there are procs scheduled
396
+ # to run (e.g. via next_tick)
397
+ sleep(@poll_interval / 1000)
398
+ else
399
+ @poller.poll @poll_interval
400
+ end
383
401
 
384
402
  @poller.readables.each { |sock| @raw_to_socket[sock].resume_read }
385
403
  @poller.writables.each { |sock| @raw_to_socket[sock].resume_write }
@@ -398,10 +416,12 @@ module ZMQMachine
398
416
  end
399
417
 
400
418
 
401
- # Internally converts the number to microseconds
419
+ # Unnecessary to convert the number to microseconds; the ffi-rzmq
420
+ # library does this for us.
421
+ #
402
422
  def determine_interval interval
403
- # set a lower bound of 100 usec so we don't burn up the CPU
404
- interval <= 0 ? 100 : (interval * 1000).to_i
423
+ # set a lower bound of 1000 usec so we don't burn up the CPU
424
+ interval <= 0 ? 1.0 : interval.to_i
405
425
  end
406
426
 
407
427
  end # class Reactor
@@ -134,6 +134,9 @@ module ZMQMachine
134
134
  rc = send_message messages.at(i), true
135
135
  i += 1
136
136
  end
137
+
138
+ # FIXME: bug; if any of the message parts fail (rc != 0) we don't see that here; the
139
+ # #send_message function should capture exceptions and turn them into integers for bubbling
137
140
 
138
141
  # send the last message without the multipart arg to flush
139
142
  # the message to the 0mq queue
@@ -157,21 +160,26 @@ module ZMQMachine
157
160
  # was successfully dequeued. The use of rc here is really ugly and wrong.
158
161
  #
159
162
  def resume_read
160
- messages = []
161
- rc = read_message_part messages
162
- #puts "resume_read: rc1 [#{rc}], more_parts? [#{@raw_socket.more_parts?}]"
163
-
164
- while 0 == rc && @raw_socket.more_parts?
165
- #puts "get next part"
163
+ rc = 0
164
+
165
+ # loop and deliver all messages until the socket returns EAGAIN
166
+ while 0 == rc
167
+ messages = []
166
168
  rc = read_message_part messages
167
- #puts "resume_read: rc2 [#{rc}]"
169
+ #puts "resume_read: rc1 [#{rc}], more_parts? [#{@raw_socket.more_parts?}]"
170
+
171
+ while 0 == rc && @raw_socket.more_parts?
172
+ #puts "get next part"
173
+ rc = read_message_part messages
174
+ #puts "resume_read: rc2 [#{rc}]"
175
+ end
176
+ #puts "no more parts, ready to deliver"
177
+
178
+ # only deliver the messages when rc is 0; otherwise, we
179
+ # may have gotten EAGAIN and no message was read;
180
+ # don't deliver empty messages
181
+ deliver messages, rc if 0 == rc
168
182
  end
169
- #puts "no more parts, ready to deliver"
170
-
171
- # only deliver the messages when rc is 0; otherwise, we
172
- # may have gotten EAGAIN and no message was read;
173
- # don't deliver empty messages
174
- deliver messages, rc if 0 == rc
175
183
  end
176
184
 
177
185
  # Used by the reactor. Never called by user code.
data/lib/zm/timers.rb CHANGED
@@ -48,7 +48,11 @@ module ZMQMachine
48
48
  #
49
49
  class Timers
50
50
  def initialize
51
- @timers = SortedSet.new
51
+ @timers = []
52
+ end
53
+
54
+ def list
55
+ @timers
52
56
  end
53
57
 
54
58
  # Adds a non-periodical, one-shot timer in order of
@@ -63,7 +67,7 @@ module ZMQMachine
63
67
  return nil unless blk
64
68
 
65
69
  timer = Timer.new self, delay, false, blk
66
- @timers.add timer
70
+ add timer
67
71
  timer
68
72
  end
69
73
 
@@ -79,7 +83,7 @@ module ZMQMachine
79
83
  return nil unless blk
80
84
 
81
85
  timer = Timer.new self, delay, true, blk
82
- @timers.add timer
86
+ add timer
83
87
  timer
84
88
  end
85
89
 
@@ -90,7 +94,13 @@ module ZMQMachine
90
94
  # given +timer+.
91
95
  #
92
96
  def cancel timer
93
- @timers.delete(timer) ? true : false
97
+ i = index timer
98
+
99
+ if timer == @timers.at(i)
100
+ @timers.delete_at(i) ? true : false
101
+ else
102
+ false
103
+ end
94
104
  end
95
105
 
96
106
  # A convenience method that loops through all known timers
@@ -102,31 +112,35 @@ module ZMQMachine
102
112
  # is not yet expired; it knows all subsequent timers are not
103
113
  # expired too.
104
114
  #
115
+ # timers should be sorted by expiration time
116
+ # NOTE: was using #delete_if here, but it does *not* delete any
117
+ # items when the break executes before iterating through the entire
118
+ # set; that's unacceptable so I save each timer for deletion and
119
+ # do that in a separate loop
120
+ #
121
+ # Additionally, some timers may execute code paths that cancel other
122
+ # timers. If those timers are deleted while we are still iterating
123
+ # over them, the behavior is undefined (each runtime can handle it
124
+ # differently). To avoid that issue, we determine if they are expired
125
+ # and save them off for final processing outside of the loop. Any
126
+ # firing timer that deletes another timer will be safe.
127
+ #
105
128
  def fire_expired
106
129
  # all time is expected as milliseconds
107
130
  now = Timers.now
108
- save = []
109
- delete = []
110
-
111
- # timers should be sorted by expiration time
112
- # NOTE: was using #delete_if here, but it does *not* delete any
113
- # items when the break executes before iterating through the entire
114
- # set; that's unacceptable so I save each timer for deletion and
115
- # do that in a separate loop
116
- @timers.each do |timer|
131
+ runnables, periodicals, expired = [], [], []
132
+
133
+ # defer firing the timer until after this loop so we can clean it up first
134
+ @timers.each_with_index do |timer, index|
117
135
  break unless timer.expired?(now)
118
- timer.fire
119
- save << timer if timer.periodical?
120
- delete << timer
136
+ runnables << timer
137
+ periodicals << timer if timer.periodical?
138
+ expired << index
121
139
  end
122
140
 
123
- delete.each { |timer| @timers.delete timer }
124
-
125
- # reinstate the periodicals; necessary to do in two steps
126
- # since changing the timer.fire_time inside the loop would
127
- # not retain proper ordering in the sorted set; re-adding it
128
- # ensures the timers are in sorted order
129
- save.each { |timer| @timers.add timer }
141
+ remove expired
142
+ runnables.each { |timer| timer.fire }
143
+ renew periodicals
130
144
  end
131
145
 
132
146
  # Runs through all timers and asks each one to reschedule itself
@@ -138,7 +152,7 @@ module ZMQMachine
138
152
 
139
153
  timers.each do |timer|
140
154
  timer.reschedule
141
- @timers.add timer
155
+ add timer
142
156
  end
143
157
  end
144
158
 
@@ -160,6 +174,49 @@ module ZMQMachine
160
174
  def self.now_converted
161
175
  now / 1000.0
162
176
  end
177
+
178
+
179
+ private
180
+
181
+ # inserts in order using a binary search (O(nlog n)) to find the
182
+ # index to insert; this scales nicely for situations where there
183
+ # are many thousands thousands of timers
184
+ def add timer
185
+ i = index timer
186
+ @timers.insert(i, timer)
187
+ end
188
+
189
+ # Original Ruby source Posted by Sergey Chernov (sergeych) on 2010-05-13 20:23
190
+ # http://www.ruby-forum.com/topic/134477
191
+ #
192
+ # binary search; assumes underlying array is already sorted
193
+ def index value
194
+ l, r = 0, @timers.size - 1
195
+
196
+ while l <= r
197
+ m = (r + l) / 2
198
+ if value < @timers.at(m)
199
+ r = m - 1
200
+ else
201
+ l = m + 1
202
+ end
203
+ end
204
+ l
205
+ end
206
+
207
+ def remove expired
208
+ # need to reverse so we are deleting the highest indexes first,
209
+ # otherwise everything shifts down and we delete the wrong timers
210
+ expired.sort.reverse.each { |index| @timers.delete_at index }
211
+ end
212
+
213
+ def renew timers
214
+ # reinstate the periodicals; necessary to do in two steps
215
+ # since changing the timer.fire_time inside the loop (in parent) would
216
+ # not retain proper ordering in the sorted list; re-adding it
217
+ # ensures the timers are in sorted order
218
+ timers.each { |timer| add timer }
219
+ end
163
220
  end # class Timers
164
221
 
165
222
 
@@ -175,9 +232,9 @@ module ZMQMachine
175
232
  class Timer
176
233
  include Comparable
177
234
 
178
- attr_reader :fire_time
235
+ attr_reader :fire_time, :timer_proc
179
236
 
180
- # +time+ is in milliseconds
237
+ # +delay+ is in milliseconds
181
238
  #
182
239
  def initialize timers, delay, periodical, timer_proc = nil, &blk
183
240
  @timers = timers
@@ -212,7 +269,7 @@ module ZMQMachine
212
269
  # True when the timer should be fired; false otherwise.
213
270
  #
214
271
  def expired? time
215
- time ||= now
272
+ time ||= Timers.now
216
273
  time > @fire_time
217
274
  end
218
275
 
@@ -225,6 +282,12 @@ module ZMQMachine
225
282
  def reschedule
226
283
  schedule_firing_time
227
284
  end
285
+
286
+ def to_s
287
+ "[delay [#{@delay}], periodical? [#{@periodical}], fire_time [#{Time.at(@fire_time/1000)}] fire_delay_s [#{(@fire_time - Timers.now)/1000}]]"
288
+ end
289
+
290
+ def inspect; to_s; end
228
291
 
229
292
 
230
293
  private
data/version.txt CHANGED
@@ -1 +1 @@
1
- 0.3.2
1
+ 0.4.0
data/zmqmachine.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{zmqmachine}
5
- s.version = "0.3.2"
5
+ s.version = "0.4.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-08-25}
9
+ s.date = %q{2010-12-22}
10
10
  s.description = %q{ZMQMachine is another Ruby implementation of the reactor pattern but this
11
11
  time using 0mq sockets rather than POSIX sockets.
12
12
 
@@ -28,21 +28,21 @@ descriptors. This isn't on my roadmap but patches are accepted.}
28
28
  s.require_paths = ["lib"]
29
29
  s.rubyforge_project = %q{zmqmachine}
30
30
  s.rubygems_version = %q{1.3.7}
31
- s.summary = %q{ZMQMachine is another Ruby implementation of the reactor pattern but this time using 0mq sockets rather than POSIX sockets}
31
+ s.summary = %q{ZMQMachine is another Ruby implementation of the reactor pattern but this time using 0mq sockets rather than POSIX sockets.}
32
32
 
33
33
  if s.respond_to? :specification_version then
34
34
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
35
35
  s.specification_version = 3
36
36
 
37
37
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
38
- s.add_runtime_dependency(%q<ffi-rzmq>, [">= 0.5.0"])
39
- s.add_development_dependency(%q<bones>, [">= 3.4.7"])
38
+ s.add_runtime_dependency(%q<ffi-rzmq>, [">= 0.7.0"])
39
+ s.add_development_dependency(%q<bones>, [">= 3.5.4"])
40
40
  else
41
- s.add_dependency(%q<ffi-rzmq>, [">= 0.5.0"])
42
- s.add_dependency(%q<bones>, [">= 3.4.7"])
41
+ s.add_dependency(%q<ffi-rzmq>, [">= 0.7.0"])
42
+ s.add_dependency(%q<bones>, [">= 3.5.4"])
43
43
  end
44
44
  else
45
- s.add_dependency(%q<ffi-rzmq>, [">= 0.5.0"])
46
- s.add_dependency(%q<bones>, [">= 3.4.7"])
45
+ s.add_dependency(%q<ffi-rzmq>, [">= 0.7.0"])
46
+ s.add_dependency(%q<bones>, [">= 3.5.4"])
47
47
  end
48
48
  end
metadata CHANGED
@@ -3,48 +3,50 @@ name: zmqmachine
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 0
7
- - 3
8
- - 2
9
- version: 0.3.2
6
+ - 0
7
+ - 4
8
+ - 0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
- - Chuck Remes
12
+ - Chuck Remes
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-08-25 00:00:00 -05:00
17
+ date: 2010-12-22 00:00:00 -06:00
18
18
  default_executable:
19
19
  dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: ffi-rzmq
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- - 5
30
- - 0
31
- version: 0.5.0
32
- type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: bones
36
- prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 3
43
- - 4
44
- - 7
45
- version: 3.4.7
46
- type: :development
47
- version_requirements: *id002
20
+ - !ruby/object:Gem::Dependency
21
+ name: ffi-rzmq
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 7
31
+ - 0
32
+ version: 0.7.0
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: bones
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 3
45
+ - 5
46
+ - 4
47
+ version: 3.5.4
48
+ type: :development
49
+ version_requirements: *id002
48
50
  description: |-
49
51
  ZMQMachine is another Ruby implementation of the reactor pattern but this
50
52
  time using 0mq sockets rather than POSIX sockets.
@@ -65,73 +67,75 @@ executables: []
65
67
  extensions: []
66
68
 
67
69
  extra_rdoc_files:
68
- - History.txt
69
- - README.rdoc
70
- - version.txt
70
+ - History.txt
71
+ - README.rdoc
72
+ - version.txt
71
73
  files:
72
- - .bnsignore
73
- - History.txt
74
- - README.rdoc
75
- - Rakefile
76
- - examples/fake_ftp.rb
77
- - examples/one_handed_ping_pong.rb
78
- - examples/ping_pong.rb
79
- - examples/pub_sub.rb
80
- - examples/pubsub_forwarder.rb
81
- - examples/throttled_ping_pong.rb
82
- - lib/zm/address.rb
83
- - lib/zm/deferrable.rb
84
- - lib/zm/devices.rb
85
- - lib/zm/devices/forwarder.rb
86
- - lib/zm/devices/queue.rb
87
- - lib/zm/exceptions.rb
88
- - lib/zm/message.rb
89
- - lib/zm/reactor.rb
90
- - lib/zm/sockets.rb
91
- - lib/zm/sockets/base.rb
92
- - lib/zm/sockets/pair.rb
93
- - lib/zm/sockets/pub.rb
94
- - lib/zm/sockets/rep.rb
95
- - lib/zm/sockets/req.rb
96
- - lib/zm/sockets/sub.rb
97
- - lib/zm/sockets/xrep.rb
98
- - lib/zm/sockets/xreq.rb
99
- - lib/zm/timers.rb
100
- - lib/zmqmachine.rb
101
- - spec/spec_helper.rb
102
- - spec/zmqmachine_spec.rb
103
- - version.txt
104
- - zmqmachine.gemspec
74
+ - .bnsignore
75
+ - History.txt
76
+ - README.rdoc
77
+ - Rakefile
78
+ - examples/fake_ftp.rb
79
+ - examples/one_handed_ping_pong.rb
80
+ - examples/ping_pong.rb
81
+ - examples/pub_sub.rb
82
+ - examples/pubsub_forwarder.rb
83
+ - examples/throttled_ping_pong.rb
84
+ - lib/zm/address.rb
85
+ - lib/zm/deferrable.rb
86
+ - lib/zm/devices.rb
87
+ - lib/zm/devices/forwarder.rb
88
+ - lib/zm/devices/queue.rb
89
+ - lib/zm/exceptions.rb
90
+ - lib/zm/message.rb
91
+ - lib/zm/reactor.rb
92
+ - lib/zm/sockets.rb
93
+ - lib/zm/sockets/base.rb
94
+ - lib/zm/sockets/pair.rb
95
+ - lib/zm/sockets/pub.rb
96
+ - lib/zm/sockets/rep.rb
97
+ - lib/zm/sockets/req.rb
98
+ - lib/zm/sockets/sub.rb
99
+ - lib/zm/sockets/xrep.rb
100
+ - lib/zm/sockets/xreq.rb
101
+ - lib/zm/timers.rb
102
+ - lib/zmqmachine.rb
103
+ - spec/spec_helper.rb
104
+ - spec/zmqmachine_spec.rb
105
+ - version.txt
106
+ - zmqmachine.gemspec
105
107
  has_rdoc: true
106
108
  homepage: http://github.com/chuckremes/zmqmachine
107
109
  licenses: []
108
110
 
109
111
  post_install_message:
110
112
  rdoc_options:
111
- - --main
112
- - README.rdoc
113
+ - --main
114
+ - README.rdoc
113
115
  require_paths:
114
- - lib
116
+ - lib
115
117
  required_ruby_version: !ruby/object:Gem::Requirement
118
+ none: false
116
119
  requirements:
117
- - - ">="
118
- - !ruby/object:Gem::Version
119
- segments:
120
- - 0
121
- version: "0"
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ segments:
123
+ - 0
124
+ version: "0"
122
125
  required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
123
127
  requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- segments:
127
- - 0
128
- version: "0"
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ segments:
131
+ - 0
132
+ version: "0"
129
133
  requirements: []
130
134
 
131
135
  rubyforge_project: zmqmachine
132
- rubygems_version: 1.3.6
136
+ rubygems_version: 1.3.7
133
137
  signing_key:
134
138
  specification_version: 3
135
- summary: ZMQMachine is another Ruby implementation of the reactor pattern but this time using 0mq sockets rather than POSIX sockets
139
+ summary: ZMQMachine is another Ruby implementation of the reactor pattern but this time using 0mq sockets rather than POSIX sockets.
136
140
  test_files: []
137
141