nio4r 0.2.0 → 2.7.5

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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/ext/libev/Changes +232 -3
  4. data/ext/libev/LICENSE +2 -1
  5. data/ext/libev/README +11 -10
  6. data/ext/libev/ev.c +2249 -473
  7. data/ext/libev/ev.h +165 -135
  8. data/ext/libev/ev_epoll.c +68 -36
  9. data/ext/libev/ev_iouring.c +694 -0
  10. data/ext/libev/ev_kqueue.c +44 -18
  11. data/ext/libev/ev_linuxaio.c +620 -0
  12. data/ext/libev/ev_poll.c +28 -20
  13. data/ext/libev/ev_port.c +23 -10
  14. data/ext/libev/ev_select.c +18 -12
  15. data/ext/libev/ev_vars.h +65 -19
  16. data/ext/libev/ev_win32.c +16 -7
  17. data/ext/libev/ev_wrap.h +236 -160
  18. data/ext/nio4r/.clang-format +16 -0
  19. data/ext/nio4r/bytebuffer.c +465 -0
  20. data/ext/nio4r/extconf.rb +44 -35
  21. data/ext/nio4r/libev.h +3 -4
  22. data/ext/nio4r/monitor.c +186 -54
  23. data/ext/nio4r/nio4r.h +17 -23
  24. data/ext/nio4r/nio4r_ext.c +11 -3
  25. data/ext/nio4r/org/nio4r/ByteBuffer.java +295 -0
  26. data/ext/nio4r/org/nio4r/Monitor.java +176 -0
  27. data/ext/nio4r/org/nio4r/Nio4r.java +104 -0
  28. data/ext/nio4r/org/nio4r/Selector.java +297 -0
  29. data/ext/nio4r/selector.c +350 -182
  30. data/lib/nio/bytebuffer.rb +235 -0
  31. data/lib/nio/monitor.rb +100 -8
  32. data/lib/nio/selector.rb +110 -44
  33. data/lib/nio/version.rb +8 -1
  34. data/lib/nio.rb +47 -16
  35. data/lib/nio4r.rb +7 -0
  36. data/license.md +80 -0
  37. data/readme.md +91 -0
  38. data/releases.md +343 -0
  39. data.tar.gz.sig +2 -0
  40. metadata +114 -79
  41. metadata.gz.sig +0 -0
  42. data/.gitignore +0 -20
  43. data/.rspec +0 -4
  44. data/.travis.yml +0 -7
  45. data/CHANGES.md +0 -10
  46. data/Gemfile +0 -4
  47. data/LICENSE.txt +0 -20
  48. data/README.md +0 -171
  49. data/Rakefile +0 -9
  50. data/examples/echo_server.rb +0 -38
  51. data/ext/libev/README.embed +0 -3
  52. data/ext/libev/test_libev_win32.c +0 -123
  53. data/lib/nio/jruby/monitor.rb +0 -42
  54. data/lib/nio/jruby/selector.rb +0 -135
  55. data/nio4r.gemspec +0 -22
  56. data/spec/nio/monitor_spec.rb +0 -46
  57. data/spec/nio/selector_spec.rb +0 -269
  58. data/spec/spec_helper.rb +0 -3
  59. data/tasks/extension.rake +0 -10
  60. data/tasks/rspec.rake +0 -7
@@ -1,42 +0,0 @@
1
- module NIO
2
- # Monitors watch Channels for specific events
3
- class Monitor
4
- attr_accessor :value, :io
5
-
6
- # :nodoc
7
- def initialize(io, selection_key)
8
- @io, @key = io, selection_key
9
- selection_key.attach self
10
- @closed = false
11
- end
12
-
13
- # Obtain the interests for this monitor
14
- def interests
15
- Selector.iops2sym @key.interestOps
16
- end
17
-
18
- # What is the IO object ready for?
19
- def readiness
20
- Selector.iops2sym @key.readyOps
21
- end
22
-
23
- # Is the IO object readable?
24
- def readable?
25
- readiness == :r || readiness == :rw
26
- end
27
-
28
- # Is the IO object writable?
29
- def writable?
30
- readiness == :w || readiness == :rw
31
- end
32
- alias_method :writeable?, :writable?
33
-
34
- # Is this monitor closed?
35
- def closed?; @closed; end
36
-
37
- # Deactivate this monitor
38
- def close
39
- @closed = true
40
- end
41
- end
42
- end
@@ -1,135 +0,0 @@
1
- module NIO
2
- # Selectors monitor IO objects for events of interest
3
- class Selector
4
- java_import "java.nio.channels.Selector"
5
- java_import "java.nio.channels.SelectionKey"
6
-
7
- # Convert nio4r interest symbols to Java NIO interest ops
8
- def self.sym2iops(interest, channel)
9
- case interest
10
- when :r
11
- if channel.validOps & SelectionKey::OP_ACCEPT != 0
12
- SelectionKey::OP_ACCEPT
13
- else
14
- SelectionKey::OP_READ
15
- end
16
- when :w
17
- if channel.respond_to? :connected? and not channel.connected?
18
- SelectionKey::OP_CONNECT
19
- else
20
- SelectionKey::OP_WRITE
21
- end
22
- when :rw
23
- super(:r, channel) | super(:w, channel)
24
- else raise ArgumentError, "invalid interest type: #{interest}"
25
- end
26
- end
27
-
28
- # Convert Java NIO interest ops to the corresponding Ruby symbols
29
- def self.iops2sym(interest_ops)
30
- case interest_ops
31
- when SelectionKey::OP_READ, SelectionKey::OP_ACCEPT
32
- :r
33
- when SelectionKey::OP_WRITE, SelectionKey::OP_CONNECT
34
- :w
35
- when SelectionKey::OP_READ | SelectionKey::OP_WRITE
36
- :rw
37
- when 0 then nil
38
- else raise ArgumentError, "unknown interest op combination: 0x#{interest_ops.to_s(16)}"
39
- end
40
- end
41
-
42
- # Create a new NIO::Selector
43
- def initialize
44
- @java_selector = Selector.open
45
- @select_lock = Mutex.new
46
- end
47
-
48
- # Register interest in an IO object with the selector for the given types
49
- # of events. Valid event types for interest are:
50
- # * :r - is the IO readable?
51
- # * :w - is the IO writeable?
52
- # * :rw - is the IO either readable or writeable?
53
- def register(io, interest)
54
- java_channel = io.to_channel
55
- java_channel.configureBlocking(false)
56
- interest_ops = self.class.sym2iops(interest, java_channel)
57
-
58
- begin
59
- selector_key = java_channel.register @java_selector, interest_ops
60
- rescue NativeException => ex
61
- case ex.cause
62
- when java.lang.IllegalArgumentException
63
- raise ArgumentError, "invalid interest type for #{java_channel}: #{interest}"
64
- else raise
65
- end
66
- end
67
-
68
- NIO::Monitor.new(io, selector_key)
69
- end
70
-
71
- # Deregister the given IO object from the selector
72
- def deregister(io)
73
- key = io.to_channel.keyFor(@java_selector)
74
- return unless key
75
-
76
- monitor = key.attachment
77
- monitor.close
78
- monitor
79
- end
80
-
81
- # Is the given IO object registered with the selector?
82
- def registered?(io)
83
- key = io.to_channel.keyFor(@java_selector)
84
- return unless key
85
- !key.attachment.closed?
86
- end
87
-
88
- # Select which monitors are ready
89
- def select(timeout = nil)
90
- selected = []
91
- ready = select_each(timeout) { |monitor| selected << monitor }
92
- return unless ready
93
-
94
- selected
95
- end
96
-
97
- # Iterate across all selectable monitors
98
- def select_each(timeout = nil)
99
- @select_lock.synchronize do
100
- if timeout == 0
101
- # The Java NIO API thinks zero means you want to BLOCK FOREVER o_O
102
- # How about we don't block at all instead?
103
- ready = @java_selector.selectNow
104
- elsif timeout
105
- ready = @java_selector.select(timeout * 1000)
106
- else
107
- ready = @java_selector.select
108
- end
109
-
110
- return unless ready > 0 # timeout or wakeup
111
-
112
- @java_selector.selectedKeys.each { |key| yield key.attachment }
113
- @java_selector.selectedKeys.clear
114
-
115
- ready
116
- end
117
- end
118
-
119
- # Wake up the other thread that's currently blocking on this selector
120
- def wakeup
121
- @java_selector.wakeup
122
- nil
123
- end
124
-
125
- # Close this selector
126
- def close
127
- @java_selector.close
128
- end
129
-
130
- # Is this selector closed?
131
- def closed?
132
- !@java_selector.isOpen
133
- end
134
- end
135
- end
data/nio4r.gemspec DELETED
@@ -1,22 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/nio/version', __FILE__)
3
-
4
- Gem::Specification.new do |gem|
5
- gem.authors = ["Tony Arcieri"]
6
- gem.email = ["tony.arcieri@gmail.com"]
7
- gem.description = "New IO for Ruby"
8
- gem.summary = "NIO provides a high performance selector API for monitoring IO objects"
9
- gem.homepage = "https://github.com/tarcieri/nio4r"
10
-
11
- gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
- gem.files = `git ls-files`.split("\n")
13
- gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
- gem.name = "nio4r"
15
- gem.require_paths = ["lib"]
16
- gem.version = NIO::VERSION
17
- gem.extensions = ["ext/nio4r/extconf.rb"]
18
-
19
- gem.add_development_dependency "rake-compiler", "~> 0.7.9"
20
- gem.add_development_dependency "rake"
21
- gem.add_development_dependency "rspec", "~> 2.7.0"
22
- end
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe NIO::Monitor do
4
- let :readable do
5
- reader, writer = IO.pipe
6
- writer << "have some data"
7
- reader
8
- end
9
-
10
- let :selector do
11
- NIO::Selector.new
12
- end
13
-
14
- # Monitors are created by registering IO objects or channels with a selector
15
- subject { selector.register(readable, :r) }
16
-
17
- it "knows its interests" do
18
- subject.interests.should == :r
19
- end
20
-
21
- it "stores arbitrary values" do
22
- subject.value = 42
23
- subject.value.should == 42
24
- end
25
-
26
- it "knows what IO objects are ready for" do
27
- # Perhaps let bindings are just confusing me but they're not producing
28
- # what I want. Manually doing the setup here does
29
- # FIXME: Hey RSpec wizards! Fix this!
30
- reader, writer = IO.pipe
31
- writer << "loldata"
32
- selector = NIO::Selector.new
33
- subject = selector.register(reader, :r)
34
-
35
- # Here's where the spec really begins
36
- selector.select(1).should include(subject)
37
- subject.readiness.should == :r
38
- subject.should be_readable
39
- end
40
-
41
- it "closes" do
42
- subject.should_not be_closed
43
- subject.close
44
- subject.should be_closed
45
- end
46
- end
@@ -1,269 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # Timeouts should be at least this precise (in seconds) to pass the tests
4
- # Typical precision should be better than this, but if it's worse it will fail
5
- # the tests
6
- TIMEOUT_PRECISION = 0.1
7
-
8
- describe NIO::Selector do
9
- it "monitors IO objects" do
10
- pipe, _ = IO.pipe
11
-
12
- monitor = subject.register(pipe, :r)
13
- monitor.should_not be_closed
14
- end
15
-
16
- it "knows which IO objects are registered" do
17
- reader, writer = IO.pipe
18
- subject.register(reader, :r)
19
-
20
- subject.should be_registered(reader)
21
- subject.should_not be_registered(writer)
22
- end
23
-
24
- it "deregisters IO objects" do
25
- pipe, _ = IO.pipe
26
-
27
- subject.register(pipe, :r)
28
- monitor = subject.deregister(pipe)
29
- subject.should_not be_registered(pipe)
30
- monitor.should be_closed
31
- end
32
-
33
- context "select" do
34
- it "waits for a timeout when selecting" do
35
- reader, writer = IO.pipe
36
- monitor = subject.register(reader, :r)
37
-
38
- payload = "hi there"
39
- writer << payload
40
-
41
- timeout = 0.5
42
- started_at = Time.now
43
- subject.select(timeout).should include monitor
44
- (Time.now - started_at).should be_within(TIMEOUT_PRECISION).of(0)
45
- reader.read_nonblock(payload.size)
46
-
47
- started_at = Time.now
48
- subject.select(timeout).should be_nil
49
- (Time.now - started_at).should be_within(TIMEOUT_PRECISION).of(timeout)
50
- end
51
-
52
- it "wakes up if signaled to from another thread" do
53
- pipe, _ = IO.pipe
54
- subject.register(pipe, :r)
55
-
56
- thread = Thread.new do
57
- started_at = Time.now
58
- subject.select.should be_nil
59
- Time.now - started_at
60
- end
61
-
62
- timeout = 0.1
63
- sleep timeout
64
- subject.wakeup
65
-
66
- thread.value.should be_within(TIMEOUT_PRECISION).of(timeout)
67
- end
68
- end
69
-
70
- context "select_each" do
71
- it "iterates across ready selectables" do
72
- readable1, writer = IO.pipe
73
- writer << "ohai"
74
-
75
- readable2, writer = IO.pipe
76
- writer << "ohai"
77
-
78
- unreadable, _ = IO.pipe
79
-
80
- monitor1 = subject.register(readable1, :r)
81
- monitor2 = subject.register(readable2, :r)
82
- monitor3 = subject.register(unreadable, :r)
83
-
84
- readables = []
85
- subject.select_each { |monitor| readables << monitor }
86
-
87
- readables.should include(monitor1)
88
- readables.should include(monitor2)
89
- readables.should_not include(monitor3)
90
- end
91
-
92
- it "allows new monitors to be registered in the select_each block" do
93
- server = TCPServer.new("localhost", 10001)
94
-
95
- monitor = subject.register(server, :r)
96
- connector = TCPSocket.open("localhost", 10001)
97
-
98
- block_fired = false
99
- subject.select_each do |monitor|
100
- block_fired = true
101
- socket = server.accept
102
- subject.register(socket, :r).should be_a NIO::Monitor
103
- end
104
-
105
- block_fired.should be_true
106
- end
107
- end
108
-
109
- it "closes" do
110
- subject.close
111
- subject.should be_closed
112
- end
113
-
114
- context "selectables" do
115
- shared_context "an NIO selectable" do
116
- it "selects for read readiness" do
117
- waiting_monitor = subject.register(unreadable_subject, :r)
118
- ready_monitor = subject.register(readable_subject, :r)
119
-
120
- ready_monitors = subject.select
121
- ready_monitors.should include ready_monitor
122
- ready_monitors.should_not include waiting_monitor
123
- end
124
-
125
- it "selects for write readiness" do
126
- waiting_monitor = subject.register(unwritable_subject, :w)
127
- ready_monitor = subject.register(writable_subject, :w)
128
-
129
- ready_monitors = subject.select(0.1)
130
-
131
- ready_monitors.should include ready_monitor
132
- ready_monitors.should_not include waiting_monitor
133
- end
134
- end
135
-
136
- context "IO.pipe" do
137
- let :readable_subject do
138
- pipe, peer = IO.pipe
139
- peer << "data"
140
- pipe
141
- end
142
-
143
- let :unreadable_subject do
144
- pipe, _ = IO.pipe
145
- pipe
146
- end
147
-
148
- let :writable_subject do
149
- _, pipe = IO.pipe
150
- pipe
151
- end
152
-
153
- let :unwritable_subject do
154
- reader, pipe = IO.pipe
155
-
156
- begin
157
- pipe.write_nonblock "JUNK IN THE TUBES"
158
- _, writers = select [], [pipe], [], 0
159
- rescue Errno::EPIPE
160
- break
161
- end while writers and writers.include? pipe
162
-
163
- pipe
164
- end
165
-
166
- it_behaves_like "an NIO selectable"
167
- end
168
-
169
- context TCPSocket do
170
- let(:tcp_port) { 12345 }
171
-
172
- let :readable_subject do
173
- server = TCPServer.new("localhost", tcp_port)
174
- sock = TCPSocket.open("localhost", tcp_port)
175
- peer = server.accept
176
- peer << "data"
177
- sock
178
- end
179
-
180
- let :unreadable_subject do
181
- if defined?(JRUBY_VERSION) and ENV['TRAVIS']
182
- pending "This is sporadically showing up readable on JRuby in CI"
183
- else
184
- TCPServer.new("localhost", tcp_port + 1)
185
- TCPSocket.open("localhost", tcp_port + 1)
186
- end
187
- end
188
-
189
- let :writable_subject do
190
- TCPServer.new("localhost", tcp_port + 2)
191
- TCPSocket.open("localhost", tcp_port + 2)
192
- end
193
-
194
- let :unwritable_subject do
195
- server = TCPServer.new("localhost", tcp_port + 3)
196
- sock = TCPSocket.open("localhost", tcp_port + 3)
197
- peer = server.accept
198
-
199
- begin
200
- sock.write_nonblock "JUNK IN THE TUBES"
201
- _, writers = select [], [sock], [], 0
202
- end while writers and writers.include? sock
203
-
204
- sock
205
- end
206
-
207
- it_behaves_like "an NIO selectable"
208
- end
209
-
210
- context UDPSocket do
211
- let(:udp_port) { 23456 }
212
-
213
- let :readable_subject do
214
- sock = UDPSocket.new
215
- sock.bind('localhost', udp_port)
216
-
217
- peer = UDPSocket.new
218
- peer.send("hi there", 0, 'localhost', udp_port)
219
-
220
- sock
221
- end
222
-
223
- let :unreadable_subject do
224
- sock = UDPSocket.new
225
- sock.bind('localhost', udp_port + 1)
226
- sock
227
- end
228
-
229
- let :writable_subject do
230
- pending "come up with a writable UDPSocket example"
231
- end
232
-
233
- let :unwritable_subject do
234
- pending "come up with a UDPSocket that's blocked on writing"
235
- end
236
-
237
- it_behaves_like "an NIO selectable"
238
- end
239
- end
240
-
241
- context "acceptables" do
242
- shared_context "an NIO acceptable" do
243
- it "selects for read readiness" do
244
- waiting_monitor = subject.register(unacceptable_subject, :r)
245
- ready_monitor = subject.register(acceptable_subject, :r)
246
-
247
- ready_monitors = subject.select
248
- ready_monitors.should include ready_monitor
249
- ready_monitors.should_not include waiting_monitor
250
- end
251
- end
252
-
253
- context TCPServer do
254
- let(:tcp_port) { 23456 }
255
-
256
- let :acceptable_subject do
257
- server = TCPServer.new("localhost", tcp_port)
258
- TCPSocket.open("localhost", tcp_port)
259
- server
260
- end
261
-
262
- let :unacceptable_subject do
263
- TCPServer.new("localhost", tcp_port + 1)
264
- end
265
-
266
- it_behaves_like "an NIO acceptable"
267
- end
268
- end
269
- end
data/spec/spec_helper.rb DELETED
@@ -1,3 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
- require 'nio'
data/tasks/extension.rake DELETED
@@ -1,10 +0,0 @@
1
- require 'rake/extensiontask'
2
-
3
- if defined?(JRUBY_VERSION)
4
- # Don't build the native extension on JRuby since it uses native Java NIO
5
- task :compile
6
- else
7
- Rake::ExtensionTask.new('nio4r_ext') do |ext|
8
- ext.ext_dir = 'ext/nio4r'
9
- end
10
- end
data/tasks/rspec.rake DELETED
@@ -1,7 +0,0 @@
1
- require 'rspec/core/rake_task'
2
-
3
- RSpec::Core::RakeTask.new
4
-
5
- RSpec::Core::RakeTask.new(:rcov) do |task|
6
- task.rcov = true
7
- end