cztop-reactor 0.1.0.pre20170316155217 → 0.1.0.pre20170323172345

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ff9e9366325f56b5134fb0c8b7123c90b259709
4
- data.tar.gz: f1effb0b47c1199772305b414d2f31e34bdb7798
3
+ metadata.gz: 693a140ab57c4d6cd02f56f750474f7b8d2b1da1
4
+ data.tar.gz: c56488274eece275fab5ec9d5383d3956f6faf4e
5
5
  SHA512:
6
- metadata.gz: 41e02a93aab2823b3dd3b6d05e2da1a15d873f99cf1efaa4068a7b632ee595b2641d0bda7a5d13b43eb931095235000edfb93a9daadb71d7517187530ffcdda6
7
- data.tar.gz: 3e391f785107c50fa41f4a4bb761fc1ad14cef76411cb3bb52dfb61d58a952376294a0d9aa86f0c81487984e8f5d9bfb2e0b48a35d9c2b17dbd2e5a91180a006
6
+ metadata.gz: 5b1fce6cca68d902057ffd8efd008e14da2cb5ed14adf121f8af406c8f4fb1c9429598085dfb379f2ce357ec0ea51524753576e79ac0fe0aabdf0af92e56d10f
7
+ data.tar.gz: 26f53aa35c4762e46fc42add8cbe732a6b66c24896df5ddb35d997883a12dc3fcc4521a9b82f623c612fc41039c7b343af6ef7fb46724b800c6cbe0c3be60848
data/ChangeLog CHANGED
@@ -1,12 +1,29 @@
1
+ 2017-03-27 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ * .gems:
4
+ Fix fivefish gem name in gemset
5
+ [27fcb613383f] [tip]
6
+
7
+ 2017-03-22 Michael Granger <ged@FaerieMUD.org>
8
+
9
+ * .hoerc, cztop-reactor.gemspec, lib/cztop/reactor.rb,
10
+ spec/cztop/reactor_spec.rb:
11
+ Allow a handler object instead of a block.
12
+ [10904c471caa] [github/master]
13
+
1
14
  2017-03-16 Michael Granger <ged@FaerieMUD.org>
2
15
 
16
+ * Rakefile, cztop-reactor.gemspec:
17
+ Add missing dependency on timers.
18
+ [962f88d917bf]
19
+
3
20
  * .hgignore:
4
21
  Ignore built gems
5
- [594168b03b71] [tip]
22
+ [594168b03b71]
6
23
 
7
24
  * README.md:
8
25
  Fix link in the README
9
- [0391133d132d] [github/master]
26
+ [0391133d132d]
10
27
 
11
28
  * .hgignore:
12
29
  Ignore generated docs directory
data/lib/cztop/reactor.rb CHANGED
@@ -100,7 +100,12 @@ class CZTop::Reactor
100
100
  ### event/handler+arguments pairs associated with the handle.
101
101
  ###
102
102
  def register( socket, *events, &handler )
103
- raise LocalJumpError, "no handler given" unless handler
103
+ if !events.empty? && !events.last.is_a?( Symbol )
104
+ handler_obj = events.pop
105
+ handler = handler_obj.method( :handle_io_event )
106
+ end
107
+
108
+ raise LocalJumpError, "no block or handler given" unless handler
104
109
 
105
110
  self.unregister( socket )
106
111
 
@@ -235,6 +240,11 @@ class CZTop::Reactor
235
240
  ### registered with the reactor for the `:read` event with the specified +callback+,
236
241
  ### then returned.
237
242
  def register_monitor( socket, *events, &callback )
243
+ if !events.empty? && !events.last.is_a?( String )
244
+ handler = events.pop
245
+ callback = handler.method( :handle_monitor_event )
246
+ end
247
+
238
248
  events.push( 'ALL' ) if events.empty?
239
249
 
240
250
  monitor = CZTop::Monitor.new( socket )
@@ -253,33 +263,45 @@ class CZTop::Reactor
253
263
  # Polling
254
264
  #
255
265
 
256
- ### Poll the sockets registered to the reactor for pending events.
257
- def start_polling
258
- until self.empty?
259
- self.log.debug "Polling %d sockets" % [ self.sockets.length ]
260
-
261
- wait_interval = self.timers.wait_interval || DEFAULT_POLL_INTERVAL
262
-
263
- # If there's a timer already due to fire, don't wait at all
264
- event = if wait_interval > 0
265
- self.log.debug "Waiting for IO for %fms" % [ wait_interval * 1000 ]
266
- self.wait( wait_interval * 1000 )
267
- else
268
- nil
269
- end
270
-
271
- self.log.debug "Got event %p" % [ event ]
272
- if event
273
- # self.log.debug "Got event: %p" % [ event ]
274
- handler = self.sockets[ event.socket ][ :handler ]
275
- handler.call( event ) if handler
266
+ ### Poll registered sockets and fire timers until they're all unregistered.
267
+ def start_polling( **opts )
268
+ self.poll_once( **opts ) until self.empty?
269
+ end
270
+
271
+
272
+ ### Poll registered sockets or fire timers and return.
273
+ def poll_once( ignore_interrupts: false, ignore_eagain: true )
274
+ self.log.debug "Polling %d sockets" % [ self.sockets.length ]
275
+
276
+ wait_interval = self.timers.wait_interval || DEFAULT_POLL_INTERVAL
277
+
278
+ # If there's a timer already due to fire, don't wait at all
279
+ event = if wait_interval > 0
280
+ self.log.debug "Waiting for IO for %fms" % [ wait_interval * 1000 ]
281
+ self.wait( wait_interval * 1000 )
276
282
  else
277
- self.log.debug "Expired: firing timers."
278
- self.timers.fire
283
+ nil
279
284
  end
280
285
 
281
- self.log.debug "%d sockets after polling: %p" % [ self.sockets.length, self.sockets ]
286
+ self.log.debug "Got event %p" % [ event ]
287
+ if event
288
+ # self.log.debug "Got event: %p" % [ event ]
289
+ handler = self.sockets[ event.socket ][ :handler ]
290
+ handler.call( event )
291
+ else
292
+ self.log.debug "Expired: firing timers."
293
+ self.timers.fire
282
294
  end
295
+
296
+ self.log.debug "%d sockets after polling: %p" % [ self.sockets.length, self.sockets ]
297
+ rescue Interrupt
298
+ raise unless ignore_interrupts
299
+ self.log.debug "Interrupted."
300
+ return nil
301
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK
302
+ raise unless ignore_eagain
303
+ self.log.debug "EAGAIN"
304
+ return nil
283
305
  end
284
306
 
285
307
 
@@ -9,6 +9,13 @@ require 'cztop/reactor'
9
9
  describe CZTop::Reactor do
10
10
 
11
11
  let( :reactor ) { described_class.new }
12
+ let( :handler_class ) do
13
+ Class.new do
14
+ def handle_io_event(ev); end
15
+ def handle_monitor_event(ev); end
16
+ end
17
+ end
18
+ let( :handler_object ) { handler_class.new }
12
19
 
13
20
 
14
21
  describe "socket registration" do
@@ -42,10 +49,22 @@ describe CZTop::Reactor do
42
49
  end
43
50
 
44
51
 
45
- it "errors if no block is given when registering a socket" do
52
+ it "allows a socket to be registered with a handler object instead of a block" do
53
+ expect( reactor ).to_not be_registered( socket )
54
+ expect( reactor ).to_not have_event_enabled( socket, :read )
55
+ expect( reactor ).to_not have_event_enabled( socket, :write )
56
+
57
+ reactor.register( socket, :read, :write, handler_object )
58
+
59
+ expect( reactor ).to be_registered( socket )
60
+ expect( reactor ).to have_event_enabled( socket, :read )
61
+ expect( reactor ).to have_event_enabled( socket, :write )
62
+ end
63
+
64
+ it "errors if no block or handler object is given when registering a socket" do
46
65
  expect {
47
66
  reactor.register( socket, :read )
48
- }.to raise_error( LocalJumpError, /no handler/i )
67
+ }.to raise_error( LocalJumpError, /no block or handler/i )
49
68
  end
50
69
 
51
70
 
@@ -107,6 +126,64 @@ describe CZTop::Reactor do
107
126
  end
108
127
 
109
128
 
129
+ describe "handler registration" do
130
+
131
+ let( :reader ) do
132
+ sock = CZTop::Socket::PAIR.new( '@inproc://callback-test' )
133
+ sock.options.linger = 0
134
+ sock
135
+ end
136
+ let( :writer ) do
137
+ sock = CZTop::Socket::PAIR.new( '>inproc://callback-test' )
138
+ sock.options.linger = 0
139
+ sock
140
+ end
141
+
142
+ after( :each ) do
143
+ reader.close
144
+ writer.close
145
+ end
146
+
147
+
148
+ it "calls a callback when a registered socket becomes readable" do
149
+ callback_called = false
150
+ data = nil
151
+
152
+ reactor.register( reader, :read ) do |event|
153
+ expect( event ).to be_a( CZTop::Reactor::Event )
154
+ expect( event ).to be_readable
155
+ expect( event ).to_not be_writable
156
+ expect( event.socket ).to equal( reader )
157
+
158
+ event.socket.receive
159
+ callback_called = true
160
+ end
161
+
162
+ writer << "stuff"
163
+
164
+ reactor.poll_once
165
+
166
+ expect( callback_called ).to be_truthy
167
+ end
168
+
169
+
170
+ it "calls #handle_io_event on a handler object when a socket becomes readable" do
171
+ handler_object = Object.new
172
+ expect( handler_object ).to receive( :handle_io_event ) do |event|
173
+ expect( event ).to be_a( CZTop::Reactor::Event )
174
+ expect( event ).to be_readable
175
+ expect( event ).to_not be_writable
176
+ expect( event.socket ).to equal( reader )
177
+ end
178
+
179
+ reactor.register( reader, :read, handler_object )
180
+ writer << "stuff"
181
+ reactor.poll_once
182
+ end
183
+
184
+ end
185
+
186
+
110
187
  describe "timer registration" do
111
188
 
112
189
  it "allows a callback to be called after a certain amount of time" do
@@ -143,6 +220,26 @@ describe CZTop::Reactor do
143
220
  end
144
221
  end
145
222
 
223
+
224
+ it "can create and register a monitor with a handler object instead of a block" do
225
+ socket = CZTop::Socket::REP.new
226
+ begin
227
+ monitor = reactor.register_monitor( socket, handler_object ) {}
228
+ expect( monitor ).to be_a( CZTop::Monitor )
229
+ expect( reactor ).to be_registered( monitor.actor )
230
+ ensure
231
+ monitor.terminate if monitor
232
+ end
233
+ end
234
+
235
+
236
+ it "raises an error when registering a monitor with no callback or handler object" do
237
+ socket = CZTop::Socket::REP.new
238
+ expect {
239
+ reactor.register_monitor( socket )
240
+ }.to raise_error( LocalJumpError, /no block or handler/i )
241
+ end
242
+
146
243
  end
147
244
 
148
245
 
@@ -176,6 +273,41 @@ describe CZTop::Reactor do
176
273
  end
177
274
 
178
275
 
276
+ it "doesn't trap interrupts by default" do
277
+ expect( CZTop::Poller::ZMQ ).to receive( :poller_wait ).
278
+ and_raise( Interrupt.new )
279
+
280
+ expect {
281
+ reactor.poll_once
282
+ }.to raise_error( Interrupt )
283
+ end
284
+
285
+
286
+ it "has an option to ignore interrupts if you're doing your own signal-handling'" do
287
+ expect( CZTop::Poller::ZMQ ).to receive( :poller_wait ).
288
+ and_raise( Interrupt.new )
289
+
290
+ expect( reactor.poll_once(ignore_interrupts: true) ).to be_nil
291
+ end
292
+
293
+
294
+ it "ignores EAGAIN/EWOULDBLOCK by default" do
295
+ expect( CZTop::Poller::ZMQ ).to receive( :poller_wait ).
296
+ and_raise( Errno::EWOULDBLOCK.new )
297
+
298
+ expect( reactor.poll_once ).to be_nil
299
+ end
300
+
301
+
302
+ it "has an option to propagate EGAIN/EWOULDBLOCK" do
303
+ expect( CZTop::Poller::ZMQ ).to receive( :poller_wait ).
304
+ and_raise( Errno::EAGAIN.new )
305
+
306
+ expect {
307
+ reactor.poll_once( ignore_eagain: false )
308
+ }.to raise_error( Errno::EAGAIN )
309
+ end
310
+
179
311
  end
180
312
 
181
313
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cztop-reactor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre20170316155217
4
+ version: 0.1.0.pre20170323172345
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -35,7 +35,7 @@ cert_chain:
35
35
  w8aNA5re5+Rt/Vvjxj5AcEnZnZiz5x959NaddQocX32Z1unHw44pzRNUur1GInfW
36
36
  p4vpx2kUSFSAGjtCbDGTNV2AH8w9OU4xEmNz8c5lyoA=
37
37
  -----END CERTIFICATE-----
38
- date: 2017-03-16 00:00:00.000000000 Z
38
+ date: 2017-03-24 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: loggability