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 +4 -0
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/ext/nio4r/org/nio4r/Nio4r.java +10 -5
- data/ext/nio4r/selector.c +3 -1
- data/lib/nio.rb +1 -1
- data/lib/nio/selector.rb +5 -10
- data/lib/nio/version.rb +1 -1
- data/spec/nio/monitor_spec.rb +2 -2
- data/spec/nio/selectables/pipe_spec.rb +6 -1
- data/spec/nio/selector_spec.rb +18 -6
- metadata +13 -19
data/CHANGES.md
CHANGED
data/Gemfile
CHANGED
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
|
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
|
-
|
273
|
+
result = this.selector.select();
|
271
274
|
} else {
|
272
275
|
double t = RubyNumeric.num2dbl(timeout);
|
273
276
|
if(t == 0) {
|
274
|
-
|
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
|
-
|
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
|
}
|
data/ext/nio4r/selector.c
CHANGED
@@ -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
data/lib/nio/selector.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
105
|
+
@waker.write "\0"
|
111
106
|
nil
|
112
107
|
end
|
113
108
|
|
data/lib/nio/version.rb
CHANGED
data/spec/nio/monitor_spec.rb
CHANGED
@@ -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, :
|
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 == :
|
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
|
27
|
+
pipe.write_nonblock str
|
23
28
|
_, writers = select [], [pipe], [], 0
|
24
29
|
rescue Errno::EPIPE
|
25
30
|
break
|
data/spec/nio/selector_spec.rb
CHANGED
@@ -114,13 +114,25 @@ describe NIO::Selector do
|
|
114
114
|
writer << "ohai"
|
115
115
|
unready, _ = IO.pipe
|
116
116
|
|
117
|
-
reader_monitor
|
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
|
123
|
-
selected.should_not include
|
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
|
144
|
-
readables.should include
|
145
|
-
readables.should_not include
|
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:
|
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
|