io-event 1.1.0 → 1.1.2
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 +1 -1
- data/ext/io/event/selector/epoll.c +4 -2
- data/ext/io/event/selector/kqueue.c +4 -2
- data/ext/io/event/selector/selector.c +48 -7
- data/ext/io/event/selector/uring.c +7 -2
- data/lib/io/event/selector/nonblock.rb +14 -0
- data/lib/io/event/selector/select.rb +50 -43
- data/lib/io/event/version.rb +1 -1
- data/lib/io/event.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd5603ed5cc26eaa2f9d4261d7462ec1d435c169c36c2770af80c0d27fe2c4e2
|
4
|
+
data.tar.gz: 1ce4d895bfc5618e97bf84702e2591aa9b3aa947678e5eae8b1b42c0c4119607
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5924e3108f8c731a55d36f5329519870931aaa16e14fab81ca7b56418afb77cc6bab395c10751b628ce2668ef5c570141af6237cc07c7a62bf8fc8a4b53c71a
|
7
|
+
data.tar.gz: a5e8281833ac2f7476ca298fc0446ad4479dd0f08cb7764c5f0940fd235446b903e03909acc669869b2847eab50e92c1ef80e6c77acef62b35525d39a48a5351
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/ext/extconf.rb
CHANGED
@@ -385,7 +385,7 @@ VALUE IO_Event_Selector_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE e
|
|
385
385
|
return rb_ensure(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_ensure, (VALUE)&io_wait_arguments);
|
386
386
|
}
|
387
387
|
|
388
|
-
#ifdef
|
388
|
+
#ifdef HAVE_RUBY_IO_BUFFER_H
|
389
389
|
|
390
390
|
struct io_read_arguments {
|
391
391
|
VALUE self;
|
@@ -715,9 +715,11 @@ void Init_IO_Event_Selector_EPoll(VALUE IO_Event_Selector) {
|
|
715
715
|
rb_define_method(IO_Event_Selector_EPoll, "close", IO_Event_Selector_EPoll_close, 0);
|
716
716
|
|
717
717
|
rb_define_method(IO_Event_Selector_EPoll, "io_wait", IO_Event_Selector_EPoll_io_wait, 3);
|
718
|
-
|
718
|
+
|
719
|
+
#ifdef HAVE_RUBY_IO_BUFFER_H
|
719
720
|
rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read_compatible, -1);
|
720
721
|
rb_define_method(IO_Event_Selector_EPoll, "io_write", IO_Event_Selector_EPoll_io_write_compatible, -1);
|
722
|
+
#endif
|
721
723
|
|
722
724
|
// Once compatibility isn't a concern, we can do this:
|
723
725
|
// rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read, 5);
|
@@ -380,7 +380,7 @@ VALUE IO_Event_Selector_KQueue_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
380
380
|
return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
|
381
381
|
}
|
382
382
|
|
383
|
-
#ifdef
|
383
|
+
#ifdef HAVE_RUBY_IO_BUFFER_H
|
384
384
|
|
385
385
|
struct io_read_arguments {
|
386
386
|
VALUE self;
|
@@ -764,9 +764,11 @@ void Init_IO_Event_Selector_KQueue(VALUE IO_Event_Selector) {
|
|
764
764
|
rb_define_method(IO_Event_Selector_KQueue, "close", IO_Event_Selector_KQueue_close, 0);
|
765
765
|
|
766
766
|
rb_define_method(IO_Event_Selector_KQueue, "io_wait", IO_Event_Selector_KQueue_io_wait, 3);
|
767
|
-
|
767
|
+
|
768
|
+
#ifdef HAVE_RUBY_IO_BUFFER_H
|
768
769
|
rb_define_method(IO_Event_Selector_KQueue, "io_read", IO_Event_Selector_KQueue_io_read_compatible, -1);
|
769
770
|
rb_define_method(IO_Event_Selector_KQueue, "io_write", IO_Event_Selector_KQueue_io_write_compatible, -1);
|
771
|
+
#endif
|
770
772
|
|
771
773
|
rb_define_method(IO_Event_Selector_KQueue, "process_wait", IO_Event_Selector_KQueue_process_wait, 3);
|
772
774
|
}
|
@@ -21,15 +21,14 @@
|
|
21
21
|
#include "selector.h"
|
22
22
|
#include <fcntl.h>
|
23
23
|
|
24
|
-
#ifndef HAVE_RB_PROCESS_STATUS_WAIT
|
25
|
-
// Pull in WNOHANG.
|
26
|
-
#include <sys/wait.h>
|
27
|
-
#endif
|
28
|
-
|
29
24
|
static const int DEBUG = 0;
|
30
25
|
|
31
26
|
static ID id_transfer, id_alive_p;
|
32
27
|
|
28
|
+
#ifndef HAVE_RB_PROCESS_STATUS_WAIT
|
29
|
+
static VALUE process_wnohang;
|
30
|
+
#endif
|
31
|
+
|
33
32
|
VALUE IO_Event_Selector_fiber_transfer(VALUE fiber, int argc, VALUE *argv) {
|
34
33
|
// TODO Consider introducing something like `rb_fiber_scheduler_transfer(...)`.
|
35
34
|
#ifdef HAVE__RB_FIBER_TRANSFER
|
@@ -79,26 +78,65 @@ static VALUE rb_Process_Status = Qnil;
|
|
79
78
|
|
80
79
|
VALUE IO_Event_Selector_process_status_wait(rb_pid_t pid)
|
81
80
|
{
|
82
|
-
return rb_funcall(rb_Process_Status, id_wait, 2, PIDT2NUM(pid),
|
81
|
+
return rb_funcall(rb_Process_Status, id_wait, 2, PIDT2NUM(pid), process_wnohang);
|
83
82
|
}
|
84
83
|
#endif
|
85
84
|
|
86
85
|
int IO_Event_Selector_nonblock_set(int file_descriptor)
|
87
86
|
{
|
87
|
+
#ifdef _WIN32
|
88
|
+
u_long nonblock = 1;
|
89
|
+
int result = ioctlsocket(file_descriptor, FIONBIO, &nonblock);
|
90
|
+
// Windows does not provide any way to know this, so we always restore it back to unset:
|
91
|
+
return 0;
|
92
|
+
#else
|
93
|
+
// Get the current mode:
|
88
94
|
int flags = fcntl(file_descriptor, F_GETFL, 0);
|
89
95
|
|
96
|
+
// Set the non-blocking flag if it isn't already:
|
90
97
|
if (!(flags & O_NONBLOCK)) {
|
91
98
|
fcntl(file_descriptor, F_SETFL, flags | O_NONBLOCK);
|
92
99
|
}
|
93
100
|
|
94
101
|
return flags;
|
102
|
+
#endif
|
95
103
|
}
|
96
104
|
|
97
105
|
void IO_Event_Selector_nonblock_restore(int file_descriptor, int flags)
|
98
106
|
{
|
107
|
+
#ifdef _WIN32
|
108
|
+
// Yolo...
|
109
|
+
u_long nonblock = flags;
|
110
|
+
int result = ioctlsocket(file_descriptor, FIONBIO, &nonblock);
|
111
|
+
#else
|
112
|
+
// The flags didn't have O_NONBLOCK set, so it would have been set, so we need to restore it:
|
99
113
|
if (!(flags & O_NONBLOCK)) {
|
100
|
-
fcntl(file_descriptor, F_SETFL, flags
|
114
|
+
fcntl(file_descriptor, F_SETFL, flags);
|
101
115
|
}
|
116
|
+
#endif
|
117
|
+
}
|
118
|
+
|
119
|
+
struct IO_Event_Selector_nonblock_arguments {
|
120
|
+
int file_descriptor;
|
121
|
+
int flags;
|
122
|
+
};
|
123
|
+
|
124
|
+
static VALUE IO_Event_Selector_nonblock_ensure(VALUE _arguments) {
|
125
|
+
struct IO_Event_Selector_nonblock_arguments *arguments = (struct IO_Event_Selector_nonblock_arguments *)_arguments;
|
126
|
+
|
127
|
+
IO_Event_Selector_nonblock_restore(arguments->file_descriptor, arguments->flags);
|
128
|
+
|
129
|
+
return Qnil;
|
130
|
+
}
|
131
|
+
|
132
|
+
static VALUE IO_Event_Selector_nonblock(VALUE class, VALUE io)
|
133
|
+
{
|
134
|
+
struct IO_Event_Selector_nonblock_arguments arguments = {
|
135
|
+
.file_descriptor = IO_Event_Selector_io_descriptor(io),
|
136
|
+
.flags = IO_Event_Selector_nonblock_set(arguments.file_descriptor)
|
137
|
+
};
|
138
|
+
|
139
|
+
return rb_ensure(rb_yield, io, IO_Event_Selector_nonblock_ensure, (VALUE)&arguments);
|
102
140
|
}
|
103
141
|
|
104
142
|
void Init_IO_Event_Selector(VALUE IO_Event_Selector) {
|
@@ -119,9 +157,12 @@ void Init_IO_Event_Selector(VALUE IO_Event_Selector) {
|
|
119
157
|
|
120
158
|
#ifndef HAVE_RB_PROCESS_STATUS_WAIT
|
121
159
|
id_wait = rb_intern("wait");
|
160
|
+
process_wnohang = rb_const_get(rb_mProcess, rb_intern("WNOHANG"));
|
122
161
|
rb_Process_Status = rb_const_get_at(rb_mProcess, rb_intern("Status"));
|
123
162
|
rb_gc_register_mark_object(rb_Process_Status);
|
124
163
|
#endif
|
164
|
+
|
165
|
+
rb_define_singleton_method(IO_Event_Selector, "nonblock", IO_Event_Selector_nonblock, 1);
|
125
166
|
}
|
126
167
|
|
127
168
|
struct wait_and_transfer_arguments {
|
@@ -326,6 +326,7 @@ VALUE io_wait_rescue(VALUE _arguments, VALUE exception) {
|
|
326
326
|
if (DEBUG) fprintf(stderr, "io_wait_rescue:io_uring_prep_poll_remove(%p)\n", (void*)arguments->fiber);
|
327
327
|
|
328
328
|
io_uring_prep_poll_remove(sqe, (uintptr_t)arguments->fiber);
|
329
|
+
io_uring_sqe_set_data(sqe, NULL);
|
329
330
|
io_uring_submit_now(data);
|
330
331
|
|
331
332
|
rb_exc_raise(exception);
|
@@ -376,7 +377,7 @@ VALUE IO_Event_Selector_URing_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE e
|
|
376
377
|
return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
|
377
378
|
}
|
378
379
|
|
379
|
-
#ifdef
|
380
|
+
#ifdef HAVE_RUBY_IO_BUFFER_H
|
380
381
|
|
381
382
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0)
|
382
383
|
static inline off_t io_seekable(int descriptor) {
|
@@ -707,6 +708,8 @@ VALUE IO_Event_Selector_URing_wakeup(VALUE self) {
|
|
707
708
|
}
|
708
709
|
|
709
710
|
io_uring_prep_nop(sqe);
|
711
|
+
// If you don't set this line, the SQE will eventually be recycled and have valid user data which can cause odd behaviour:
|
712
|
+
io_uring_sqe_set_data(sqe, NULL);
|
710
713
|
io_uring_submit(&data->ring);
|
711
714
|
|
712
715
|
return Qtrue;
|
@@ -737,9 +740,11 @@ void Init_IO_Event_Selector_URing(VALUE IO_Event_Selector) {
|
|
737
740
|
rb_define_method(IO_Event_Selector_URing, "close", IO_Event_Selector_URing_close, 0);
|
738
741
|
|
739
742
|
rb_define_method(IO_Event_Selector_URing, "io_wait", IO_Event_Selector_URing_io_wait, 3);
|
740
|
-
|
743
|
+
|
744
|
+
#ifdef HAVE_RUBY_IO_BUFFER_H
|
741
745
|
rb_define_method(IO_Event_Selector_URing, "io_read", IO_Event_Selector_URing_io_read_compatible, -1);
|
742
746
|
rb_define_method(IO_Event_Selector_URing, "io_write", IO_Event_Selector_URing_io_write_compatible, -1);
|
747
|
+
#endif
|
743
748
|
|
744
749
|
rb_define_method(IO_Event_Selector_URing, "io_close", IO_Event_Selector_URing_io_close, 1);
|
745
750
|
|
@@ -6,8 +6,6 @@
|
|
6
6
|
require_relative '../interrupt'
|
7
7
|
require_relative '../support'
|
8
8
|
|
9
|
-
require 'io/nonblock'
|
10
|
-
|
11
9
|
module IO::Event
|
12
10
|
module Selector
|
13
11
|
class Select
|
@@ -136,29 +134,35 @@ module IO::Event
|
|
136
134
|
waiter&.invalidate
|
137
135
|
end
|
138
136
|
|
137
|
+
EAGAIN = -Errno::EAGAIN::Errno
|
138
|
+
EWOULDBLOCK = -Errno::EWOULDBLOCK::Errno
|
139
|
+
|
140
|
+
def again?(errno)
|
141
|
+
errno == EAGAIN or errno == EWOULDBLOCK
|
142
|
+
end
|
143
|
+
|
139
144
|
if Support.fiber_scheduler_v2?
|
140
|
-
EAGAIN = Errno::EAGAIN::Errno
|
141
|
-
|
142
145
|
def io_read(fiber, io, buffer, length, offset = 0)
|
143
146
|
total = 0
|
144
|
-
io.nonblock = true
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
if
|
152
|
-
|
153
|
-
|
148
|
+
Selector.nonblock(io) do
|
149
|
+
while true
|
150
|
+
maximum_size = buffer.size - offset
|
151
|
+
result = Fiber.blocking{buffer.read(io, maximum_size, offset)}
|
152
|
+
|
153
|
+
if again?(result)
|
154
|
+
if length > 0
|
155
|
+
self.io_wait(fiber, io, IO::READABLE)
|
156
|
+
else
|
157
|
+
return result
|
158
|
+
end
|
159
|
+
elsif result < 0
|
154
160
|
return result
|
161
|
+
else
|
162
|
+
total += result
|
163
|
+
offset += result
|
164
|
+
break if total >= length
|
155
165
|
end
|
156
|
-
elsif result < 0
|
157
|
-
return result
|
158
|
-
else
|
159
|
-
total += result
|
160
|
-
offset += result
|
161
|
-
break if total >= length
|
162
166
|
end
|
163
167
|
end
|
164
168
|
|
@@ -167,34 +171,34 @@ module IO::Event
|
|
167
171
|
|
168
172
|
def io_write(fiber, io, buffer, length, offset = 0)
|
169
173
|
total = 0
|
170
|
-
io.nonblock = true
|
171
174
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
if
|
178
|
-
|
179
|
-
|
175
|
+
Selector.nonblock(io) do
|
176
|
+
while true
|
177
|
+
maximum_size = buffer.size - offset
|
178
|
+
result = Fiber.blocking{buffer.write(io, maximum_size, offset)}
|
179
|
+
|
180
|
+
if again?(result)
|
181
|
+
if length > 0
|
182
|
+
self.io_wait(fiber, io, IO::READABLE)
|
183
|
+
else
|
184
|
+
return result
|
185
|
+
end
|
186
|
+
elsif result < 0
|
180
187
|
return result
|
188
|
+
else
|
189
|
+
total += result
|
190
|
+
offset += result
|
191
|
+
break if total >= length
|
181
192
|
end
|
182
|
-
elsif result < 0
|
183
|
-
return result
|
184
|
-
else
|
185
|
-
total += result
|
186
|
-
offset += result
|
187
|
-
break if total >= length
|
188
193
|
end
|
189
194
|
end
|
190
195
|
|
191
|
-
return
|
196
|
+
return total
|
192
197
|
end
|
193
198
|
elsif Support.fiber_scheduler_v1?
|
194
|
-
EAGAIN = Errno::EAGAIN::Errno
|
195
|
-
|
196
199
|
def io_read(fiber, _io, buffer, length, offset = 0)
|
197
200
|
io = IO.for_fd(_io.fileno, autoclose: false)
|
201
|
+
total = 0
|
198
202
|
|
199
203
|
while true
|
200
204
|
maximum_size = buffer.size - offset
|
@@ -204,13 +208,13 @@ module IO::Event
|
|
204
208
|
if length > 0
|
205
209
|
self.io_wait(fiber, io, IO::READABLE)
|
206
210
|
else
|
207
|
-
return
|
211
|
+
return EWOULDBLOCK
|
208
212
|
end
|
209
213
|
when :wait_writable
|
210
214
|
if length > 0
|
211
215
|
self.io_wait(fiber, io, IO::WRITABLE)
|
212
216
|
else
|
213
|
-
return
|
217
|
+
return EWOULDBLOCK
|
214
218
|
end
|
215
219
|
when nil
|
216
220
|
break
|
@@ -218,17 +222,19 @@ module IO::Event
|
|
218
222
|
buffer.set_string(result, offset)
|
219
223
|
|
220
224
|
size = result.bytesize
|
225
|
+
total += size
|
221
226
|
offset += size
|
222
227
|
break if size >= length
|
223
228
|
length -= size
|
224
229
|
end
|
225
230
|
end
|
226
231
|
|
227
|
-
return
|
232
|
+
return total
|
228
233
|
end
|
229
234
|
|
230
235
|
def io_write(fiber, _io, buffer, length, offset = 0)
|
231
236
|
io = IO.for_fd(_io.fileno, autoclose: false)
|
237
|
+
total = 0
|
232
238
|
|
233
239
|
while true
|
234
240
|
maximum_size = buffer.size - offset
|
@@ -239,22 +245,23 @@ module IO::Event
|
|
239
245
|
if length > 0
|
240
246
|
self.io_wait(fiber, io, IO::READABLE)
|
241
247
|
else
|
242
|
-
return
|
248
|
+
return EWOULDBLOCK
|
243
249
|
end
|
244
250
|
when :wait_writable
|
245
251
|
if length > 0
|
246
252
|
self.io_wait(fiber, io, IO::WRITABLE)
|
247
253
|
else
|
248
|
-
return
|
254
|
+
return EWOULDBLOCK
|
249
255
|
end
|
250
256
|
else
|
257
|
+
total += result
|
251
258
|
offset += result
|
252
259
|
break if result >= length
|
253
260
|
length -= result
|
254
261
|
end
|
255
262
|
end
|
256
263
|
|
257
|
-
return
|
264
|
+
return total
|
258
265
|
end
|
259
266
|
|
260
267
|
def blocking(&block)
|
data/lib/io/event/version.rb
CHANGED
data/lib/io/event.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-event
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -41,7 +41,7 @@ cert_chain:
|
|
41
41
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
42
42
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
43
43
|
-----END CERTIFICATE-----
|
44
|
-
date: 2022-10-
|
44
|
+
date: 2022-10-19 00:00:00.000000000 Z
|
45
45
|
dependencies:
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: bake
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- lib/io/event/debug/selector.rb
|
126
126
|
- lib/io/event/interrupt.rb
|
127
127
|
- lib/io/event/selector.rb
|
128
|
+
- lib/io/event/selector/nonblock.rb
|
128
129
|
- lib/io/event/selector/select.rb
|
129
130
|
- lib/io/event/support.rb
|
130
131
|
- lib/io/event/version.rb
|
metadata.gz.sig
CHANGED
Binary file
|