zmqmachine 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/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