io-event 1.2.2 → 1.3.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ext/extconf.rb +6 -4
- data/ext/io/event/selector/array.h +135 -0
- data/ext/io/event/selector/epoll.c +435 -196
- data/ext/io/event/selector/kqueue.c +481 -218
- data/ext/io/event/selector/list.h +87 -0
- data/ext/io/event/selector/selector.c +14 -14
- data/ext/io/event/selector/selector.h +20 -6
- data/ext/io/event/selector/uring.c +399 -216
- data/lib/io/event/interrupt.rb +1 -1
- data/lib/io/event/selector/nonblock.rb +1 -1
- data/lib/io/event/selector/select.rb +59 -22
- data/lib/io/event/selector.rb +1 -5
- data/lib/io/event/version.rb +2 -2
- data/lib/io/event.rb +1 -1
- data/license.md +2 -1
- data/readme.md +13 -5
- data.tar.gz.sig +0 -0
- metadata +8 -61
- metadata.gz.sig +0 -0
data/lib/io/event/interrupt.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2021-
|
4
|
+
# Copyright, 2021-2023, by Samuel Williams.
|
5
|
+
# Copyright, 2023, by Math Ieu.
|
5
6
|
|
6
7
|
require_relative '../interrupt'
|
7
8
|
require_relative '../support'
|
@@ -103,14 +104,26 @@ module IO::Event
|
|
103
104
|
self.fiber&.alive?
|
104
105
|
end
|
105
106
|
|
106
|
-
|
107
|
+
# Dispatch the given events to the list of waiting fibers. If the fiber was not waiting for the given events, it is reactivated by calling the given block.
|
108
|
+
def dispatch(events, &reactivate)
|
109
|
+
# We capture the tail here, because calling reactivate might modify it:
|
110
|
+
tail = self.tail
|
111
|
+
|
107
112
|
if fiber = self.fiber
|
108
|
-
|
109
|
-
|
110
|
-
|
113
|
+
if fiber.alive?
|
114
|
+
revents = events & self.events
|
115
|
+
if revents.zero?
|
116
|
+
reactivate.call(self)
|
117
|
+
else
|
118
|
+
self.fiber = nil
|
119
|
+
fiber.transfer(revents)
|
120
|
+
end
|
121
|
+
else
|
122
|
+
self.fiber = nil
|
123
|
+
end
|
111
124
|
end
|
112
|
-
|
113
|
-
|
125
|
+
|
126
|
+
tail&.dispatch(events, &reactivate)
|
114
127
|
end
|
115
128
|
|
116
129
|
def invalidate
|
@@ -152,8 +165,8 @@ module IO::Event
|
|
152
165
|
total = 0
|
153
166
|
|
154
167
|
Selector.nonblock(io) do
|
155
|
-
|
156
|
-
|
168
|
+
maximum_size = buffer.size - offset
|
169
|
+
while maximum_size > 0
|
157
170
|
result = Fiber.blocking{buffer.read(io, maximum_size, offset)}
|
158
171
|
|
159
172
|
if again?(result)
|
@@ -169,6 +182,8 @@ module IO::Event
|
|
169
182
|
offset += result
|
170
183
|
break if total >= length
|
171
184
|
end
|
185
|
+
|
186
|
+
maximum_size = buffer.size - offset
|
172
187
|
end
|
173
188
|
end
|
174
189
|
|
@@ -179,8 +194,8 @@ module IO::Event
|
|
179
194
|
total = 0
|
180
195
|
|
181
196
|
Selector.nonblock(io) do
|
182
|
-
|
183
|
-
|
197
|
+
maximum_size = buffer.size - offset
|
198
|
+
while maximum_size > 0
|
184
199
|
result = Fiber.blocking{buffer.write(io, maximum_size, offset)}
|
185
200
|
|
186
201
|
if again?(result)
|
@@ -196,6 +211,8 @@ module IO::Event
|
|
196
211
|
offset += result
|
197
212
|
break if total >= length
|
198
213
|
end
|
214
|
+
|
215
|
+
maximum_size = buffer.size - offset
|
199
216
|
end
|
200
217
|
end
|
201
218
|
|
@@ -206,9 +223,8 @@ module IO::Event
|
|
206
223
|
io = IO.for_fd(_io.fileno, autoclose: false)
|
207
224
|
total = 0
|
208
225
|
|
209
|
-
|
210
|
-
|
211
|
-
|
226
|
+
maximum_size = buffer.size - offset
|
227
|
+
while maximum_size > 0
|
212
228
|
case result = blocking{io.read_nonblock(maximum_size, exception: false)}
|
213
229
|
when :wait_readable
|
214
230
|
if length > 0
|
@@ -233,6 +249,8 @@ module IO::Event
|
|
233
249
|
break if size >= length
|
234
250
|
length -= size
|
235
251
|
end
|
252
|
+
|
253
|
+
maximum_size = buffer.size - offset
|
236
254
|
end
|
237
255
|
|
238
256
|
return total
|
@@ -246,9 +264,8 @@ module IO::Event
|
|
246
264
|
io = IO.for_fd(_io.fileno, autoclose: false)
|
247
265
|
total = 0
|
248
266
|
|
249
|
-
|
250
|
-
|
251
|
-
|
267
|
+
maximum_size = buffer.size - offset
|
268
|
+
while maximum_size > 0
|
252
269
|
chunk = buffer.get_string(offset, maximum_size)
|
253
270
|
case result = blocking{io.write_nonblock(chunk, exception: false)}
|
254
271
|
when :wait_readable
|
@@ -269,6 +286,8 @@ module IO::Event
|
|
269
286
|
break if result >= length
|
270
287
|
length -= result
|
271
288
|
end
|
289
|
+
|
290
|
+
maximum_size = buffer.size - offset
|
272
291
|
end
|
273
292
|
|
274
293
|
return total
|
@@ -329,12 +348,26 @@ module IO::Event
|
|
329
348
|
end
|
330
349
|
end
|
331
350
|
|
332
|
-
@blocked = true
|
333
351
|
duration = 0 unless @ready.empty?
|
334
|
-
|
335
|
-
@blocked = false
|
352
|
+
error = nil
|
336
353
|
|
337
|
-
|
354
|
+
# We need to handle interrupts on blocking IO. Every other implementation uses EINTR, but that doesn't work with `::IO.select` as it will retry the call on EINTR.
|
355
|
+
Thread.handle_interrupt(::Exception => :on_blocking) do
|
356
|
+
@blocked = true
|
357
|
+
readable, writable, priority = ::IO.select(readable, writable, priority, duration)
|
358
|
+
rescue ::Exception => error
|
359
|
+
# Requeue below...
|
360
|
+
ensure
|
361
|
+
@blocked = false
|
362
|
+
end
|
363
|
+
|
364
|
+
if error
|
365
|
+
# Requeue the error into the pending exception queue:
|
366
|
+
Thread.current.raise(error)
|
367
|
+
return 0
|
368
|
+
end
|
369
|
+
|
370
|
+
ready = Hash.new(0).compare_by_identity
|
338
371
|
|
339
372
|
readable&.each do |io|
|
340
373
|
ready[io] |= IO::READABLE
|
@@ -349,7 +382,11 @@ module IO::Event
|
|
349
382
|
end
|
350
383
|
|
351
384
|
ready.each do |io, events|
|
352
|
-
@waiting.delete(io).
|
385
|
+
@waiting.delete(io).dispatch(events) do |waiter|
|
386
|
+
# Re-schedule the waiting IO:
|
387
|
+
waiter.tail = @waiting[io]
|
388
|
+
@waiting[io] = waiter
|
389
|
+
end
|
353
390
|
end
|
354
391
|
|
355
392
|
return ready.size
|
data/lib/io/event/selector.rb
CHANGED
@@ -11,11 +11,7 @@ module IO::Event
|
|
11
11
|
module Selector
|
12
12
|
def self.default(env = ENV)
|
13
13
|
if name = env['IO_EVENT_SELECTOR']&.to_sym
|
14
|
-
|
15
|
-
return const_get(name)
|
16
|
-
else
|
17
|
-
warn "Could not find IO_EVENT_SELECTOR=#{name}!"
|
18
|
-
end
|
14
|
+
return const_get(name)
|
19
15
|
end
|
20
16
|
|
21
17
|
if self.const_defined?(:URing)
|
data/lib/io/event/version.rb
CHANGED
data/lib/io/event.rb
CHANGED
data/license.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# MIT License
|
2
2
|
|
3
|
-
Copyright, 2021-
|
3
|
+
Copyright, 2021-2023, by Samuel Williams.
|
4
4
|
Copyright, 2021, by Delton Ding.
|
5
5
|
Copyright, 2021, by Benoit Daloze.
|
6
6
|
Copyright, 2022, by Alex Matchneer.
|
7
7
|
Copyright, 2022, by Bruno Sutic.
|
8
|
+
Copyright, 2023, by Math Ieu.
|
8
9
|
|
9
10
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
11
|
of this software and associated documentation files (the "Software"), to deal
|
data/readme.md
CHANGED
@@ -16,8 +16,16 @@ Please see the [project documentation](https://socketry.github.io/io-event/).
|
|
16
16
|
|
17
17
|
We welcome contributions to this project.
|
18
18
|
|
19
|
-
1. Fork it
|
20
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
21
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
22
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
23
|
-
5. Create new Pull Request
|
19
|
+
1. Fork it.
|
20
|
+
2. Create your feature branch (`git checkout -b my-new-feature`).
|
21
|
+
3. Commit your changes (`git commit -am 'Add some feature'`).
|
22
|
+
4. Push to the branch (`git push origin my-new-feature`).
|
23
|
+
5. Create new Pull Request.
|
24
|
+
|
25
|
+
### Developer Certificate of Origin
|
26
|
+
|
27
|
+
This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this project must agree to this document to have their contributions accepted.
|
28
|
+
|
29
|
+
### Contributor Covenant
|
30
|
+
|
31
|
+
This project is governed by [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-event
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
- Bruno Sutic
|
9
|
+
- Math Ieu
|
10
|
+
- Alex Matchneer
|
9
11
|
- Benoit Daloze
|
10
12
|
- Delton Ding
|
11
|
-
- machty
|
12
13
|
autorequire:
|
13
14
|
bindir: bin
|
14
15
|
cert_chain:
|
@@ -41,64 +42,8 @@ cert_chain:
|
|
41
42
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
42
43
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
43
44
|
-----END CERTIFICATE-----
|
44
|
-
date: 2023-
|
45
|
-
dependencies:
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: bake
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
requirements:
|
50
|
-
- - ">="
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: '0'
|
53
|
-
type: :development
|
54
|
-
prerelease: false
|
55
|
-
version_requirements: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - ">="
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '0'
|
60
|
-
- !ruby/object:Gem::Dependency
|
61
|
-
name: bundler
|
62
|
-
requirement: !ruby/object:Gem::Requirement
|
63
|
-
requirements:
|
64
|
-
- - ">="
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: '0'
|
67
|
-
type: :development
|
68
|
-
prerelease: false
|
69
|
-
version_requirements: !ruby/object:Gem::Requirement
|
70
|
-
requirements:
|
71
|
-
- - ">="
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
version: '0'
|
74
|
-
- !ruby/object:Gem::Dependency
|
75
|
-
name: covered
|
76
|
-
requirement: !ruby/object:Gem::Requirement
|
77
|
-
requirements:
|
78
|
-
- - ">="
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
version: '0'
|
81
|
-
type: :development
|
82
|
-
prerelease: false
|
83
|
-
version_requirements: !ruby/object:Gem::Requirement
|
84
|
-
requirements:
|
85
|
-
- - ">="
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version: '0'
|
88
|
-
- !ruby/object:Gem::Dependency
|
89
|
-
name: sus
|
90
|
-
requirement: !ruby/object:Gem::Requirement
|
91
|
-
requirements:
|
92
|
-
- - "~>"
|
93
|
-
- !ruby/object:Gem::Version
|
94
|
-
version: '0.6'
|
95
|
-
type: :development
|
96
|
-
prerelease: false
|
97
|
-
version_requirements: !ruby/object:Gem::Requirement
|
98
|
-
requirements:
|
99
|
-
- - "~>"
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '0.6'
|
45
|
+
date: 2023-08-23 00:00:00.000000000 Z
|
46
|
+
dependencies: []
|
102
47
|
description:
|
103
48
|
email:
|
104
49
|
executables: []
|
@@ -112,10 +57,12 @@ files:
|
|
112
57
|
- ext/io/event/event.h
|
113
58
|
- ext/io/event/interrupt.c
|
114
59
|
- ext/io/event/interrupt.h
|
60
|
+
- ext/io/event/selector/array.h
|
115
61
|
- ext/io/event/selector/epoll.c
|
116
62
|
- ext/io/event/selector/epoll.h
|
117
63
|
- ext/io/event/selector/kqueue.c
|
118
64
|
- ext/io/event/selector/kqueue.h
|
65
|
+
- ext/io/event/selector/list.h
|
119
66
|
- ext/io/event/selector/pidfd.c
|
120
67
|
- ext/io/event/selector/selector.c
|
121
68
|
- ext/io/event/selector/selector.h
|
@@ -150,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
97
|
- !ruby/object:Gem::Version
|
151
98
|
version: '0'
|
152
99
|
requirements: []
|
153
|
-
rubygems_version: 3.4.
|
100
|
+
rubygems_version: 3.4.10
|
154
101
|
signing_key:
|
155
102
|
specification_version: 4
|
156
103
|
summary: An event loop.
|
metadata.gz.sig
CHANGED
Binary file
|