io-event 1.7.4 → 1.10.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 +2 -2
- data/ext/io/event/{selector/array.h → array.h} +23 -1
- data/ext/io/event/event.c +6 -20
- data/ext/io/event/event.h +2 -19
- data/ext/io/event/fiber.c +63 -0
- data/ext/io/event/fiber.h +23 -0
- data/ext/io/event/interrupt.c +12 -27
- data/ext/io/event/interrupt.h +2 -19
- data/ext/io/event/{selector/list.h → list.h} +1 -1
- data/ext/io/event/selector/epoll.c +36 -35
- data/ext/io/event/selector/epoll.h +2 -19
- data/ext/io/event/selector/kqueue.c +37 -35
- data/ext/io/event/selector/kqueue.h +2 -19
- data/ext/io/event/selector/pidfd.c +2 -19
- data/ext/io/event/selector/selector.c +42 -101
- data/ext/io/event/selector/selector.h +45 -43
- data/ext/io/event/selector/uring.c +37 -35
- data/ext/io/event/selector/uring.h +2 -19
- data/ext/io/event/time.c +35 -0
- data/ext/io/event/time.h +17 -0
- data/lib/io/event/debug/selector.rb +41 -1
- data/lib/io/event/native.rb +11 -0
- data/lib/io/event/priority_heap.rb +13 -14
- data/lib/io/event/selector/nonblock.rb +4 -0
- data/lib/io/event/selector/select.rb +19 -3
- data/lib/io/event/selector.rb +10 -0
- data/lib/io/event/support.rb +12 -0
- data/lib/io/event/timers.rb +41 -3
- data/lib/io/event/version.rb +4 -2
- data/lib/io/event.rb +2 -8
- data/license.md +1 -1
- data/readme.md +25 -2
- data/releases.md +18 -0
- data.tar.gz.sig +0 -0
- metadata +13 -10
- 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: ec418d3289f8648ac13d7808bbe8d56b50a3b4cf518f61da116c56c3c345daa9
|
4
|
+
data.tar.gz: 8de6423981f2bfb2da54e0cd99e493787253a2c2c83bc644f72fffdcf52a295c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fd70cf075b1703fd8e4659fa2adaf7381f7d5523e47e8700eeda233a01679c671ebb8197fd06f525da17b7a30332e996dd087874503f8ff7a594b8f88268554
|
7
|
+
data.tar.gz: c42e23c74e1069fb199fd1044b7fc487b8f1587294703a19362242bbbfa23c21fbba36a6a114fafb978ddc4cfcd2a21d2a6c7b7c3d3dc1c4a08094ca9b51bd2a
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/ext/extconf.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Released under the MIT License.
|
5
|
-
# Copyright, 2021-
|
5
|
+
# Copyright, 2021-2025, by Samuel Williams.
|
6
6
|
# Copyright, 2023, by Math Ieu.
|
7
7
|
|
8
8
|
return if RUBY_DESCRIPTION =~ /jruby/
|
@@ -22,7 +22,7 @@ if ENV.key?("RUBY_DEBUG")
|
|
22
22
|
$CFLAGS << " -DRUBY_DEBUG -O0"
|
23
23
|
end
|
24
24
|
|
25
|
-
$srcs = ["io/event/event.c", "io/event/selector/selector.c"]
|
25
|
+
$srcs = ["io/event/event.c", "io/event/time.c", "io/event/fiber.c", "io/event/selector/selector.c"]
|
26
26
|
$VPATH << "$(srcdir)/io/event"
|
27
27
|
$VPATH << "$(srcdir)/io/event/selector"
|
28
28
|
|
@@ -28,7 +28,7 @@ struct IO_Event_Array {
|
|
28
28
|
void (*element_free)(void*);
|
29
29
|
};
|
30
30
|
|
31
|
-
inline static int
|
31
|
+
inline static int IO_Event_Array_initialize(struct IO_Event_Array *array, size_t count, size_t element_size)
|
32
32
|
{
|
33
33
|
array->limit = 0;
|
34
34
|
array->element_size = element_size;
|
@@ -153,6 +153,28 @@ inline static void* IO_Event_Array_lookup(struct IO_Event_Array *array, size_t i
|
|
153
153
|
return *element;
|
154
154
|
}
|
155
155
|
|
156
|
+
inline static void* IO_Event_Array_last(struct IO_Event_Array *array)
|
157
|
+
{
|
158
|
+
if (array->limit == 0) return NULL;
|
159
|
+
else return array->base[array->limit - 1];
|
160
|
+
}
|
161
|
+
|
162
|
+
inline static void IO_Event_Array_truncate(struct IO_Event_Array *array, size_t limit)
|
163
|
+
{
|
164
|
+
if (limit < array->limit) {
|
165
|
+
for (size_t i = limit; i < array->limit; i += 1) {
|
166
|
+
void **element = array->base + i;
|
167
|
+
if (*element) {
|
168
|
+
array->element_free(*element);
|
169
|
+
free(*element);
|
170
|
+
*element = NULL;
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
array->limit = limit;
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
156
178
|
// Push a new element onto the end of the array.
|
157
179
|
inline static void* IO_Event_Array_push(struct IO_Event_Array *array)
|
158
180
|
{
|
data/ext/io/event/event.c
CHANGED
@@ -1,24 +1,8 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
// of this software and associated documentation files (the "Software"), to deal
|
5
|
-
// in the Software without restriction, including without limitation the rights
|
6
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
// copies of the Software, and to permit persons to whom the Software is
|
8
|
-
// furnished to do so, subject to the following conditions:
|
9
|
-
//
|
10
|
-
// The above copyright notice and this permission notice shall be included in
|
11
|
-
// all copies or substantial portions of the Software.
|
12
|
-
//
|
13
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
// THE SOFTWARE.
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2021-2025, by Samuel Williams.
|
20
3
|
|
21
4
|
#include "event.h"
|
5
|
+
#include "fiber.h"
|
22
6
|
#include "selector/selector.h"
|
23
7
|
|
24
8
|
void Init_IO_Event(void)
|
@@ -28,8 +12,10 @@ void Init_IO_Event(void)
|
|
28
12
|
#endif
|
29
13
|
|
30
14
|
VALUE IO_Event = rb_define_module_under(rb_cIO, "Event");
|
31
|
-
VALUE IO_Event_Selector = rb_define_module_under(IO_Event, "Selector");
|
32
15
|
|
16
|
+
Init_IO_Event_Fiber(IO_Event);
|
17
|
+
|
18
|
+
VALUE IO_Event_Selector = rb_define_module_under(IO_Event, "Selector");
|
33
19
|
Init_IO_Event_Selector(IO_Event_Selector);
|
34
20
|
|
35
21
|
#ifdef IO_EVENT_SELECTOR_URING
|
data/ext/io/event/event.h
CHANGED
@@ -1,22 +1,5 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
// of this software and associated documentation files (the "Software"), to deal
|
5
|
-
// in the Software without restriction, including without limitation the rights
|
6
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
// copies of the Software, and to permit persons to whom the Software is
|
8
|
-
// furnished to do so, subject to the following conditions:
|
9
|
-
//
|
10
|
-
// The above copyright notice and this permission notice shall be included in
|
11
|
-
// all copies or substantial portions of the Software.
|
12
|
-
//
|
13
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
// THE SOFTWARE.
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2021-2025, by Samuel Williams.
|
20
3
|
|
21
4
|
#pragma once
|
22
5
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2025, by Samuel Williams.
|
3
|
+
|
4
|
+
#include "fiber.h"
|
5
|
+
|
6
|
+
static ID id_transfer, id_alive_p;
|
7
|
+
|
8
|
+
VALUE IO_Event_Fiber_transfer(VALUE fiber, int argc, VALUE *argv) {
|
9
|
+
// TODO Consider introducing something like `rb_fiber_scheduler_transfer(...)`.
|
10
|
+
#ifdef HAVE__RB_FIBER_TRANSFER
|
11
|
+
if (RTEST(rb_obj_is_fiber(fiber))) {
|
12
|
+
if (RTEST(rb_fiber_alive_p(fiber))) {
|
13
|
+
return rb_fiber_transfer(fiber, argc, argv);
|
14
|
+
}
|
15
|
+
|
16
|
+
// If it's a fiber, but dead, we are done.
|
17
|
+
return Qnil;
|
18
|
+
}
|
19
|
+
#endif
|
20
|
+
if (RTEST(rb_funcall(fiber, id_alive_p, 0))) {
|
21
|
+
return rb_funcallv(fiber, id_transfer, argc, argv);
|
22
|
+
}
|
23
|
+
|
24
|
+
return Qnil;
|
25
|
+
}
|
26
|
+
|
27
|
+
#ifndef HAVE__RB_FIBER_RAISE
|
28
|
+
static ID id_raise;
|
29
|
+
|
30
|
+
VALUE IO_Event_Fiber_raise(VALUE fiber, int argc, VALUE *argv) {
|
31
|
+
return rb_funcallv(fiber, id_raise, argc, argv);
|
32
|
+
}
|
33
|
+
#endif
|
34
|
+
|
35
|
+
#ifndef HAVE_RB_FIBER_CURRENT
|
36
|
+
static ID id_current;
|
37
|
+
|
38
|
+
static VALUE IO_Event_Fiber_current(void) {
|
39
|
+
return rb_funcall(rb_cFiber, id_current, 0);
|
40
|
+
}
|
41
|
+
#endif
|
42
|
+
|
43
|
+
// There is no public interface for this... yet.
|
44
|
+
static ID id_blocking_p;
|
45
|
+
|
46
|
+
int IO_Event_Fiber_blocking(VALUE fiber) {
|
47
|
+
return RTEST(rb_funcall(fiber, id_blocking_p, 0));
|
48
|
+
}
|
49
|
+
|
50
|
+
void Init_IO_Event_Fiber(VALUE IO_Event) {
|
51
|
+
id_transfer = rb_intern("transfer");
|
52
|
+
id_alive_p = rb_intern("alive?");
|
53
|
+
|
54
|
+
#ifndef HAVE__RB_FIBER_RAISE
|
55
|
+
id_raise = rb_intern("raise");
|
56
|
+
#endif
|
57
|
+
|
58
|
+
#ifndef HAVE_RB_FIBER_CURRENT
|
59
|
+
id_current = rb_intern("current");
|
60
|
+
#endif
|
61
|
+
|
62
|
+
id_blocking_p = rb_intern("blocking?");
|
63
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2025, by Samuel Williams.
|
3
|
+
|
4
|
+
#pragma once
|
5
|
+
|
6
|
+
#include <ruby.h>
|
7
|
+
|
8
|
+
VALUE IO_Event_Fiber_transfer(VALUE fiber, int argc, VALUE *argv);
|
9
|
+
|
10
|
+
#ifdef HAVE__RB_FIBER_RAISE
|
11
|
+
#define IO_Event_Fiber_raise(fiber, argc, argv) rb_fiber_raise(fiber, argc, argv)
|
12
|
+
#else
|
13
|
+
VALUE IO_Event_Fiber_raise(VALUE fiber, int argc, VALUE *argv);
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#ifdef HAVE_RB_FIBER_CURRENT
|
17
|
+
#define IO_Event_Fiber_current() rb_fiber_current()
|
18
|
+
#else
|
19
|
+
VALUE IO_Event_Fiber_current(void);
|
20
|
+
#endif
|
21
|
+
|
22
|
+
int IO_Event_Fiber_blocking(VALUE fiber);
|
23
|
+
void Init_IO_Event_Fiber(VALUE IO_Event);
|
data/ext/io/event/interrupt.c
CHANGED
@@ -1,24 +1,5 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
// of this software and associated documentation files (the "Software"), to deal
|
5
|
-
// in the Software without restriction, including without limitation the rights
|
6
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
// copies of the Software, and to permit persons to whom the Software is
|
8
|
-
// furnished to do so, subject to the following conditions:
|
9
|
-
//
|
10
|
-
// The above copyright notice and this permission notice shall be included in
|
11
|
-
// all copies or substantial portions of the Software.
|
12
|
-
//
|
13
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
// THE SOFTWARE.
|
20
|
-
|
21
|
-
// static const int DEBUG = 0;
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2021-2025, by Samuel Williams.
|
22
3
|
|
23
4
|
#include "interrupt.h"
|
24
5
|
#include <unistd.h>
|
@@ -95,9 +76,11 @@ void IO_Event_Interrupt_signal(struct IO_Event_Interrupt *interrupt)
|
|
95
76
|
ssize_t result = write(interrupt->descriptor[1], ".", 1);
|
96
77
|
|
97
78
|
if (result == -1) {
|
98
|
-
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
99
|
-
|
100
|
-
|
79
|
+
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
80
|
+
// If we can't write to the pipe, it means the other end is full. In that case, we can be sure that the other end has already been woken up or is about to be woken up.
|
81
|
+
} else {
|
82
|
+
rb_sys_fail("IO_Event_Interrupt_signal:write");
|
83
|
+
}
|
101
84
|
}
|
102
85
|
}
|
103
86
|
|
@@ -107,9 +90,11 @@ void IO_Event_Interrupt_clear(struct IO_Event_Interrupt *interrupt)
|
|
107
90
|
ssize_t result = read(interrupt->descriptor[0], buffer, sizeof(buffer));
|
108
91
|
|
109
92
|
if (result == -1) {
|
110
|
-
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
111
|
-
|
112
|
-
|
93
|
+
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
94
|
+
// If we can't read from the pipe, it means the other end is empty. In that case, we can be sure that the other end is already clear.
|
95
|
+
} else {
|
96
|
+
rb_sys_fail("IO_Event_Interrupt_clear:read");
|
97
|
+
}
|
113
98
|
}
|
114
99
|
}
|
115
100
|
#endif
|
data/ext/io/event/interrupt.h
CHANGED
@@ -1,22 +1,5 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
// of this software and associated documentation files (the "Software"), to deal
|
5
|
-
// in the Software without restriction, including without limitation the rights
|
6
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
// copies of the Software, and to permit persons to whom the Software is
|
8
|
-
// furnished to do so, subject to the following conditions:
|
9
|
-
//
|
10
|
-
// The above copyright notice and this permission notice shall be included in
|
11
|
-
// all copies or substantial portions of the Software.
|
12
|
-
//
|
13
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
// THE SOFTWARE.
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2021-2025, by Samuel Williams.
|
20
3
|
|
21
4
|
#pragma once
|
22
5
|
|
@@ -1,27 +1,10 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
// of this software and associated documentation files (the "Software"), to deal
|
5
|
-
// in the Software without restriction, including without limitation the rights
|
6
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
// copies of the Software, and to permit persons to whom the Software is
|
8
|
-
// furnished to do so, subject to the following conditions:
|
9
|
-
//
|
10
|
-
// The above copyright notice and this permission notice shall be included in
|
11
|
-
// all copies or substantial portions of the Software.
|
12
|
-
//
|
13
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
// THE SOFTWARE.
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2021-2025, by Samuel Williams.
|
20
3
|
|
21
4
|
#include "epoll.h"
|
22
5
|
#include "selector.h"
|
23
|
-
#include "list.h"
|
24
|
-
#include "array.h"
|
6
|
+
#include "../list.h"
|
7
|
+
#include "../array.h"
|
25
8
|
|
26
9
|
#include <sys/epoll.h>
|
27
10
|
#include <time.h>
|
@@ -174,7 +157,7 @@ size_t IO_Event_Selector_EPoll_Type_size(const void *_selector)
|
|
174
157
|
}
|
175
158
|
|
176
159
|
static const rb_data_type_t IO_Event_Selector_EPoll_Type = {
|
177
|
-
.wrap_struct_name = "
|
160
|
+
.wrap_struct_name = "IO::Event::Backend::EPoll",
|
178
161
|
.function = {
|
179
162
|
.dmark = IO_Event_Selector_EPoll_Type_mark,
|
180
163
|
.dcompact = IO_Event_Selector_EPoll_Type_compact,
|
@@ -337,9 +320,9 @@ VALUE IO_Event_Selector_EPoll_allocate(VALUE self) {
|
|
337
320
|
|
338
321
|
selector->descriptors.element_initialize = IO_Event_Selector_EPoll_Descriptor_initialize;
|
339
322
|
selector->descriptors.element_free = IO_Event_Selector_EPoll_Descriptor_free;
|
340
|
-
int result =
|
323
|
+
int result = IO_Event_Array_initialize(&selector->descriptors, IO_EVENT_ARRAY_DEFAULT_COUNT, sizeof(struct IO_Event_Selector_EPoll_Descriptor));
|
341
324
|
if (result < 0) {
|
342
|
-
rb_sys_fail("IO_Event_Selector_EPoll_allocate:
|
325
|
+
rb_sys_fail("IO_Event_Selector_EPoll_allocate:IO_Event_Array_initialize");
|
343
326
|
}
|
344
327
|
|
345
328
|
return instance;
|
@@ -411,7 +394,7 @@ VALUE IO_Event_Selector_EPoll_transfer(VALUE self)
|
|
411
394
|
struct IO_Event_Selector_EPoll *selector = NULL;
|
412
395
|
TypedData_Get_Struct(self, struct IO_Event_Selector_EPoll, &IO_Event_Selector_EPoll_Type, selector);
|
413
396
|
|
414
|
-
return
|
397
|
+
return IO_Event_Selector_loop_yield(&selector->backend);
|
415
398
|
}
|
416
399
|
|
417
400
|
VALUE IO_Event_Selector_EPoll_resume(int argc, VALUE *argv, VALUE self)
|
@@ -435,7 +418,7 @@ VALUE IO_Event_Selector_EPoll_push(VALUE self, VALUE fiber)
|
|
435
418
|
struct IO_Event_Selector_EPoll *selector = NULL;
|
436
419
|
TypedData_Get_Struct(self, struct IO_Event_Selector_EPoll, &IO_Event_Selector_EPoll_Type, selector);
|
437
420
|
|
438
|
-
|
421
|
+
IO_Event_Selector_ready_push(&selector->backend, fiber);
|
439
422
|
|
440
423
|
return Qnil;
|
441
424
|
}
|
@@ -467,7 +450,7 @@ static
|
|
467
450
|
VALUE process_wait_transfer(VALUE _arguments) {
|
468
451
|
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
469
452
|
|
470
|
-
|
453
|
+
IO_Event_Selector_loop_yield(&arguments->selector->backend);
|
471
454
|
|
472
455
|
if (arguments->waiting->ready) {
|
473
456
|
return IO_Event_Selector_process_status_wait(arguments->pid, arguments->flags);
|
@@ -519,7 +502,7 @@ VALUE IO_Event_Selector_EPoll_process_wait(VALUE self, VALUE fiber, VALUE _pid,
|
|
519
502
|
|
520
503
|
RB_OBJ_WRITTEN(self, Qundef, fiber);
|
521
504
|
|
522
|
-
int result = IO_Event_Selector_EPoll_Waiting_register(selector,
|
505
|
+
int result = IO_Event_Selector_EPoll_Waiting_register(selector, _pid, descriptor, &waiting);
|
523
506
|
|
524
507
|
if (result == -1) {
|
525
508
|
close(descriptor);
|
@@ -555,7 +538,7 @@ static
|
|
555
538
|
VALUE io_wait_transfer(VALUE _arguments) {
|
556
539
|
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
557
540
|
|
558
|
-
|
541
|
+
IO_Event_Selector_loop_yield(&arguments->selector->backend);
|
559
542
|
|
560
543
|
if (arguments->waiting->ready) {
|
561
544
|
return RB_INT2NUM(arguments->waiting->ready);
|
@@ -584,7 +567,7 @@ VALUE IO_Event_Selector_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE e
|
|
584
567
|
|
585
568
|
if (result == -1) {
|
586
569
|
if (errno == EPERM) {
|
587
|
-
|
570
|
+
IO_Event_Selector_ready_push(&selector->backend, fiber);
|
588
571
|
IO_Event_Selector_yield(&selector->backend);
|
589
572
|
return events;
|
590
573
|
}
|
@@ -942,7 +925,7 @@ int IO_Event_Selector_EPoll_handle(struct IO_Event_Selector_EPoll *selector, con
|
|
942
925
|
|
943
926
|
// Resume the fiber:
|
944
927
|
waiting->ready = matching_events;
|
945
|
-
|
928
|
+
IO_Event_Selector_loop_resume(&selector->backend, waiting->fiber, 0, NULL);
|
946
929
|
|
947
930
|
node = saved->tail;
|
948
931
|
IO_Event_List_pop(saved);
|
@@ -994,7 +977,7 @@ VALUE IO_Event_Selector_EPoll_select(VALUE self, VALUE duration) {
|
|
994
977
|
selector->idle_duration.tv_sec = 0;
|
995
978
|
selector->idle_duration.tv_nsec = 0;
|
996
979
|
|
997
|
-
int ready =
|
980
|
+
int ready = IO_Event_Selector_ready_flush(&selector->backend);
|
998
981
|
|
999
982
|
struct select_arguments arguments = {
|
1000
983
|
.selector = selector,
|
@@ -1020,14 +1003,14 @@ VALUE IO_Event_Selector_EPoll_select(VALUE self, VALUE duration) {
|
|
1020
1003
|
|
1021
1004
|
if (!timeout_nonblocking(arguments.timeout)) {
|
1022
1005
|
struct timespec start_time;
|
1023
|
-
|
1006
|
+
IO_Event_Time_current(&start_time);
|
1024
1007
|
|
1025
1008
|
// Wait for events to occur:
|
1026
1009
|
select_internal_without_gvl(&arguments);
|
1027
1010
|
|
1028
1011
|
struct timespec end_time;
|
1029
|
-
|
1030
|
-
|
1012
|
+
IO_Event_Time_current(&end_time);
|
1013
|
+
IO_Event_Time_elapsed(&start_time, &end_time, &selector->idle_duration);
|
1031
1014
|
}
|
1032
1015
|
}
|
1033
1016
|
|
@@ -1052,7 +1035,25 @@ VALUE IO_Event_Selector_EPoll_wakeup(VALUE self) {
|
|
1052
1035
|
return Qfalse;
|
1053
1036
|
}
|
1054
1037
|
|
1038
|
+
static int IO_Event_Selector_EPoll_supported_p(void) {
|
1039
|
+
int fd = epoll_create1(EPOLL_CLOEXEC);
|
1040
|
+
|
1041
|
+
if (fd < 0) {
|
1042
|
+
rb_warn("epoll_create1() was available at compile time but failed at run time: %s\n", strerror(errno));
|
1043
|
+
|
1044
|
+
return 0;
|
1045
|
+
}
|
1046
|
+
|
1047
|
+
close(fd);
|
1048
|
+
|
1049
|
+
return 1;
|
1050
|
+
}
|
1051
|
+
|
1055
1052
|
void Init_IO_Event_Selector_EPoll(VALUE IO_Event_Selector) {
|
1053
|
+
if (!IO_Event_Selector_EPoll_supported_p()) {
|
1054
|
+
return;
|
1055
|
+
}
|
1056
|
+
|
1056
1057
|
VALUE IO_Event_Selector_EPoll = rb_define_class_under(IO_Event_Selector, "EPoll", rb_cObject);
|
1057
1058
|
|
1058
1059
|
rb_define_alloc_func(IO_Event_Selector_EPoll, IO_Event_Selector_EPoll_allocate);
|
@@ -1,22 +1,5 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
// of this software and associated documentation files (the "Software"), to deal
|
5
|
-
// in the Software without restriction, including without limitation the rights
|
6
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
// copies of the Software, and to permit persons to whom the Software is
|
8
|
-
// furnished to do so, subject to the following conditions:
|
9
|
-
//
|
10
|
-
// The above copyright notice and this permission notice shall be included in
|
11
|
-
// all copies or substantial portions of the Software.
|
12
|
-
//
|
13
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
// THE SOFTWARE.
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2021-2025, by Samuel Williams.
|
20
3
|
|
21
4
|
#pragma once
|
22
5
|
|
@@ -1,27 +1,10 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
// of this software and associated documentation files (the "Software"), to deal
|
5
|
-
// in the Software without restriction, including without limitation the rights
|
6
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
// copies of the Software, and to permit persons to whom the Software is
|
8
|
-
// furnished to do so, subject to the following conditions:
|
9
|
-
//
|
10
|
-
// The above copyright notice and this permission notice shall be included in
|
11
|
-
// all copies or substantial portions of the Software.
|
12
|
-
//
|
13
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
// THE SOFTWARE.
|
1
|
+
// Released under the MIT License.
|
2
|
+
// Copyright, 2021-2025, by Samuel Williams.
|
20
3
|
|
21
4
|
#include "kqueue.h"
|
22
5
|
#include "selector.h"
|
23
|
-
#include "list.h"
|
24
|
-
#include "array.h"
|
6
|
+
#include "../list.h"
|
7
|
+
#include "../array.h"
|
25
8
|
|
26
9
|
#include <sys/event.h>
|
27
10
|
#include <sys/ioctl.h>
|
@@ -173,7 +156,7 @@ size_t IO_Event_Selector_KQueue_Type_size(const void *_selector)
|
|
173
156
|
}
|
174
157
|
|
175
158
|
static const rb_data_type_t IO_Event_Selector_KQueue_Type = {
|
176
|
-
.wrap_struct_name = "
|
159
|
+
.wrap_struct_name = "IO::Event::Backend::KQueue",
|
177
160
|
.function = {
|
178
161
|
.dmark = IO_Event_Selector_KQueue_Type_mark,
|
179
162
|
.dcompact = IO_Event_Selector_KQueue_Type_compact,
|
@@ -312,9 +295,9 @@ VALUE IO_Event_Selector_KQueue_allocate(VALUE self) {
|
|
312
295
|
selector->descriptors.element_initialize = IO_Event_Selector_KQueue_Descriptor_initialize;
|
313
296
|
selector->descriptors.element_free = IO_Event_Selector_KQueue_Descriptor_free;
|
314
297
|
|
315
|
-
int result =
|
298
|
+
int result = IO_Event_Array_initialize(&selector->descriptors, IO_EVENT_ARRAY_DEFAULT_COUNT, sizeof(struct IO_Event_Selector_KQueue_Descriptor));
|
316
299
|
if (result < 0) {
|
317
|
-
rb_sys_fail("IO_Event_Selector_KQueue_allocate:
|
300
|
+
rb_sys_fail("IO_Event_Selector_KQueue_allocate:IO_Event_Array_initialize");
|
318
301
|
}
|
319
302
|
|
320
303
|
return instance;
|
@@ -398,7 +381,7 @@ VALUE IO_Event_Selector_KQueue_transfer(VALUE self)
|
|
398
381
|
struct IO_Event_Selector_KQueue *selector = NULL;
|
399
382
|
TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, selector);
|
400
383
|
|
401
|
-
return
|
384
|
+
return IO_Event_Selector_loop_yield(&selector->backend);
|
402
385
|
}
|
403
386
|
|
404
387
|
VALUE IO_Event_Selector_KQueue_resume(int argc, VALUE *argv, VALUE self)
|
@@ -422,7 +405,7 @@ VALUE IO_Event_Selector_KQueue_push(VALUE self, VALUE fiber)
|
|
422
405
|
struct IO_Event_Selector_KQueue *selector = NULL;
|
423
406
|
TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, selector);
|
424
407
|
|
425
|
-
|
408
|
+
IO_Event_Selector_ready_push(&selector->backend, fiber);
|
426
409
|
|
427
410
|
return Qnil;
|
428
411
|
}
|
@@ -472,7 +455,7 @@ static
|
|
472
455
|
VALUE process_wait_transfer(VALUE _arguments) {
|
473
456
|
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
474
457
|
|
475
|
-
|
458
|
+
IO_Event_Selector_loop_yield(&arguments->selector->backend);
|
476
459
|
|
477
460
|
if (arguments->waiting->ready) {
|
478
461
|
process_prewait(arguments->pid);
|
@@ -548,7 +531,7 @@ static
|
|
548
531
|
VALUE io_wait_transfer(VALUE _arguments) {
|
549
532
|
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
550
533
|
|
551
|
-
|
534
|
+
IO_Event_Selector_loop_yield(&arguments->selector->backend);
|
552
535
|
|
553
536
|
if (arguments->waiting->ready) {
|
554
537
|
return RB_INT2NUM(arguments->waiting->ready);
|
@@ -914,7 +897,7 @@ int IO_Event_Selector_KQueue_handle(struct IO_Event_Selector_KQueue *selector, u
|
|
914
897
|
IO_Event_List_append(node, saved);
|
915
898
|
|
916
899
|
waiting->ready = matching_events;
|
917
|
-
|
900
|
+
IO_Event_Selector_loop_resume(&selector->backend, waiting->fiber, 0, NULL);
|
918
901
|
|
919
902
|
node = saved->tail;
|
920
903
|
IO_Event_List_pop(saved);
|
@@ -971,7 +954,7 @@ VALUE IO_Event_Selector_KQueue_select(VALUE self, VALUE duration) {
|
|
971
954
|
selector->idle_duration.tv_sec = 0;
|
972
955
|
selector->idle_duration.tv_nsec = 0;
|
973
956
|
|
974
|
-
int ready =
|
957
|
+
int ready = IO_Event_Selector_ready_flush(&selector->backend);
|
975
958
|
|
976
959
|
struct select_arguments arguments = {
|
977
960
|
.selector = selector,
|
@@ -992,7 +975,7 @@ VALUE IO_Event_Selector_KQueue_select(VALUE self, VALUE duration) {
|
|
992
975
|
// Non-comprehensive testing shows this gives a 1.5x speedup.
|
993
976
|
|
994
977
|
// First do the syscall with no timeout to get any immediately available events:
|
995
|
-
if (DEBUG) fprintf(stderr, "\r\nselect_internal_with_gvl timeout="
|
978
|
+
if (DEBUG) fprintf(stderr, "\r\nselect_internal_with_gvl timeout=" IO_EVENT_TIME_PRINTF_TIMESPEC "\r\n", IO_EVENT_TIME_PRINTF_TIMESPEC_ARGUMENTS(arguments.storage));
|
996
979
|
select_internal_with_gvl(&arguments);
|
997
980
|
if (DEBUG) fprintf(stderr, "\r\nselect_internal_with_gvl done\r\n");
|
998
981
|
|
@@ -1008,14 +991,14 @@ VALUE IO_Event_Selector_KQueue_select(VALUE self, VALUE duration) {
|
|
1008
991
|
arguments.count = KQUEUE_MAX_EVENTS;
|
1009
992
|
|
1010
993
|
struct timespec start_time;
|
1011
|
-
|
994
|
+
IO_Event_Time_current(&start_time);
|
1012
995
|
|
1013
|
-
if (DEBUG) fprintf(stderr, "IO_Event_Selector_KQueue_select timeout="
|
996
|
+
if (DEBUG) fprintf(stderr, "IO_Event_Selector_KQueue_select timeout=" IO_EVENT_TIME_PRINTF_TIMESPEC "\n", IO_EVENT_TIME_PRINTF_TIMESPEC_ARGUMENTS(arguments.storage));
|
1014
997
|
select_internal_without_gvl(&arguments);
|
1015
998
|
|
1016
999
|
struct timespec end_time;
|
1017
|
-
|
1018
|
-
|
1000
|
+
IO_Event_Time_current(&end_time);
|
1001
|
+
IO_Event_Time_elapsed(&start_time, &end_time, &selector->idle_duration);
|
1019
1002
|
}
|
1020
1003
|
}
|
1021
1004
|
|
@@ -1062,7 +1045,26 @@ VALUE IO_Event_Selector_KQueue_wakeup(VALUE self) {
|
|
1062
1045
|
return Qfalse;
|
1063
1046
|
}
|
1064
1047
|
|
1048
|
+
|
1049
|
+
static int IO_Event_Selector_KQueue_supported_p(void) {
|
1050
|
+
int fd = kqueue();
|
1051
|
+
|
1052
|
+
if (fd < 0) {
|
1053
|
+
rb_warn("kqueue() was available at compile time but failed at run time: %s\n", strerror(errno));
|
1054
|
+
|
1055
|
+
return 0;
|
1056
|
+
}
|
1057
|
+
|
1058
|
+
close(fd);
|
1059
|
+
|
1060
|
+
return 1;
|
1061
|
+
}
|
1062
|
+
|
1065
1063
|
void Init_IO_Event_Selector_KQueue(VALUE IO_Event_Selector) {
|
1064
|
+
if (!IO_Event_Selector_KQueue_supported_p()) {
|
1065
|
+
return;
|
1066
|
+
}
|
1067
|
+
|
1066
1068
|
VALUE IO_Event_Selector_KQueue = rb_define_class_under(IO_Event_Selector, "KQueue", rb_cObject);
|
1067
1069
|
|
1068
1070
|
rb_define_alloc_func(IO_Event_Selector_KQueue, IO_Event_Selector_KQueue_allocate);
|