nio4r 0.4.3-java → 0.4.4-java

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ 0.4.4
2
+ -----
3
+ * Fix return values for Selector_synchronize and Selector_unlock
4
+
1
5
  0.4.3
2
6
  -----
3
7
  * REALLY have thread synchronization when closing selectors ;)
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
 
3
3
  gem 'jruby-openssl' if defined? JRUBY_VERSION
4
4
 
data/README.md CHANGED
@@ -121,7 +121,7 @@ selector.deregister(reader)
121
121
 
122
122
  Monitors provide methods which let you introspect on why a particular IO
123
123
  object was selected. These methods are not thread safe unless you are holding
124
- the selector lock (i.e. if you're in a block pased to #select). Only use them
124
+ the selector lock (i.e. if you're in a block passed to #select). Only use them
125
125
  if you aren't concerned with thread safety, or you're within a #select
126
126
  block:
127
127
 
@@ -231,7 +231,7 @@ public class Nio4r implements Library {
231
231
  @JRubyMethod
232
232
  public synchronized IRubyObject select(ThreadContext context, IRubyObject timeout, Block block) {
233
233
  Ruby runtime = context.getRuntime();
234
- int ready = doSelect(runtime, timeout);
234
+ int ready = doSelect(runtime, context, timeout);
235
235
 
236
236
  /* Timeout or wakeup */
237
237
  if(ready <= 0)
@@ -263,21 +263,26 @@ public class Nio4r implements Library {
263
263
  }
264
264
 
265
265
  /* Run the selector */
266
- private int doSelect(Ruby runtime, IRubyObject timeout) {
266
+ private int doSelect(Ruby runtime, ThreadContext context, IRubyObject timeout) {
267
+ int result;
268
+
267
269
  cancelKeys();
268
270
  try {
271
+ context.getThread().beforeBlockingCall();
269
272
  if(timeout.isNil()) {
270
- return this.selector.select();
273
+ result = this.selector.select();
271
274
  } else {
272
275
  double t = RubyNumeric.num2dbl(timeout);
273
276
  if(t == 0) {
274
- return this.selector.selectNow();
277
+ result = this.selector.selectNow();
275
278
  } else if(t < 0) {
276
279
  throw runtime.newArgumentError("time interval must be positive");
277
280
  } else {
278
- return this.selector.select((long)(t * 1000));
281
+ result = this.selector.select((long)(t * 1000));
279
282
  }
280
283
  }
284
+ context.getThread().afterBlockingCall();
285
+ return result;
281
286
  } catch(IOException ie) {
282
287
  throw runtime.newIOError(ie.getLocalizedMessage());
283
288
  }
@@ -170,7 +170,7 @@ static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE *args), VA
170
170
  return rb_ensure(func, (VALUE)args, NIO_Selector_unlock, self);
171
171
  } else {
172
172
  /* We already hold the selector lock, so no need to unlock it */
173
- func(args);
173
+ return func(args);
174
174
  }
175
175
  }
176
176
 
@@ -183,6 +183,8 @@ static VALUE NIO_Selector_unlock(VALUE self)
183
183
 
184
184
  lock = rb_ivar_get(self, rb_intern("lock"));
185
185
  rb_funcall(lock, rb_intern("unlock"), 0, 0);
186
+
187
+ return Qnil;
186
188
  }
187
189
 
188
190
  /* Register an IO object with the selector for the given interests */
data/lib/nio.rb CHANGED
@@ -11,7 +11,7 @@ module NIO
11
11
  def self.engine; ENGINE end
12
12
  end
13
13
 
14
- if ENV["NIO4R_PURE"]
14
+ if ENV["NIO4R_PURE"] || ENV["OS"] =~ /Windows/i
15
15
  require 'nio/monitor'
16
16
  require 'nio/selector'
17
17
  NIO::ENGINE = 'select'
@@ -18,7 +18,9 @@ module NIO
18
18
  # * :rw - is the IO either readable or writeable?
19
19
  def register(io, interest)
20
20
  @lock.synchronize do
21
- raise ArgumentError, "this IO is already registered with the selector" if @selectables[io]
21
+ if monitor = @selectables[io]
22
+ raise ArgumentError, "this IO is already registered with the selector as #{monitor.interests.inspect}"
23
+ end
22
24
 
23
25
  monitor = Monitor.new(io, interest, self)
24
26
  @selectables[io] = monitor
@@ -61,14 +63,7 @@ module NIO
61
63
  if io == @wakeup
62
64
  # Clear all wakeup signals we've received by reading them
63
65
  # Wakeups should have level triggered behavior
64
- begin
65
- @wakeup.read_nonblock(1024)
66
-
67
- # Loop until we've drained all incoming events
68
- redo
69
- rescue Errno::EWOULDBLOCK
70
- end
71
-
66
+ @wakeup.read(@wakeup.stat.size)
72
67
  return
73
68
  else
74
69
  monitor = @selectables[io]
@@ -107,7 +102,7 @@ module NIO
107
102
  # level-triggered behavior.
108
103
  def wakeup
109
104
  # Send the selector a signal in the form of writing data to a pipe
110
- @waker << "\0"
105
+ @waker.write "\0"
111
106
  nil
112
107
  end
113
108
 
@@ -1,3 +1,3 @@
1
1
  module NIO
2
- VERSION = "0.4.3"
2
+ VERSION = "0.4.4"
3
3
  end
@@ -6,12 +6,12 @@ describe NIO::Monitor do
6
6
  let(:writer) { pipes.last }
7
7
  let(:selector) { NIO::Selector.new }
8
8
 
9
- subject { selector.register(reader, :rw) }
9
+ subject { selector.register(reader, :r) }
10
10
  let(:peer) { selector.register(writer, :rw) }
11
11
  after { selector.close }
12
12
 
13
13
  it "knows its interests" do
14
- subject.interests.should == :rw
14
+ subject.interests.should == :r
15
15
  peer.interests.should == :rw
16
16
  end
17
17
 
@@ -18,8 +18,13 @@ describe "IO.pipe" do
18
18
  let :unwritable_subject do
19
19
  reader, pipe = IO.pipe
20
20
 
21
+ #HACK: On OS X 10.8, this str must be larger than PIPE_BUF. Otherwise,
22
+ # the write is atomic and select() will return writable but write()
23
+ # will throw EAGAIN if there is too little space to write the string
24
+ # TODO: Use FFI to lookup the platform-specific size of PIPE_BUF
25
+ str = "JUNK IN THE TUBES" * 10000
21
26
  begin
22
- pipe.write_nonblock "JUNK IN THE TUBES"
27
+ pipe.write_nonblock str
23
28
  _, writers = select [], [pipe], [], 0
24
29
  rescue Errno::EPIPE
25
30
  break
@@ -114,13 +114,25 @@ describe NIO::Selector do
114
114
  writer << "ohai"
115
115
  unready, _ = IO.pipe
116
116
 
117
- reader_monitor = subject.register(reader, :r)
117
+ reader_monitor = subject.register(reader, :r)
118
118
  unready_monitor = subject.register(unready, :r)
119
119
 
120
120
  selected = subject.select(0)
121
121
  selected.size.should == 1
122
- selected.should include(reader_monitor)
123
- selected.should_not include(unready_monitor)
122
+ selected.should include reader_monitor
123
+ selected.should_not include unready_monitor
124
+ end
125
+
126
+ it "selects closed IO objects" do
127
+ monitor = subject.register(reader, :r)
128
+ subject.select(0).should be_nil
129
+
130
+ thread = Thread.new { subject.select }
131
+ Thread.pass while thread.status && thread.status != "sleep"
132
+
133
+ writer.close
134
+ selected = thread.value
135
+ selected.should include monitor
124
136
  end
125
137
 
126
138
  it "iterates across selected objects with a block" do
@@ -140,9 +152,9 @@ describe NIO::Selector do
140
152
  result = subject.select { |monitor| readables << monitor }
141
153
  result.should == 2
142
154
 
143
- readables.should include(monitor1)
144
- readables.should include(monitor2)
145
- readables.should_not include(monitor3)
155
+ readables.should include monitor1
156
+ readables.should include monitor2
157
+ readables.should_not include monitor3
146
158
  end
147
159
  end
148
160
 
metadata CHANGED
@@ -1,28 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nio4r
3
3
  version: !ruby/object:Gem::Version
4
+ version: 0.4.4
4
5
  prerelease:
5
- version: 0.4.3
6
6
  platform: java
7
7
  authors:
8
8
  - Tony Arcieri
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-21 00:00:00.000000000 Z
12
+ date: 2013-05-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler
16
16
  version_requirements: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ! '>='
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: !binary |-
21
21
  MA==
22
22
  none: false
23
23
  requirement: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ! '>='
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: !binary |-
28
28
  MA==
@@ -33,14 +33,14 @@ dependencies:
33
33
  name: rake
34
34
  version_requirements: !ruby/object:Gem::Requirement
35
35
  requirements:
36
- - - ! '>='
36
+ - - ">="
37
37
  - !ruby/object:Gem::Version
38
38
  version: !binary |-
39
39
  MA==
40
40
  none: false
41
41
  requirement: !ruby/object:Gem::Requirement
42
42
  requirements:
43
- - - ! '>='
43
+ - - ">="
44
44
  - !ruby/object:Gem::Version
45
45
  version: !binary |-
46
46
  MA==
@@ -51,14 +51,14 @@ dependencies:
51
51
  name: rspec
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - ! '>='
54
+ - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: !binary |-
57
57
  MA==
58
58
  none: false
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - ! '>='
61
+ - - ">="
62
62
  - !ruby/object:Gem::Version
63
63
  version: !binary |-
64
64
  MA==
@@ -72,9 +72,9 @@ executables: []
72
72
  extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
- - .gitignore
76
- - .rspec
77
- - .travis.yml
75
+ - ".gitignore"
76
+ - ".rspec"
77
+ - ".travis.yml"
78
78
  - CHANGES.md
79
79
  - Gemfile
80
80
  - LICENSE.txt
@@ -128,21 +128,15 @@ require_paths:
128
128
  - lib
129
129
  required_ruby_version: !ruby/object:Gem::Requirement
130
130
  requirements:
131
- - - ! '>='
131
+ - - ">="
132
132
  - !ruby/object:Gem::Version
133
- segments:
134
- - 0
135
- hash: 2
136
133
  version: !binary |-
137
134
  MA==
138
135
  none: false
139
136
  required_rubygems_version: !ruby/object:Gem::Requirement
140
137
  requirements:
141
- - - ! '>='
138
+ - - ">="
142
139
  - !ruby/object:Gem::Version
143
- segments:
144
- - 0
145
- hash: 2
146
140
  version: !binary |-
147
141
  MA==
148
142
  none: false