event 0.1.2 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 287fe2e9885bd34fd2595c49589c2cfe751799e34f738a18e93f9ccdf13f3ffd
4
- data.tar.gz: 88cec8cd2badba810501a9a3aef7309dcb76d87ef0c6029bca147ba2d3eea09e
3
+ metadata.gz: 29775c0ba7779c7773bf794270f5259429ee7e6d6611e6dcd3b4007a59dabc55
4
+ data.tar.gz: 4df129eb3e0c99ad4d23131df66a794c0756a8a34032ef4864a492579faf61d3
5
5
  SHA512:
6
- metadata.gz: 956801d0c052c06efe6cf126e76472a02f2271d8476a0501f262ab1d71b0e97992fc5bf2ffce33b753f510179ec42f8f5529152d9bd48ed6029b4009ba754d3c
7
- data.tar.gz: 3f35bf37920170794733e5b3671aa9e0e1a3a64620dde2209310d5c8143866ce92289c5efe6b9f2010f271b2452b3efdb9bbb3d2c3c72d80cefd847154746355
6
+ metadata.gz: 6540f3372b5cded8e108c4dd314efb95f0e5fc6b794be77e84819e054c13a63c479d985ce35f6e5fbff35e1196b4f5606f7a4e46c93d856c91c32b5e5e7dbac2
7
+ data.tar.gz: 687b15f76c4715b3f34b7467732887d75a3a15b3bfa7b29cdc9cd1385600e9fb4c797ca0ad6b3f8c1d5401e7bc87d1850a861e8e3cb9a333021d96fe4a348f18
@@ -0,0 +1,266 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ # V=0 quiet, V=1 verbose. other values don't work.
5
+ V = 0
6
+ Q1 = $(V:1=)
7
+ Q = $(Q1:0=@)
8
+ ECHO1 = $(V:1=@ :)
9
+ ECHO = $(ECHO1:0=@ echo)
10
+ NULLCMD = :
11
+
12
+ #### Start of system configuration section. ####
13
+
14
+ srcdir = .
15
+ topdir = /home/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0
16
+ hdrdir = $(topdir)
17
+ arch_hdrdir = /home/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-linux
18
+ PATH_SEPARATOR = :
19
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby:$(srcdir)/backend
20
+ prefix = $(DESTDIR)/home/samuel/.rubies/ruby-3.0.1
21
+ rubysitearchprefix = $(rubylibprefix)/$(sitearch)
22
+ rubyarchprefix = $(rubylibprefix)/$(arch)
23
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
24
+ exec_prefix = $(prefix)
25
+ vendorarchhdrdir = $(vendorhdrdir)/$(sitearch)
26
+ sitearchhdrdir = $(sitehdrdir)/$(sitearch)
27
+ rubyarchhdrdir = $(rubyhdrdir)/$(arch)
28
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
29
+ sitehdrdir = $(rubyhdrdir)/site_ruby
30
+ rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME)
31
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
32
+ vendorlibdir = $(vendordir)/$(ruby_version)
33
+ vendordir = $(rubylibprefix)/vendor_ruby
34
+ sitearchdir = $(sitelibdir)/$(sitearch)
35
+ sitelibdir = $(sitedir)/$(ruby_version)
36
+ sitedir = $(rubylibprefix)/site_ruby
37
+ rubyarchdir = $(rubylibdir)/$(arch)
38
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
39
+ sitearchincludedir = $(includedir)/$(sitearch)
40
+ archincludedir = $(includedir)/$(arch)
41
+ sitearchlibdir = $(libdir)/$(sitearch)
42
+ archlibdir = $(libdir)/$(arch)
43
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
44
+ mandir = $(datarootdir)/man
45
+ localedir = $(datarootdir)/locale
46
+ libdir = $(exec_prefix)/lib
47
+ psdir = $(docdir)
48
+ pdfdir = $(docdir)
49
+ dvidir = $(docdir)
50
+ htmldir = $(docdir)
51
+ infodir = $(datarootdir)/info
52
+ docdir = $(datarootdir)/doc/$(PACKAGE)
53
+ oldincludedir = $(DESTDIR)/usr/include
54
+ includedir = $(prefix)/include
55
+ runstatedir = $(localstatedir)/run
56
+ localstatedir = $(prefix)/var
57
+ sharedstatedir = $(prefix)/com
58
+ sysconfdir = $(prefix)/etc
59
+ datadir = $(datarootdir)
60
+ datarootdir = $(prefix)/share
61
+ libexecdir = $(exec_prefix)/libexec
62
+ sbindir = $(exec_prefix)/sbin
63
+ bindir = $(exec_prefix)/bin
64
+ archdir = $(rubyarchdir)
65
+
66
+
67
+ CC_WRAPPER =
68
+ CC = gcc
69
+ CXX = g++
70
+ LIBRUBY = $(LIBRUBY_A)
71
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
72
+ LIBRUBYARG_SHARED = -Wl,-rpath,$(libdir) -L$(libdir)
73
+ LIBRUBYARG_STATIC = -Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static $(MAINLIBS)
74
+ empty =
75
+ OUTFLAG = -o $(empty)
76
+ COUTFLAG = -o $(empty)
77
+ CSRCFLAG = $(empty)
78
+
79
+ RUBY_EXTCONF_H = extconf.h
80
+ cflags = $(optflags) $(debugflags) $(warnflags)
81
+ cxxflags =
82
+ optflags = -O3
83
+ debugflags = -ggdb3
84
+ warnflags = -Wall -Wextra -Wdeprecated-declarations -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wwrite-strings -Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable
85
+ cppflags =
86
+ CCDLFLAGS = -fPIC
87
+ CFLAGS = $(CCDLFLAGS) $(cflags) -Wall $(ARCH_FLAG)
88
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
89
+ DEFS =
90
+ CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\" $(DEFS) $(cppflags)
91
+ CXXFLAGS = $(CCDLFLAGS) $(ARCH_FLAG)
92
+ ldflags = -L. -fstack-protector-strong -rdynamic -Wl,-export-dynamic
93
+ dldflags = -Wl,--compress-debug-sections=zlib
94
+ ARCH_FLAG =
95
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
96
+ LDSHARED = $(CC) -shared
97
+ LDSHAREDXX = $(CXX) -shared
98
+ AR = gcc-ar
99
+ EXEEXT =
100
+
101
+ RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)
102
+ RUBY_SO_NAME = ruby
103
+ RUBYW_INSTALL_NAME =
104
+ RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
105
+ RUBYW_BASE_NAME = rubyw
106
+ RUBY_BASE_NAME = ruby
107
+
108
+ arch = x86_64-linux
109
+ sitearch = $(arch)
110
+ ruby_version = 3.0.0
111
+ ruby = $(bindir)/$(RUBY_BASE_NAME)
112
+ RUBY = $(ruby)
113
+ ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h $(RUBY_EXTCONF_H)
114
+
115
+ RM = rm -f
116
+ RM_RF = $(RUBY) -run -e rm -- -rf
117
+ RMDIRS = rmdir --ignore-fail-on-non-empty -p
118
+ MAKEDIRS = /usr/bin/mkdir -p
119
+ INSTALL = /usr/bin/install -c
120
+ INSTALL_PROG = $(INSTALL) -m 0755
121
+ INSTALL_DATA = $(INSTALL) -m 644
122
+ COPY = cp
123
+ TOUCH = exit >
124
+
125
+ #### End of system configuration section. ####
126
+
127
+ preload =
128
+ libpath = . $(libdir)
129
+ LIBPATH = -L. -L$(libdir) -Wl,-rpath,$(libdir)
130
+ DEFFILE =
131
+
132
+ CLEANFILES = mkmf.log
133
+ DISTCLEANFILES =
134
+ DISTCLEANDIRS =
135
+
136
+ extout =
137
+ extout_prefix =
138
+ target_prefix = /event
139
+ LOCAL_LIBS =
140
+ LIBS = -luring -lm -lc
141
+ ORIG_SRCS = event.c
142
+ SRCS = $(ORIG_SRCS) event.c uring.c epoll.c
143
+ OBJS = event.o uring.o epoll.o
144
+ HDRS = $(srcdir)/event.h $(srcdir)/extconf.h
145
+ LOCAL_HDRS =
146
+ TARGET = event
147
+ TARGET_NAME = event
148
+ TARGET_ENTRY = Init_$(TARGET_NAME)
149
+ DLLIB = $(TARGET).so
150
+ EXTSTATIC =
151
+ STATIC_LIB =
152
+
153
+ TIMESTAMP_DIR = .
154
+ BINDIR = $(bindir)
155
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
156
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
157
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
158
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
159
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
160
+ TARGET_SO_DIR =
161
+ TARGET_SO = $(TARGET_SO_DIR)$(DLLIB)
162
+ CLEANLIBS = $(TARGET_SO)
163
+ CLEANOBJS = *.o *.bak
164
+
165
+ all: $(DLLIB)
166
+ static: $(STATIC_LIB)
167
+ .PHONY: all install static install-so install-rb
168
+ .PHONY: clean clean-so clean-static clean-rb
169
+
170
+ clean-static::
171
+ clean-rb-default::
172
+ clean-rb::
173
+ clean-so::
174
+ clean: clean-so clean-static clean-rb-default clean-rb
175
+ -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
176
+
177
+ distclean-rb-default::
178
+ distclean-rb::
179
+ distclean-so::
180
+ distclean-static::
181
+ distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
182
+ -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
183
+ -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
184
+ -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
185
+
186
+ realclean: distclean
187
+ install: install-so install-rb
188
+
189
+ install-so: $(DLLIB) $(TIMESTAMP_DIR)/.sitearchdir.-.event.time
190
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
191
+ clean-static::
192
+ -$(Q)$(RM) $(STATIC_LIB)
193
+ install-rb: pre-install-rb do-install-rb install-rb-default
194
+ install-rb-default: pre-install-rb-default do-install-rb-default
195
+ pre-install-rb: Makefile
196
+ pre-install-rb-default: Makefile
197
+ do-install-rb:
198
+ do-install-rb-default:
199
+ pre-install-rb-default:
200
+ @$(NULLCMD)
201
+ $(TIMESTAMP_DIR)/.sitearchdir.-.event.time:
202
+ $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR)
203
+ $(Q) $(TOUCH) $@
204
+
205
+ site-install: site-install-so site-install-rb
206
+ site-install-so: install-so
207
+ site-install-rb: install-rb
208
+
209
+ .SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S
210
+
211
+ .cc.o:
212
+ $(ECHO) compiling $(<)
213
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
214
+
215
+ .cc.S:
216
+ $(ECHO) translating $(<)
217
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
218
+
219
+ .mm.o:
220
+ $(ECHO) compiling $(<)
221
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
222
+
223
+ .mm.S:
224
+ $(ECHO) translating $(<)
225
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
226
+
227
+ .cxx.o:
228
+ $(ECHO) compiling $(<)
229
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
230
+
231
+ .cxx.S:
232
+ $(ECHO) translating $(<)
233
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
234
+
235
+ .cpp.o:
236
+ $(ECHO) compiling $(<)
237
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
238
+
239
+ .cpp.S:
240
+ $(ECHO) translating $(<)
241
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
242
+
243
+ .c.o:
244
+ $(ECHO) compiling $(<)
245
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
246
+
247
+ .c.S:
248
+ $(ECHO) translating $(<)
249
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
250
+
251
+ .m.o:
252
+ $(ECHO) compiling $(<)
253
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
254
+
255
+ .m.S:
256
+ $(ECHO) translating $(<)
257
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
258
+
259
+ $(TARGET_SO): $(OBJS) Makefile
260
+ $(ECHO) linking shared-object event/$(DLLIB)
261
+ -$(Q)$(RM) $(@)
262
+ $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
263
+
264
+
265
+
266
+ $(OBJS): $(HDRS) $(ruby_headers)
@@ -0,0 +1,29 @@
1
+ // Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
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
+ enum Event {
22
+ READABLE = 1,
23
+ PRIORITY = 2,
24
+ WRITABLE = 4,
25
+ ERROR = 8,
26
+ HANGUP = 16
27
+ };
28
+
29
+ #include <ruby/thread.h>
@@ -19,6 +19,7 @@
19
19
  // THE SOFTWARE.
20
20
 
21
21
  #include "kqueue.h"
22
+ #include "backend.h"
22
23
 
23
24
  #include <sys/epoll.h>
24
25
  #include <time.h>
@@ -27,9 +28,7 @@
27
28
  static VALUE Event_Backend_EPoll = Qnil;
28
29
  static ID id_fileno, id_transfer;
29
30
 
30
- static const int READABLE = 1, PRIORITY = 2, WRITABLE = 4;
31
-
32
- static const unsigned EPOLL_MAX_EVENTS = 1024;
31
+ enum {EPOLL_MAX_EVENTS = 64};
33
32
 
34
33
  struct Event_Backend_EPoll {
35
34
  VALUE loop;
@@ -42,13 +41,19 @@ void Event_Backend_EPoll_Type_mark(void *_data)
42
41
  rb_gc_mark(data->loop);
43
42
  }
44
43
 
44
+ static
45
+ void close_internal(struct Event_Backend_EPoll *data) {
46
+ if (data->descriptor >= 0) {
47
+ close(data->descriptor);
48
+ data->descriptor = -1;
49
+ }
50
+ }
51
+
45
52
  void Event_Backend_EPoll_Type_free(void *_data)
46
53
  {
47
54
  struct Event_Backend_EPoll *data = _data;
48
55
 
49
- if (data->descriptor >= 0) {
50
- close(data->descriptor);
51
- }
56
+ close_internal(data);
52
57
 
53
58
  free(data);
54
59
  }
@@ -97,36 +102,86 @@ VALUE Event_Backend_EPoll_initialize(VALUE self, VALUE loop) {
97
102
  return self;
98
103
  }
99
104
 
100
- VALUE Event_Backend_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
105
+ VALUE Event_Backend_EPoll_close(VALUE self) {
101
106
  struct Event_Backend_EPoll *data = NULL;
102
107
  TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
103
108
 
104
- struct epoll_event event = {0};
109
+ close_internal(data);
105
110
 
106
- int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
107
- int duplicate = -1;
111
+ return Qnil;
112
+ }
113
+
114
+ static inline
115
+ uint32_t epoll_flags_from_events(int events) {
116
+ uint32_t flags = 0;
108
117
 
109
- int mask = NUM2INT(events);
118
+ if (events & READABLE) flags |= EPOLLIN;
119
+ if (events & PRIORITY) flags |= EPOLLPRI;
120
+ if (events & WRITABLE) flags |= EPOLLOUT;
110
121
 
111
- if (mask & READABLE) {
112
- event.events |= EPOLLIN;
113
- }
122
+ flags |= EPOLLRDHUP;
123
+ flags |= EPOLLONESHOT;
114
124
 
115
- if (mask & PRIORITY) {
116
- event.events |= EPOLLPRI;
117
- }
125
+ return flags;
126
+ }
127
+
128
+ static inline
129
+ int events_from_epoll_flags(uint32_t flags) {
130
+ int events = 0;
131
+
132
+ if (flags & EPOLLIN) events |= READABLE;
133
+ if (flags & EPOLLPRI) events |= PRIORITY;
134
+ if (flags & EPOLLOUT) events |= WRITABLE;
135
+
136
+ return events;
137
+ }
138
+
139
+ struct io_wait_arguments {
140
+ struct Event_Backend_EPoll *data;
141
+ int descriptor;
142
+ int duplicate;
143
+ };
144
+
145
+ static
146
+ VALUE io_wait_ensure(VALUE _arguments) {
147
+ struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
118
148
 
119
- if (mask & WRITABLE) {
120
- event.events |= EPOLLOUT;
149
+ if (arguments->duplicate >= 0) {
150
+ epoll_ctl(arguments->data->descriptor, EPOLL_CTL_DEL, arguments->duplicate, NULL);
151
+
152
+ close(arguments->duplicate);
153
+ } else {
154
+ epoll_ctl(arguments->data->descriptor, EPOLL_CTL_DEL, arguments->descriptor, NULL);
121
155
  }
122
156
 
123
- event.events |= EPOLLRDHUP;
124
- event.events |= EPOLLONESHOT;
157
+ return Qnil;
158
+ };
159
+
160
+ static
161
+ VALUE io_wait_transfer(VALUE _arguments) {
162
+ struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
163
+
164
+ VALUE result = rb_funcall(arguments->data->loop, id_transfer, 0);
125
165
 
166
+ return INT2NUM(events_from_epoll_flags(NUM2INT(result)));
167
+ };
168
+
169
+ VALUE Event_Backend_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
170
+ struct Event_Backend_EPoll *data = NULL;
171
+ TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
172
+
173
+ struct epoll_event event = {0};
174
+
175
+ int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
176
+ int duplicate = -1;
177
+
178
+ event.events = epoll_flags_from_events(NUM2INT(events));
126
179
  event.data.ptr = (void*)fiber;
127
180
 
181
+ // fprintf(stderr, "<- fiber=%p descriptor=%d\n", (void*)fiber, descriptor);
182
+
128
183
  // A better approach is to batch all changes:
129
- int result = epoll_ctl(data->descriptor, EPOLL_CTL_ADD, descriptor, &event);;
184
+ int result = epoll_ctl(data->descriptor, EPOLL_CTL_ADD, descriptor, &event);
130
185
 
131
186
  if (result == -1 && errno == EEXIST) {
132
187
  // The file descriptor was already inserted into epoll.
@@ -137,20 +192,20 @@ VALUE Event_Backend_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE event
137
192
  if (descriptor == -1)
138
193
  rb_sys_fail("dup");
139
194
 
140
- result = epoll_ctl(data->descriptor, EPOLL_CTL_ADD, descriptor, &event);;
195
+ result = epoll_ctl(data->descriptor, EPOLL_CTL_ADD, descriptor, &event);
141
196
  }
142
197
 
143
198
  if (result == -1) {
144
199
  rb_sys_fail("epoll_ctl");
145
200
  }
146
201
 
147
- rb_funcall(data->loop, id_transfer, 0);
202
+ struct io_wait_arguments io_wait_arguments = {
203
+ .data = data,
204
+ .descriptor = descriptor,
205
+ .duplicate = duplicate
206
+ };
148
207
 
149
- if (duplicate >= 0) {
150
- close(duplicate);
151
- }
152
-
153
- return Qnil;
208
+ return rb_ensure(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_ensure, (VALUE)&io_wait_arguments);
154
209
  }
155
210
 
156
211
  static
@@ -172,24 +227,71 @@ int make_timeout(VALUE duration) {
172
227
  rb_raise(rb_eRuntimeError, "unable to convert timeout");
173
228
  }
174
229
 
230
+ struct select_arguments {
231
+ struct Event_Backend_EPoll *data;
232
+
233
+ int count;
234
+ struct epoll_event events[EPOLL_MAX_EVENTS];
235
+
236
+ int timeout;
237
+ };
238
+
239
+ static
240
+ void * select_internal(void *_arguments) {
241
+ struct select_arguments * arguments = (struct select_arguments *)_arguments;
242
+
243
+ arguments->count = epoll_wait(arguments->data->descriptor, arguments->events, EPOLL_MAX_EVENTS, arguments->timeout);
244
+
245
+ return NULL;
246
+ }
247
+
248
+ static
249
+ void select_internal_without_gvl(struct select_arguments *arguments) {
250
+ rb_thread_call_without_gvl(select_internal, (void *)arguments, RUBY_UBF_IO, 0);
251
+
252
+ if (arguments->count == -1) {
253
+ rb_sys_fail("select_internal_without_gvl:epoll_wait");
254
+ }
255
+ }
256
+
257
+ static
258
+ void select_internal_with_gvl(struct select_arguments *arguments) {
259
+ select_internal((void *)arguments);
260
+
261
+ if (arguments->count == -1) {
262
+ rb_sys_fail("select_internal_with_gvl:epoll_wait");
263
+ }
264
+ }
265
+
175
266
  VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
176
267
  struct Event_Backend_EPoll *data = NULL;
177
268
  TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
178
269
 
179
- struct epoll_event events[EPOLL_MAX_EVENTS];
270
+ struct select_arguments arguments = {
271
+ .data = data,
272
+ .timeout = 0
273
+ };
180
274
 
181
- int count = epoll_wait(data->descriptor, events, EPOLL_MAX_EVENTS, make_timeout(duration));
275
+ select_internal_without_gvl(&arguments);
182
276
 
183
- if (count == -1) {
184
- rb_sys_fail("epoll_wait");
277
+ if (arguments.count == 0) {
278
+ arguments.timeout = make_timeout(duration);
279
+
280
+ if (arguments.timeout != 0) {
281
+ select_internal_with_gvl(&arguments);
282
+ }
185
283
  }
186
284
 
187
- for (int i = 0; i < count; i += 1) {
188
- VALUE fiber = (VALUE)events[i].data.ptr;
189
- rb_funcall(fiber, id_transfer, 0);
285
+ for (int i = 0; i < arguments.count; i += 1) {
286
+ VALUE fiber = (VALUE)arguments.events[i].data.ptr;
287
+ VALUE result = INT2NUM(arguments.events[i].events);
288
+
289
+ // fprintf(stderr, "-> fiber=%p descriptor=%d\n", (void*)fiber, events[i].data.fd);
290
+
291
+ rb_funcall(fiber, id_transfer, 1, result);
190
292
  }
191
293
 
192
- return INT2NUM(count);
294
+ return INT2NUM(arguments.count);
193
295
  }
194
296
 
195
297
  void Init_Event_Backend_EPoll(VALUE Event_Backend) {
@@ -200,6 +302,7 @@ void Init_Event_Backend_EPoll(VALUE Event_Backend) {
200
302
 
201
303
  rb_define_alloc_func(Event_Backend_EPoll, Event_Backend_EPoll_allocate);
202
304
  rb_define_method(Event_Backend_EPoll, "initialize", Event_Backend_EPoll_initialize, 1);
305
+ rb_define_method(Event_Backend_EPoll, "close", Event_Backend_EPoll_close, 0);
203
306
 
204
307
  rb_define_method(Event_Backend_EPoll, "io_wait", Event_Backend_EPoll_io_wait, 3);
205
308
  rb_define_method(Event_Backend_EPoll, "select", Event_Backend_EPoll_select, 1);