cztop-reactor 0.1.0.pre20170316155217 → 0.1.0.pre20170323172345

Sign up to get free protection for your applications and to get access to all the features.
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