event 0.2.2 → 0.2.3
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
- data/ext/event/Makefile +28 -27
- data/ext/event/backend/backend.h +2 -0
- data/ext/event/backend/epoll.c +52 -9
- data/ext/event/backend/kqueue.c +165 -40
- data/ext/event/backend/uring.c +120 -24
- data/ext/event/backend/uring.h +1 -0
- data/ext/event/event.bundle +0 -0
- data/ext/event/event.o +0 -0
- data/ext/event/extconf.h +4 -0
- data/ext/event/extconf.rb +2 -0
- data/ext/event/kqueue.o +0 -0
- data/ext/event/mkmf.log +73 -0
- data/lib/event/backend/select.rb +8 -0
- data/lib/event/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a363339a1d384ea4d844450be2ff46cbc091bc0aca240e869491bf6a5d61300
|
4
|
+
data.tar.gz: b1b3c431481f4499bf6605010392283acfb6f54a59aed232f25217d2cce4a221
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3321631a8be1353038cdc9c63a2b6b17f02ea66924b11f5fb9126f9db1072ea4ee59141858f26e8879e1b52fe265471a2552afcab56cddd84b1e28d1611235d9
|
7
|
+
data.tar.gz: 7196977bd770153c5be35d16701e32a635c84cf53edf2880b4c5f095b8644825c7dcd1254a4da8f72655fb48e3ac3ec529d2ae2496691fb9ead30bb595cae357
|
data/ext/event/Makefile
CHANGED
@@ -12,12 +12,12 @@ NULLCMD = :
|
|
12
12
|
#### Start of system configuration section. ####
|
13
13
|
|
14
14
|
srcdir = .
|
15
|
-
topdir = /
|
15
|
+
topdir = /Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0
|
16
16
|
hdrdir = $(topdir)
|
17
|
-
arch_hdrdir = /
|
17
|
+
arch_hdrdir = /Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/x86_64-darwin20
|
18
18
|
PATH_SEPARATOR = :
|
19
19
|
VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby:$(srcdir)/backend
|
20
|
-
prefix = $(DESTDIR)/
|
20
|
+
prefix = $(DESTDIR)/Users/samuel/.rubies/ruby-3.0.0
|
21
21
|
rubysitearchprefix = $(rubylibprefix)/$(sitearch)
|
22
22
|
rubyarchprefix = $(rubylibprefix)/$(arch)
|
23
23
|
rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
|
@@ -50,7 +50,7 @@ dvidir = $(docdir)
|
|
50
50
|
htmldir = $(docdir)
|
51
51
|
infodir = $(datarootdir)/info
|
52
52
|
docdir = $(datarootdir)/doc/$(PACKAGE)
|
53
|
-
oldincludedir = $(
|
53
|
+
oldincludedir = $(SDKROOT)/usr/include
|
54
54
|
includedir = $(prefix)/include
|
55
55
|
runstatedir = $(localstatedir)/run
|
56
56
|
localstatedir = $(prefix)/var
|
@@ -65,12 +65,12 @@ archdir = $(rubyarchdir)
|
|
65
65
|
|
66
66
|
|
67
67
|
CC_WRAPPER =
|
68
|
-
CC =
|
69
|
-
CXX =
|
68
|
+
CC = clang -fdeclspec
|
69
|
+
CXX = clang++ -fdeclspec
|
70
70
|
LIBRUBY = $(LIBRUBY_A)
|
71
71
|
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
72
|
-
LIBRUBYARG_SHARED =
|
73
|
-
LIBRUBYARG_STATIC = -
|
72
|
+
LIBRUBYARG_SHARED =
|
73
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static -framework Security -framework Foundation $(MAINLIBS)
|
74
74
|
empty =
|
75
75
|
OUTFLAG = -o $(empty)
|
76
76
|
COUTFLAG = -o $(empty)
|
@@ -81,31 +81,31 @@ cflags = $(optflags) $(debugflags) $(warnflags)
|
|
81
81
|
cxxflags =
|
82
82
|
optflags = -O3
|
83
83
|
debugflags = -ggdb3
|
84
|
-
warnflags = -Wall -Wextra -Wdeprecated-declarations -
|
84
|
+
warnflags = -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens
|
85
85
|
cppflags =
|
86
|
-
CCDLFLAGS = -
|
87
|
-
CFLAGS = $(CCDLFLAGS) $(cflags) $(ARCH_FLAG)
|
86
|
+
CCDLFLAGS = -fno-common
|
87
|
+
CFLAGS = $(CCDLFLAGS) $(cflags) -pipe -Wall $(ARCH_FLAG)
|
88
88
|
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
|
89
89
|
DEFS =
|
90
|
-
CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\" $(DEFS) $(cppflags)
|
90
|
+
CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\" -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT $(DEFS) $(cppflags)
|
91
91
|
CXXFLAGS = $(CCDLFLAGS) $(ARCH_FLAG)
|
92
|
-
ldflags = -L. -fstack-protector-strong -
|
93
|
-
dldflags = -Wl
|
92
|
+
ldflags = -L. -fstack-protector-strong -L/opt/local/lib
|
93
|
+
dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -L/opt/local/lib
|
94
94
|
ARCH_FLAG =
|
95
95
|
DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
|
96
|
-
LDSHARED = $(CC) -
|
97
|
-
LDSHAREDXX = $(CXX) -
|
98
|
-
AR =
|
96
|
+
LDSHARED = $(CC) -dynamic -bundle
|
97
|
+
LDSHAREDXX = $(CXX) -dynamic -bundle
|
98
|
+
AR = ar
|
99
99
|
EXEEXT =
|
100
100
|
|
101
101
|
RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)
|
102
|
-
RUBY_SO_NAME = ruby
|
102
|
+
RUBY_SO_NAME = ruby.3.0
|
103
103
|
RUBYW_INSTALL_NAME =
|
104
104
|
RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
|
105
105
|
RUBYW_BASE_NAME = rubyw
|
106
106
|
RUBY_BASE_NAME = ruby
|
107
107
|
|
108
|
-
arch = x86_64-
|
108
|
+
arch = x86_64-darwin20
|
109
109
|
sitearch = $(arch)
|
110
110
|
ruby_version = 3.0.0
|
111
111
|
ruby = $(bindir)/$(RUBY_BASE_NAME)
|
@@ -114,8 +114,8 @@ ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h
|
|
114
114
|
|
115
115
|
RM = rm -f
|
116
116
|
RM_RF = $(RUBY) -run -e rm -- -rf
|
117
|
-
RMDIRS = rmdir
|
118
|
-
MAKEDIRS = /
|
117
|
+
RMDIRS = rmdir -p
|
118
|
+
MAKEDIRS = /opt/local/bin/gmkdir -p
|
119
119
|
INSTALL = /usr/bin/install -c
|
120
120
|
INSTALL_PROG = $(INSTALL) -m 0755
|
121
121
|
INSTALL_DATA = $(INSTALL) -m 644
|
@@ -125,8 +125,8 @@ TOUCH = exit >
|
|
125
125
|
#### End of system configuration section. ####
|
126
126
|
|
127
127
|
preload =
|
128
|
-
libpath = . $(libdir)
|
129
|
-
LIBPATH = -L. -L$(libdir) -
|
128
|
+
libpath = . $(libdir) /opt/local/lib
|
129
|
+
LIBPATH = -L. -L$(libdir) -L/opt/local/lib
|
130
130
|
DEFFILE =
|
131
131
|
|
132
132
|
CLEANFILES = mkmf.log
|
@@ -137,16 +137,16 @@ extout =
|
|
137
137
|
extout_prefix =
|
138
138
|
target_prefix = /event
|
139
139
|
LOCAL_LIBS =
|
140
|
-
LIBS =
|
140
|
+
LIBS =
|
141
141
|
ORIG_SRCS = event.c
|
142
|
-
SRCS = $(ORIG_SRCS) event.c
|
143
|
-
OBJS = event.o
|
142
|
+
SRCS = $(ORIG_SRCS) event.c kqueue.c
|
143
|
+
OBJS = event.o kqueue.o
|
144
144
|
HDRS = $(srcdir)/event.h $(srcdir)/extconf.h
|
145
145
|
LOCAL_HDRS =
|
146
146
|
TARGET = event
|
147
147
|
TARGET_NAME = event
|
148
148
|
TARGET_ENTRY = Init_$(TARGET_NAME)
|
149
|
-
DLLIB = $(TARGET).
|
149
|
+
DLLIB = $(TARGET).bundle
|
150
150
|
EXTSTATIC =
|
151
151
|
STATIC_LIB =
|
152
152
|
|
@@ -260,6 +260,7 @@ $(TARGET_SO): $(OBJS) Makefile
|
|
260
260
|
$(ECHO) linking shared-object event/$(DLLIB)
|
261
261
|
-$(Q)$(RM) $(@)
|
262
262
|
$(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
|
263
|
+
$(Q) $(POSTLINK)
|
263
264
|
|
264
265
|
|
265
266
|
|
data/ext/event/backend/backend.h
CHANGED
data/ext/event/backend/epoll.c
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
static VALUE Event_Backend_EPoll = Qnil;
|
29
29
|
static ID id_fileno, id_transfer;
|
30
30
|
|
31
|
-
|
31
|
+
enum {EPOLL_MAX_EVENTS = 64};
|
32
32
|
|
33
33
|
struct Event_Backend_EPoll {
|
34
34
|
VALUE loop;
|
@@ -212,28 +212,71 @@ int make_timeout(VALUE duration) {
|
|
212
212
|
rb_raise(rb_eRuntimeError, "unable to convert timeout");
|
213
213
|
}
|
214
214
|
|
215
|
+
struct select_arguments {
|
216
|
+
struct Event_Backend_EPoll *data;
|
217
|
+
|
218
|
+
int count;
|
219
|
+
struct epoll_event events[EPOLL_MAX_EVENTS];
|
220
|
+
|
221
|
+
int timeout;
|
222
|
+
};
|
223
|
+
|
224
|
+
static
|
225
|
+
void * select_internal(void *_arguments) {
|
226
|
+
struct select_arguments * arguments = (struct select_arguments *)_arguments;
|
227
|
+
|
228
|
+
arguments->count = epoll_wait(arguments->data->descriptor, arguments->events, EPOLL_MAX_EVENTS, arguments->timeout);
|
229
|
+
|
230
|
+
return NULL;
|
231
|
+
}
|
232
|
+
|
233
|
+
static
|
234
|
+
void select_internal_without_gvl(struct select_arguments *arguments) {
|
235
|
+
rb_thread_call_without_gvl(select_internal, (void *)arguments, RUBY_UBF_IO, 0);
|
236
|
+
|
237
|
+
if (arguments->count == -1) {
|
238
|
+
rb_sys_fail("select_internal_without_gvl:epoll_wait");
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
static
|
243
|
+
void select_internal_with_gvl(struct select_arguments *arguments) {
|
244
|
+
select_internal((void *)arguments);
|
245
|
+
|
246
|
+
if (arguments->count == -1) {
|
247
|
+
rb_sys_fail("select_internal_with_gvl:epoll_wait");
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
215
251
|
VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
|
216
252
|
struct Event_Backend_EPoll *data = NULL;
|
217
253
|
TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
|
218
254
|
|
219
|
-
struct
|
255
|
+
struct select_arguments arguments = {
|
256
|
+
.data = data,
|
257
|
+
.timeout = 0
|
258
|
+
};
|
220
259
|
|
221
|
-
|
260
|
+
select_internal_without_gvl(&arguments);
|
222
261
|
|
223
|
-
if (count ==
|
224
|
-
|
262
|
+
if (arguments.count == 0) {
|
263
|
+
arguments.timeout = make_timeout(duration);
|
264
|
+
|
265
|
+
if (arguments.timeout != 0) {
|
266
|
+
select_internal_with_gvl(&arguments);
|
267
|
+
}
|
225
268
|
}
|
226
269
|
|
227
|
-
for (int i = 0; i < count; i += 1) {
|
228
|
-
VALUE fiber = (VALUE)events[i].data.ptr;
|
229
|
-
VALUE result = INT2NUM(events[i].events);
|
270
|
+
for (int i = 0; i < arguments.count; i += 1) {
|
271
|
+
VALUE fiber = (VALUE)arguments.events[i].data.ptr;
|
272
|
+
VALUE result = INT2NUM(arguments.events[i].events);
|
230
273
|
|
231
274
|
// fprintf(stderr, "-> fiber=%p descriptor=%d\n", (void*)fiber, events[i].data.fd);
|
232
275
|
|
233
276
|
rb_funcall(fiber, id_transfer, 1, result);
|
234
277
|
}
|
235
278
|
|
236
|
-
return INT2NUM(count);
|
279
|
+
return INT2NUM(arguments.count);
|
237
280
|
}
|
238
281
|
|
239
282
|
void Init_Event_Backend_EPoll(VALUE Event_Backend) {
|
data/ext/event/backend/kqueue.c
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
static VALUE Event_Backend_KQueue = Qnil;
|
29
29
|
static ID id_fileno, id_transfer;
|
30
30
|
|
31
|
-
|
31
|
+
enum {KQUEUE_MAX_EVENTS = 64};
|
32
32
|
|
33
33
|
struct Event_Backend_KQueue {
|
34
34
|
VALUE loop;
|
@@ -97,50 +97,112 @@ VALUE Event_Backend_KQueue_initialize(VALUE self, VALUE loop) {
|
|
97
97
|
return self;
|
98
98
|
}
|
99
99
|
|
100
|
-
static
|
101
|
-
|
102
|
-
|
100
|
+
static
|
101
|
+
int io_add_filters(int descriptor, int ident, int events, VALUE fiber) {
|
102
|
+
int count = 0;
|
103
|
+
struct kevent kevents[2] = {0};
|
104
|
+
|
105
|
+
if (events & READABLE) {
|
106
|
+
kevents[count].ident = ident;
|
107
|
+
kevents[count].filter = EVFILT_READ;
|
108
|
+
kevents[count].flags = EV_ADD | EV_ENABLE | EV_ONESHOT;
|
109
|
+
kevents[count].udata = (void*)fiber;
|
110
|
+
|
111
|
+
// #ifdef EV_OOBAND
|
112
|
+
// if (events & PRIORITY) {
|
113
|
+
// kevents[count].flags |= EV_OOBAND;
|
114
|
+
// }
|
115
|
+
// #endif
|
116
|
+
|
117
|
+
count++;
|
118
|
+
}
|
119
|
+
|
120
|
+
if (events & WRITABLE) {
|
121
|
+
kevents[count].ident = ident;
|
122
|
+
kevents[count].filter = EVFILT_WRITE;
|
123
|
+
kevents[count].flags = EV_ADD | EV_ENABLE | EV_ONESHOT;
|
124
|
+
kevents[count].udata = (void*)fiber;
|
125
|
+
count++;
|
126
|
+
}
|
127
|
+
|
128
|
+
int result = kevent(descriptor, kevents, count, NULL, 0, NULL);
|
103
129
|
|
104
|
-
if (
|
105
|
-
|
106
|
-
|
130
|
+
if (result == -1) {
|
131
|
+
rb_sys_fail("kevent(register)");
|
132
|
+
}
|
107
133
|
|
108
|
-
return
|
134
|
+
return events;
|
109
135
|
}
|
110
136
|
|
111
|
-
static
|
112
|
-
|
113
|
-
int
|
137
|
+
static
|
138
|
+
void io_remove_filters(int descriptor, int ident, int events) {
|
139
|
+
int count = 0;
|
140
|
+
struct kevent kevents[2] = {0};
|
114
141
|
|
115
|
-
if (
|
116
|
-
|
117
|
-
|
142
|
+
if (events & READABLE) {
|
143
|
+
kevents[count].ident = ident;
|
144
|
+
kevents[count].filter = EVFILT_READ;
|
145
|
+
kevents[count].flags = EV_DELETE;
|
146
|
+
|
147
|
+
count++;
|
148
|
+
}
|
149
|
+
|
150
|
+
if (events & WRITABLE) {
|
151
|
+
kevents[count].ident = ident;
|
152
|
+
kevents[count].filter = EVFILT_WRITE;
|
153
|
+
kevents[count].flags = EV_DELETE;
|
154
|
+
count++;
|
155
|
+
}
|
118
156
|
|
119
|
-
|
157
|
+
// Ignore the result.
|
158
|
+
kevent(descriptor, kevents, count, NULL, 0, NULL);
|
120
159
|
}
|
121
160
|
|
161
|
+
struct io_wait_arguments {
|
162
|
+
struct Event_Backend_KQueue *data;
|
163
|
+
int events;
|
164
|
+
int descriptor;
|
165
|
+
};
|
166
|
+
|
167
|
+
static
|
168
|
+
VALUE io_wait_rescue(VALUE _arguments, VALUE exception) {
|
169
|
+
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
170
|
+
|
171
|
+
io_remove_filters(arguments->data->descriptor, arguments->descriptor, arguments->events);
|
172
|
+
|
173
|
+
rb_exc_raise(exception);
|
174
|
+
};
|
175
|
+
|
176
|
+
static inline
|
177
|
+
int events_from_kqueue_filter(int filter) {
|
178
|
+
if (filter == EVFILT_READ) return READABLE;
|
179
|
+
if (filter == EVFILT_WRITE) return WRITABLE;
|
180
|
+
|
181
|
+
return 0;
|
182
|
+
}
|
183
|
+
|
184
|
+
static
|
185
|
+
VALUE io_wait_transfer(VALUE _arguments) {
|
186
|
+
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
187
|
+
|
188
|
+
VALUE result = rb_funcall(arguments->data->loop, id_transfer, 0);
|
189
|
+
|
190
|
+
return INT2NUM(events_from_kqueue_filter(NUM2INT(result)));
|
191
|
+
};
|
192
|
+
|
122
193
|
VALUE Event_Backend_KQueue_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
|
123
194
|
struct Event_Backend_KQueue *data = NULL;
|
124
195
|
TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
|
125
196
|
|
126
|
-
struct kevent event = {0};
|
127
|
-
|
128
197
|
int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
|
129
198
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
// A better approach is to batch all changes:
|
136
|
-
int result = kevent(data->descriptor, &event, 1, NULL, 0, NULL);
|
137
|
-
|
138
|
-
if (result == -1) {
|
139
|
-
rb_sys_fail("kevent");
|
140
|
-
}
|
199
|
+
struct io_wait_arguments io_wait_arguments = {
|
200
|
+
.events = io_add_filters(data->descriptor, descriptor, NUM2INT(events), fiber),
|
201
|
+
.data = data,
|
202
|
+
.descriptor = descriptor,
|
203
|
+
};
|
141
204
|
|
142
|
-
|
143
|
-
return INT2NUM(events_from_kqueue_filter(NUM2INT(result)));
|
205
|
+
return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
|
144
206
|
}
|
145
207
|
|
146
208
|
static
|
@@ -158,7 +220,7 @@ struct timespec * make_timeout(VALUE duration, struct timespec * storage) {
|
|
158
220
|
|
159
221
|
else if (RB_FLOAT_TYPE_P(duration)) {
|
160
222
|
double value = RFLOAT_VALUE(duration);
|
161
|
-
time_t seconds =
|
223
|
+
time_t seconds = value;
|
162
224
|
|
163
225
|
storage->tv_sec = seconds;
|
164
226
|
storage->tv_nsec = (value - seconds) * 1000000000L;
|
@@ -169,26 +231,89 @@ struct timespec * make_timeout(VALUE duration, struct timespec * storage) {
|
|
169
231
|
rb_raise(rb_eRuntimeError, "unable to convert timeout");
|
170
232
|
}
|
171
233
|
|
234
|
+
static
|
235
|
+
int timeout_nonblocking(struct timespec * timespec) {
|
236
|
+
return timespec && timespec->tv_sec == 0 && timespec->tv_nsec == 0;
|
237
|
+
}
|
238
|
+
|
239
|
+
struct select_arguments {
|
240
|
+
struct Event_Backend_KQueue *data;
|
241
|
+
|
242
|
+
int count;
|
243
|
+
struct kevent events[KQUEUE_MAX_EVENTS];
|
244
|
+
|
245
|
+
struct timespec storage;
|
246
|
+
struct timespec *timeout;
|
247
|
+
};
|
248
|
+
|
249
|
+
static
|
250
|
+
void * select_internal(void *_arguments) {
|
251
|
+
struct select_arguments * arguments = (struct select_arguments *)_arguments;
|
252
|
+
|
253
|
+
arguments->count = kevent(arguments->data->descriptor, NULL, 0, arguments->events, arguments->count, arguments->timeout);
|
254
|
+
|
255
|
+
return NULL;
|
256
|
+
}
|
257
|
+
|
258
|
+
static
|
259
|
+
void select_internal_without_gvl(struct select_arguments *arguments) {
|
260
|
+
rb_thread_call_without_gvl(select_internal, (void *)arguments, RUBY_UBF_IO, 0);
|
261
|
+
|
262
|
+
if (arguments->count == -1) {
|
263
|
+
rb_sys_fail("select_internal_without_gvl:kevent");
|
264
|
+
}
|
265
|
+
}
|
266
|
+
|
267
|
+
static
|
268
|
+
void select_internal_with_gvl(struct select_arguments *arguments) {
|
269
|
+
select_internal((void *)arguments);
|
270
|
+
|
271
|
+
if (arguments->count == -1) {
|
272
|
+
rb_sys_fail("select_internal_with_gvl:kevent");
|
273
|
+
}
|
274
|
+
}
|
275
|
+
|
172
276
|
VALUE Event_Backend_KQueue_select(VALUE self, VALUE duration) {
|
173
277
|
struct Event_Backend_KQueue *data = NULL;
|
174
278
|
TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
|
175
279
|
|
176
|
-
struct
|
177
|
-
|
280
|
+
struct select_arguments arguments = {
|
281
|
+
.data = data,
|
282
|
+
.count = KQUEUE_MAX_EVENTS,
|
283
|
+
.storage = {
|
284
|
+
.tv_sec = 0,
|
285
|
+
.tv_nsec = 0
|
286
|
+
}
|
287
|
+
};
|
178
288
|
|
179
|
-
|
289
|
+
// We break this implementation into two parts.
|
290
|
+
// (1) count = kevent(..., timeout = 0)
|
291
|
+
// (2) without gvl: kevent(..., timeout = 0) if count == 0 and timeout != 0
|
292
|
+
// This allows us to avoid releasing and reacquiring the GVL.
|
293
|
+
// Non-comprehensive testing shows this gives a 1.5x speedup.
|
294
|
+
arguments.timeout = &arguments.storage;
|
180
295
|
|
181
|
-
|
182
|
-
|
296
|
+
// First do the syscall with no timeout to get any immediately available events:
|
297
|
+
select_internal_with_gvl(&arguments);
|
298
|
+
|
299
|
+
// If there were no pending events, if we have a timeout, wait for more events:
|
300
|
+
if (arguments.count == 0) {
|
301
|
+
arguments.timeout = make_timeout(duration, &arguments.storage);
|
302
|
+
|
303
|
+
if (!timeout_nonblocking(arguments.timeout)) {
|
304
|
+
arguments.count = KQUEUE_MAX_EVENTS;
|
305
|
+
|
306
|
+
select_internal_without_gvl(&arguments);
|
307
|
+
}
|
183
308
|
}
|
184
309
|
|
185
|
-
for (int i = 0; i < count; i += 1) {
|
186
|
-
VALUE fiber = (VALUE)events[i].udata;
|
187
|
-
VALUE result = INT2NUM(events[i].filter);
|
310
|
+
for (int i = 0; i < arguments.count; i += 1) {
|
311
|
+
VALUE fiber = (VALUE)arguments.events[i].udata;
|
312
|
+
VALUE result = INT2NUM(arguments.events[i].filter);
|
188
313
|
rb_funcall(fiber, id_transfer, 1, result);
|
189
314
|
}
|
190
315
|
|
191
|
-
return INT2NUM(count);
|
316
|
+
return INT2NUM(arguments.count);
|
192
317
|
}
|
193
318
|
|
194
319
|
void Init_Event_Backend_KQueue(VALUE Event_Backend) {
|
data/ext/event/backend/uring.c
CHANGED
@@ -28,8 +28,8 @@
|
|
28
28
|
static VALUE Event_Backend_URing = Qnil;
|
29
29
|
static ID id_fileno, id_transfer;
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
enum {URING_ENTRIES = 64};
|
32
|
+
enum {URING_MAX_EVENTS = 64};
|
33
33
|
|
34
34
|
struct Event_Backend_URing {
|
35
35
|
VALUE loop;
|
@@ -122,28 +122,76 @@ int events_from_poll_flags(short flags) {
|
|
122
122
|
return events;
|
123
123
|
}
|
124
124
|
|
125
|
+
struct io_wait_arguments {
|
126
|
+
struct Event_Backend_URing *data;
|
127
|
+
VALUE fiber;
|
128
|
+
short flags;
|
129
|
+
};
|
130
|
+
|
131
|
+
static
|
132
|
+
VALUE io_wait_rescue(VALUE _arguments, VALUE exception) {
|
133
|
+
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
134
|
+
struct Event_Backend_URing *data = arguments->data;
|
135
|
+
|
136
|
+
struct io_uring_sqe *sqe = Event_Backend_URing_io_uring_get_sqe(data);
|
137
|
+
|
138
|
+
// fprintf(stderr, "poll_remove(%p, %p)\n", sqe, (void*)arguments->fiber);
|
139
|
+
|
140
|
+
io_uring_prep_poll_remove(sqe, (void*)arguments->fiber);
|
141
|
+
io_uring_submit(&data->ring);
|
142
|
+
|
143
|
+
rb_exc_raise(exception);
|
144
|
+
};
|
145
|
+
|
146
|
+
static
|
147
|
+
VALUE io_wait_transfer(VALUE _arguments) {
|
148
|
+
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
149
|
+
struct Event_Backend_URing *data = arguments->data;
|
150
|
+
|
151
|
+
VALUE result = rb_funcall(data->loop, id_transfer, 0);
|
152
|
+
|
153
|
+
// We explicitly filter the resulting events based on the requested events.
|
154
|
+
// In some cases, poll will report events we didn't ask for.
|
155
|
+
short flags = arguments->flags & NUM2INT(result);
|
156
|
+
|
157
|
+
return INT2NUM(events_from_poll_flags(flags));
|
158
|
+
};
|
159
|
+
|
160
|
+
struct io_uring_sqe *Event_Backend_URing_io_uring_get_sqe(struct Event_Backend_URing *data) {
|
161
|
+
struct io_uring_sqe *sqe = NULL;
|
162
|
+
|
163
|
+
while (true) {
|
164
|
+
sqe = io_uring_get_sqe(&data->ring);
|
165
|
+
if (sqe != NULL) {
|
166
|
+
return sqe;
|
167
|
+
}
|
168
|
+
// The sqe is full, we need to poll before submitting more events.
|
169
|
+
Event_Backend_URing_select(self, INT2NUM(0));
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
125
173
|
VALUE Event_Backend_URing_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
|
126
174
|
struct Event_Backend_URing *data = NULL;
|
127
175
|
TypedData_Get_Struct(self, struct Event_Backend_URing, &Event_Backend_URing_Type, data);
|
128
176
|
|
129
177
|
int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
|
130
|
-
struct io_uring_sqe *sqe =
|
178
|
+
struct io_uring_sqe *sqe = Event_Backend_URing_io_uring_get_sqe(data);
|
131
179
|
|
132
180
|
short flags = poll_flags_from_events(NUM2INT(events));
|
133
181
|
|
134
|
-
// fprintf(stderr, "poll_add(%p, %d, %d)\n", sqe, descriptor, flags);
|
182
|
+
// fprintf(stderr, "poll_add(%p, %d, %d, %p)\n", sqe, descriptor, flags, (void*)fiber);
|
135
183
|
|
136
184
|
io_uring_prep_poll_add(sqe, descriptor, flags);
|
137
185
|
io_uring_sqe_set_data(sqe, (void*)fiber);
|
138
186
|
io_uring_submit(&data->ring);
|
139
187
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
188
|
+
struct io_wait_arguments io_wait_arguments = {
|
189
|
+
.data = data,
|
190
|
+
.fiber = fiber,
|
191
|
+
.flags = flags
|
192
|
+
};
|
145
193
|
|
146
|
-
return
|
194
|
+
return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
|
147
195
|
}
|
148
196
|
|
149
197
|
inline static
|
@@ -176,7 +224,7 @@ VALUE Event_Backend_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffe
|
|
176
224
|
resize_to_capacity(buffer, NUM2SIZET(offset), NUM2SIZET(length));
|
177
225
|
|
178
226
|
int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
|
179
|
-
struct io_uring_sqe *sqe =
|
227
|
+
struct io_uring_sqe *sqe = Event_Backend_URing_io_uring_get_sqe(data);
|
180
228
|
|
181
229
|
struct iovec iovecs[1];
|
182
230
|
iovecs[0].iov_base = RSTRING_PTR(buffer) + NUM2SIZET(offset);
|
@@ -208,7 +256,7 @@ VALUE Event_Backend_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buff
|
|
208
256
|
}
|
209
257
|
|
210
258
|
int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
|
211
|
-
struct io_uring_sqe *sqe =
|
259
|
+
struct io_uring_sqe *sqe = Event_Backend_URing_io_uring_get_sqe(data);
|
212
260
|
|
213
261
|
struct iovec iovecs[1];
|
214
262
|
iovecs[0].iov_base = RSTRING_PTR(buffer) + NUM2SIZET(offset);
|
@@ -244,7 +292,7 @@ struct __kernel_timespec * make_timeout(VALUE duration, struct __kernel_timespec
|
|
244
292
|
|
245
293
|
else if (RB_FLOAT_TYPE_P(duration)) {
|
246
294
|
double value = RFLOAT_VALUE(duration);
|
247
|
-
time_t seconds =
|
295
|
+
time_t seconds = value;
|
248
296
|
|
249
297
|
storage->tv_sec = seconds;
|
250
298
|
storage->tv_nsec = (value - seconds) * 1000000000L;
|
@@ -255,36 +303,84 @@ struct __kernel_timespec * make_timeout(VALUE duration, struct __kernel_timespec
|
|
255
303
|
rb_raise(rb_eRuntimeError, "unable to convert timeout");
|
256
304
|
}
|
257
305
|
|
306
|
+
static
|
307
|
+
int timeout_nonblocking(struct __kernel_timespec *timespec) {
|
308
|
+
return timespec && timespec->tv_sec == 0 && timespec->tv_nsec == 0;
|
309
|
+
}
|
310
|
+
|
311
|
+
struct select_arguments {
|
312
|
+
struct Event_Backend_URing *data;
|
313
|
+
|
314
|
+
int count;
|
315
|
+
struct io_uring_cqe **cqes;
|
316
|
+
|
317
|
+
struct __kernel_timespec storage;
|
318
|
+
struct __kernel_timespec *timeout;
|
319
|
+
};
|
320
|
+
|
321
|
+
static
|
322
|
+
void * select_internal(void *_arguments) {
|
323
|
+
struct select_arguments * arguments = (struct select_arguments *)_arguments;
|
324
|
+
|
325
|
+
arguments->count = io_uring_wait_cqes(&arguments->data->ring, arguments->cqes, 1, arguments->timeout, NULL);
|
326
|
+
|
327
|
+
// If waiting resulted in a timeout, there are 0 events.
|
328
|
+
if (arguments->count == -ETIME) {
|
329
|
+
arguments->count = 0;
|
330
|
+
}
|
331
|
+
|
332
|
+
return NULL;
|
333
|
+
}
|
334
|
+
|
335
|
+
static
|
336
|
+
int select_internal_without_gvl(struct select_arguments *arguments) {
|
337
|
+
rb_thread_call_without_gvl(select_internal, (void *)arguments, RUBY_UBF_IO, 0);
|
338
|
+
|
339
|
+
if (arguments->count < 0) {
|
340
|
+
rb_syserr_fail(-arguments->count, "select_internal_without_gvl:io_uring_wait_cqes");
|
341
|
+
}
|
342
|
+
|
343
|
+
return arguments->count;
|
344
|
+
}
|
345
|
+
|
258
346
|
VALUE Event_Backend_URing_select(VALUE self, VALUE duration) {
|
259
347
|
struct Event_Backend_URing *data = NULL;
|
260
348
|
TypedData_Get_Struct(self, struct Event_Backend_URing, &Event_Backend_URing_Type, data);
|
261
349
|
|
262
350
|
struct io_uring_cqe *cqes[URING_MAX_EVENTS];
|
263
|
-
struct __kernel_timespec storage;
|
264
351
|
|
352
|
+
// This is a non-blocking operation:
|
265
353
|
int result = io_uring_peek_batch_cqe(&data->ring, cqes, URING_MAX_EVENTS);
|
266
354
|
|
267
|
-
// fprintf(stderr, "result = %d\n", result);
|
268
|
-
|
269
355
|
if (result < 0) {
|
270
356
|
rb_syserr_fail(-result, strerror(-result));
|
271
|
-
} else if (result == 0
|
272
|
-
|
357
|
+
} else if (result == 0) {
|
358
|
+
// We might need to wait for events:
|
359
|
+
struct select_arguments arguments = {
|
360
|
+
.data = data,
|
361
|
+
.cqes = cqes,
|
362
|
+
.timeout = NULL,
|
363
|
+
};
|
273
364
|
|
274
|
-
|
365
|
+
arguments.timeout = make_timeout(duration, &arguments.storage);
|
275
366
|
|
276
|
-
if (
|
277
|
-
result =
|
278
|
-
} else if (result < 0) {
|
279
|
-
rb_syserr_fail(-result, strerror(-result));
|
367
|
+
if (!timeout_nonblocking(arguments.timeout)) {
|
368
|
+
result = select_internal_without_gvl(&arguments);
|
280
369
|
}
|
281
370
|
}
|
282
371
|
|
372
|
+
// fprintf(stderr, "cqes count=%d\n", result);
|
373
|
+
|
283
374
|
for (int i = 0; i < result; i += 1) {
|
375
|
+
// If the operation was cancelled, or the operation has no user data (fiber):
|
376
|
+
if (cqes[i]->res == -ECANCELED || cqes[i]->user_data == 0) {
|
377
|
+
continue;
|
378
|
+
}
|
379
|
+
|
284
380
|
VALUE fiber = (VALUE)io_uring_cqe_get_data(cqes[i]);
|
285
381
|
VALUE result = INT2NUM(cqes[i]->res);
|
286
382
|
|
287
|
-
// fprintf(stderr, "cqes[i]
|
383
|
+
// fprintf(stderr, "cqes[i] res=%d user_data=%p\n", cqes[i]->res, (void*)cqes[i]->user_data);
|
288
384
|
|
289
385
|
io_uring_cqe_seen(&data->ring, cqes[i]);
|
290
386
|
|
data/ext/event/backend/uring.h
CHANGED
Binary file
|
data/ext/event/event.o
ADDED
Binary file
|
data/ext/event/extconf.h
ADDED
data/ext/event/extconf.rb
CHANGED
data/ext/event/kqueue.o
ADDED
Binary file
|
data/ext/event/mkmf.log
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
have_library: checking for -luring... -------------------- no
|
2
|
+
|
3
|
+
"clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -L. -L/Users/samuel/.rubies/ruby-3.0.0/lib -L/opt/local/lib -L. -fstack-protector-strong -L/opt/local/lib -lruby.3.0-static -framework Security -framework Foundation -lpthread -lgmp -ldl -lobjc "
|
4
|
+
checked program was:
|
5
|
+
/* begin */
|
6
|
+
1: #include "ruby.h"
|
7
|
+
2:
|
8
|
+
3: int main(int argc, char **argv)
|
9
|
+
4: {
|
10
|
+
5: return !!argv[argc];
|
11
|
+
6: }
|
12
|
+
/* end */
|
13
|
+
|
14
|
+
"clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -L. -L/Users/samuel/.rubies/ruby-3.0.0/lib -L/opt/local/lib -L. -fstack-protector-strong -L/opt/local/lib -lruby.3.0-static -framework Security -framework Foundation -lpthread -lgmp -ldl -lobjc -luring "
|
15
|
+
ld: library not found for -luring
|
16
|
+
clang: error: linker command failed with exit code 1 (use -v to see invocation)
|
17
|
+
checked program was:
|
18
|
+
/* begin */
|
19
|
+
1: #include "ruby.h"
|
20
|
+
2:
|
21
|
+
3: /*top*/
|
22
|
+
4: extern int t(void);
|
23
|
+
5: int main(int argc, char **argv)
|
24
|
+
6: {
|
25
|
+
7: if (argc > 1000000) {
|
26
|
+
8: int (* volatile tp)(void)=(int (*)(void))&t;
|
27
|
+
9: printf("%d", (*tp)());
|
28
|
+
10: }
|
29
|
+
11:
|
30
|
+
12: return !!argv[argc];
|
31
|
+
13: }
|
32
|
+
14:
|
33
|
+
15: int t(void) { ; return 0; }
|
34
|
+
/* end */
|
35
|
+
|
36
|
+
--------------------
|
37
|
+
|
38
|
+
have_header: checking for sys/epoll.h... -------------------- no
|
39
|
+
|
40
|
+
"clang -E -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -o conftest.i"
|
41
|
+
conftest.c:3:10: fatal error: 'sys/epoll.h' file not found
|
42
|
+
#include <sys/epoll.h>
|
43
|
+
^~~~~~~~~~~~~
|
44
|
+
1 error generated.
|
45
|
+
checked program was:
|
46
|
+
/* begin */
|
47
|
+
1: #include "ruby.h"
|
48
|
+
2:
|
49
|
+
3: #include <sys/epoll.h>
|
50
|
+
/* end */
|
51
|
+
|
52
|
+
--------------------
|
53
|
+
|
54
|
+
have_header: checking for sys/event.h... -------------------- yes
|
55
|
+
|
56
|
+
"clang -E -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.0/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -o conftest.i"
|
57
|
+
checked program was:
|
58
|
+
/* begin */
|
59
|
+
1: #include "ruby.h"
|
60
|
+
2:
|
61
|
+
3: #include <sys/event.h>
|
62
|
+
/* end */
|
63
|
+
|
64
|
+
--------------------
|
65
|
+
|
66
|
+
extconf.h is:
|
67
|
+
/* begin */
|
68
|
+
1: #ifndef EXTCONF_H
|
69
|
+
2: #define EXTCONF_H
|
70
|
+
3: #define HAVE_SYS_EVENT_H 1
|
71
|
+
4: #endif
|
72
|
+
/* end */
|
73
|
+
|
data/lib/event/backend/select.rb
CHANGED
@@ -29,15 +29,23 @@ module Event
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def io_wait(fiber, io, events)
|
32
|
+
remove_readable = remove_writable = false
|
33
|
+
|
32
34
|
if (events & READABLE) > 0 or (events & PRIORITY) > 0
|
33
35
|
@readable[io] = fiber
|
36
|
+
remove_readable = true
|
34
37
|
end
|
35
38
|
|
36
39
|
if (events & WRITABLE) > 0
|
37
40
|
@writable[io] = fiber
|
41
|
+
remove_writable = true
|
38
42
|
end
|
39
43
|
|
40
44
|
@loop.transfer
|
45
|
+
|
46
|
+
ensure
|
47
|
+
@readable.delete(io) if remove_readable
|
48
|
+
@writable.delete(io) if remove_writable
|
41
49
|
end
|
42
50
|
|
43
51
|
def select(duration = nil)
|
data/lib/event/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bake
|
@@ -81,9 +81,14 @@ files:
|
|
81
81
|
- ext/event/backend/kqueue.h
|
82
82
|
- ext/event/backend/uring.c
|
83
83
|
- ext/event/backend/uring.h
|
84
|
+
- ext/event/event.bundle
|
84
85
|
- ext/event/event.c
|
85
86
|
- ext/event/event.h
|
87
|
+
- ext/event/event.o
|
88
|
+
- ext/event/extconf.h
|
86
89
|
- ext/event/extconf.rb
|
90
|
+
- ext/event/kqueue.o
|
91
|
+
- ext/event/mkmf.log
|
87
92
|
- lib/event.rb
|
88
93
|
- lib/event/backend/select.rb
|
89
94
|
- lib/event/debug/selector.rb
|
@@ -108,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
113
|
- !ruby/object:Gem::Version
|
109
114
|
version: '0'
|
110
115
|
requirements: []
|
111
|
-
rubygems_version: 3.2.
|
116
|
+
rubygems_version: 3.2.15
|
112
117
|
signing_key:
|
113
118
|
specification_version: 4
|
114
119
|
summary: An event loop.
|