event 0.4.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94dad12ffcb84e598eae15a76f783046e324ca041f71b55b1d8925ad742fe51d
4
- data.tar.gz: 8776e1608c0b321557ea48857157f1496d0ab0babbff3fc186f9308e0a73c8eb
3
+ metadata.gz: '0380b6d95d8bd8f8d378820eefa77e6c6f0f1aaceb2afec54cb4d38f57747cbc'
4
+ data.tar.gz: 2a0bfede977154f30a402fda4ec445eedc4daf3893bae8760eceaa1e58c999be
5
5
  SHA512:
6
- metadata.gz: e2714eea3be4dd9119b41a3aa98f9575c9bf0e9a3268a1c4af185bd92b5d56d78db152849cff9453f9337374d2ee6ba2ce2981b468252f9f09db15881c39963a
7
- data.tar.gz: 2cc11adfcee9ae1188305691010049775abcdec1ec58b1666cfe5ccfd4276692597bb524e41f106478c0ceb80539e52c6fc3db84d9488f9b70d2c4556f4aece2
6
+ metadata.gz: d12fab2ce89b8c22d583a7472670f8bdb5b5b3428832938f9c51ce3635f08bfaf7d107b6568f762849a4fa8b32fdb0d79823bbd4ebd795b690e885b0eff52798
7
+ data.tar.gz: 793cf18caeb1457cd5499ee3d0fd2108dbf46e953cbc11b80e7c800efeb6beac279395a24da420b4c751a89ee5ecd54ad53a3b3a58d4b07d75e9a89d84a8be4d
data/ext/event/Makefile CHANGED
@@ -12,12 +12,12 @@ NULLCMD = :
12
12
  #### Start of system configuration section. ####
13
13
 
14
14
  srcdir = .
15
- topdir = /home/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0
15
+ topdir = /Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0
16
16
  hdrdir = $(topdir)
17
- arch_hdrdir = /home/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-linux
17
+ arch_hdrdir = /Users/samuel/.rubies/ruby-3.0.1/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)/home/samuel/.rubies/ruby-3.0.1
20
+ prefix = $(DESTDIR)/Users/samuel/.rubies/ruby-3.0.1
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 = $(DESTDIR)/usr/include
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 = gcc
69
- CXX = g++
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 = -Wl,-rpath,$(libdir) -L$(libdir)
73
- LIBRUBYARG_STATIC = -Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static $(MAINLIBS)
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 -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
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 = -fPIC
87
- CFLAGS = $(CCDLFLAGS) $(cflags) -Wall $(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 -rdynamic -Wl,-export-dynamic
93
- dldflags = -Wl,--compress-debug-sections=zlib
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) -shared
97
- LDSHAREDXX = $(CXX) -shared
98
- AR = gcc-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-linux
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 --ignore-fail-on-non-empty -p
118
- MAKEDIRS = /usr/bin/mkdir -p
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) -Wl,-rpath,$(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 = -luring -lm -lc
140
+ LIBS =
141
141
  ORIG_SRCS = event.c
142
- SRCS = $(ORIG_SRCS) event.c uring.c epoll.c
143
- OBJS = event.o uring.o epoll.o
142
+ SRCS = $(ORIG_SRCS) event.c backend.c kqueue.c
143
+ OBJS = event.o backend.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).so
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
 
Binary file
@@ -0,0 +1,108 @@
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
+ #include "backend.h"
22
+ #include <fcntl.h>
23
+
24
+ static ID id_transfer, id_wait;
25
+ static VALUE rb_Process_Status = Qnil;
26
+
27
+ void Init_Event_Backend(VALUE Event_Backend) {
28
+ id_transfer = rb_intern("transfer");
29
+ id_wait = rb_intern("wait");
30
+ // id_alive_p = rb_intern("alive?");
31
+ rb_Process_Status = rb_const_get_at(rb_mProcess, rb_intern("Status"));
32
+ }
33
+
34
+ VALUE
35
+ Event_Backend_transfer(VALUE fiber) {
36
+ #ifdef HAVE__RB_FIBER_TRANSFER
37
+ return rb_fiber_transfer(fiber, 0, NULL);
38
+ #else
39
+ return rb_funcall(fiber, id_transfer, 0);
40
+ #endif
41
+ }
42
+
43
+ VALUE
44
+ Event_Backend_transfer_result(VALUE fiber, VALUE result) {
45
+ // if (!RTEST(rb_fiber_alive_p(fiber))) {
46
+ // return Qnil;
47
+ // }
48
+
49
+ #ifdef HAVE__RB_FIBER_TRANSFER
50
+ return rb_fiber_transfer(fiber, 1, &result);
51
+ #else
52
+ return rb_funcall(fiber, id_transfer, 1, result);
53
+ #endif
54
+ }
55
+
56
+ VALUE Event_Backend_process_status_wait(rb_pid_t pid)
57
+ {
58
+ return rb_funcall(rb_Process_Status, id_wait, 2, PIDT2NUM(pid), INT2NUM(WNOHANG));
59
+ }
60
+
61
+ char* Event_Backend_verify_size(VALUE buffer, size_t offset, size_t length) {
62
+ if ((size_t)RSTRING_LEN(buffer) < offset + length) {
63
+ rb_raise(rb_eRuntimeError, "invalid offset/length exceeds bounds of buffer");
64
+ }
65
+
66
+ return RSTRING_PTR(buffer);
67
+ }
68
+
69
+ char* Event_Backend_resize_to_capacity(VALUE string, size_t offset, size_t length) {
70
+ size_t current_length = RSTRING_LEN(string);
71
+ long difference = (long)(offset + length) - (long)current_length;
72
+
73
+ difference += 1;
74
+
75
+ if (difference > 0) {
76
+ rb_str_modify_expand(string, difference);
77
+ } else {
78
+ rb_str_modify(string);
79
+ }
80
+
81
+ return RSTRING_PTR(string);
82
+ }
83
+
84
+ void Event_Backend_resize_to_fit(VALUE string, size_t offset, size_t length) {
85
+ size_t current_length = RSTRING_LEN(string);
86
+
87
+ if (current_length < (offset + length)) {
88
+ rb_str_set_len(string, offset + length);
89
+ }
90
+ }
91
+
92
+ int Event_Backend_nonblock_set(int file_descriptor)
93
+ {
94
+ int flags = fcntl(file_descriptor, F_GETFL, 0);
95
+
96
+ if (!(flags & O_NONBLOCK)) {
97
+ fcntl(file_descriptor, F_SETFL, flags | O_NONBLOCK);
98
+ }
99
+
100
+ return flags;
101
+ }
102
+
103
+ void Event_Backend_nonblock_restore(int file_descriptor, int flags)
104
+ {
105
+ if (!(flags & O_NONBLOCK)) {
106
+ fcntl(file_descriptor, F_SETFL, flags & ~flags);
107
+ }
108
+ }
@@ -18,6 +18,9 @@
18
18
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  // THE SOFTWARE.
20
20
 
21
+ #include <ruby.h>
22
+ #include <ruby/thread.h>
23
+
21
24
  enum Event {
22
25
  READABLE = 1,
23
26
  PRIORITY = 2,
@@ -26,4 +29,17 @@ enum Event {
26
29
  HANGUP = 16
27
30
  };
28
31
 
29
- #include <ruby/thread.h>
32
+ void
33
+ Init_Event_Backend();
34
+
35
+ VALUE Event_Backend_transfer(VALUE fiber);
36
+ VALUE Event_Backend_transfer_result(VALUE fiber, VALUE argument);
37
+
38
+ VALUE Event_Backend_process_status_wait(rb_pid_t pid);
39
+
40
+ char* Event_Backend_verify_size(VALUE buffer, size_t offset, size_t length);
41
+ char* Event_Backend_resize_to_capacity(VALUE string, size_t offset, size_t length);
42
+ void Event_Backend_resize_to_fit(VALUE string, size_t offset, size_t length);
43
+
44
+ int Event_Backend_nonblock_set(int file_descriptor);
45
+ void Event_Backend_nonblock_restore(int file_descriptor, int flags);
@@ -25,8 +25,10 @@
25
25
  #include <time.h>
26
26
  #include <errno.h>
27
27
 
28
+ #include "pidfd.c"
29
+
28
30
  static VALUE Event_Backend_EPoll = Qnil;
29
- static ID id_fileno, id_transfer;
31
+ static ID id_fileno;
30
32
 
31
33
  enum {EPOLL_MAX_EVENTS = 64};
32
34
 
@@ -111,6 +113,60 @@ VALUE Event_Backend_EPoll_close(VALUE self) {
111
113
  return Qnil;
112
114
  }
113
115
 
116
+ struct process_wait_arguments {
117
+ struct Event_Backend_EPoll *data;
118
+ pid_t pid;
119
+ int flags;
120
+ int descriptor;
121
+ };
122
+
123
+ static
124
+ VALUE process_wait_transfer(VALUE _arguments) {
125
+ struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
126
+
127
+ Event_Backend_transfer(arguments->data->loop);
128
+
129
+ return Event_Backend_process_status_wait(arguments->pid);
130
+ }
131
+
132
+ static
133
+ VALUE process_wait_ensure(VALUE _arguments) {
134
+ struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
135
+
136
+ // epoll_ctl(arguments->data->descriptor, EPOLL_CTL_DEL, arguments->descriptor, NULL);
137
+
138
+ close(arguments->descriptor);
139
+
140
+ return Qnil;
141
+ }
142
+
143
+ VALUE Event_Backend_EPoll_process_wait(VALUE self, VALUE fiber, VALUE pid, VALUE flags) {
144
+ struct Event_Backend_EPoll *data = NULL;
145
+ TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
146
+
147
+ struct process_wait_arguments process_wait_arguments = {
148
+ .data = data,
149
+ .pid = NUM2PIDT(pid),
150
+ .flags = NUM2INT(flags),
151
+ };
152
+
153
+ process_wait_arguments.descriptor = pidfd_open(process_wait_arguments.pid, 0);
154
+ rb_update_max_fd(process_wait_arguments.descriptor);
155
+
156
+ struct epoll_event event = {
157
+ .events = EPOLLIN|EPOLLRDHUP|EPOLLONESHOT,
158
+ .data = {.ptr = (void*)fiber},
159
+ };
160
+
161
+ int result = epoll_ctl(data->descriptor, EPOLL_CTL_ADD, process_wait_arguments.descriptor, &event);
162
+
163
+ if (result == -1) {
164
+ rb_sys_fail("epoll_ctl(process_wait)");
165
+ }
166
+
167
+ return rb_ensure(process_wait_transfer, (VALUE)&process_wait_arguments, process_wait_ensure, (VALUE)&process_wait_arguments);
168
+ }
169
+
114
170
  static inline
115
171
  uint32_t epoll_flags_from_events(int events) {
116
172
  uint32_t flags = 0;
@@ -161,7 +217,7 @@ static
161
217
  VALUE io_wait_transfer(VALUE _arguments) {
162
218
  struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
163
219
 
164
- VALUE result = rb_funcall(arguments->data->loop, id_transfer, 0);
220
+ VALUE result = Event_Backend_transfer(arguments->data->loop);
165
221
 
166
222
  return INT2NUM(events_from_epoll_flags(NUM2INT(result)));
167
223
  };
@@ -208,6 +264,155 @@ VALUE Event_Backend_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE event
208
264
  return rb_ensure(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_ensure, (VALUE)&io_wait_arguments);
209
265
  }
210
266
 
267
+ struct io_read_arguments {
268
+ VALUE self;
269
+ VALUE fiber;
270
+ VALUE io;
271
+
272
+ int flags;
273
+
274
+ int descriptor;
275
+
276
+ VALUE buffer;
277
+ size_t offset;
278
+ size_t length;
279
+ };
280
+
281
+ static
282
+ VALUE io_read_loop(VALUE _arguments) {
283
+ struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
284
+
285
+ size_t offset = arguments->offset;
286
+ size_t length = arguments->length;
287
+ size_t total = 0;
288
+
289
+ while (length > 0) {
290
+ char *buffer = Event_Backend_resize_to_capacity(arguments->buffer, offset, length);
291
+ ssize_t result = read(arguments->descriptor, buffer+offset, length);
292
+
293
+ if (result >= 0) {
294
+ offset += result;
295
+ length -= result;
296
+ total += result;
297
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
298
+ Event_Backend_EPoll_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(READABLE));
299
+ } else {
300
+ rb_sys_fail("Event_Backend_EPoll_io_read");
301
+ }
302
+ }
303
+
304
+ Event_Backend_resize_to_fit(arguments->buffer, arguments->offset, arguments->length);
305
+
306
+ return SIZET2NUM(total);
307
+ }
308
+
309
+ static
310
+ VALUE io_read_ensure(VALUE _arguments) {
311
+ struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
312
+
313
+ Event_Backend_nonblock_restore(arguments->descriptor, arguments->flags);
314
+
315
+ return Qnil;
316
+ }
317
+
318
+ VALUE Event_Backend_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _offset, VALUE _length) {
319
+ struct Event_Backend_EPoll *data = NULL;
320
+ TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
321
+
322
+ int descriptor = RB_NUM2INT(rb_funcall(io, id_fileno, 0));
323
+
324
+ size_t offset = NUM2SIZET(_offset);
325
+ size_t length = NUM2SIZET(_length);
326
+
327
+
328
+ struct io_read_arguments io_read_arguments = {
329
+ .self = self,
330
+ .fiber = fiber,
331
+ .io = io,
332
+
333
+ .flags = Event_Backend_nonblock_set(descriptor),
334
+ .descriptor = descriptor,
335
+ .buffer = buffer,
336
+ .offset = offset,
337
+ .length = length,
338
+ };
339
+
340
+ return rb_ensure(io_read_loop, (VALUE)&io_read_arguments, io_read_ensure, (VALUE)&io_read_arguments);
341
+ }
342
+
343
+ struct io_write_arguments {
344
+ VALUE self;
345
+ VALUE fiber;
346
+ VALUE io;
347
+
348
+ int flags;
349
+
350
+ int descriptor;
351
+
352
+ VALUE buffer;
353
+ size_t offset;
354
+ size_t length;
355
+ };
356
+
357
+ static
358
+ VALUE io_write_loop(VALUE _arguments) {
359
+ struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;
360
+
361
+ size_t offset = arguments->offset;
362
+ size_t length = arguments->length;
363
+ size_t total = 0;
364
+
365
+ while (length > 0) {
366
+ char *buffer = Event_Backend_verify_size(arguments->buffer, offset, length);
367
+ ssize_t result = write(arguments->descriptor, buffer+offset, length);
368
+
369
+ if (result >= 0) {
370
+ length -= result;
371
+ offset += result;
372
+ total += result;
373
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
374
+ Event_Backend_EPoll_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(WRITABLE));
375
+ } else {
376
+ rb_sys_fail("Event_Backend_EPoll_io_write");
377
+ }
378
+ }
379
+
380
+ return SIZET2NUM(total);
381
+ };
382
+
383
+ static
384
+ VALUE io_write_ensure(VALUE _arguments) {
385
+ struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;
386
+
387
+ Event_Backend_nonblock_restore(arguments->descriptor, arguments->flags);
388
+
389
+ return Qnil;
390
+ };
391
+
392
+ VALUE Event_Backend_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _offset, VALUE _length) {
393
+ struct Event_Backend_EPoll *data = NULL;
394
+ TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
395
+
396
+ int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
397
+
398
+ size_t offset = NUM2SIZET(_offset);
399
+ size_t length = NUM2SIZET(_length);
400
+
401
+ struct io_write_arguments io_write_arguments = {
402
+ .self = self,
403
+ .fiber = fiber,
404
+ .io = io,
405
+
406
+ .flags = Event_Backend_nonblock_set(descriptor),
407
+ .descriptor = descriptor,
408
+ .buffer = buffer,
409
+ .offset = offset,
410
+ .length = length,
411
+ };
412
+
413
+ return rb_ensure(io_write_loop, (VALUE)&io_write_arguments, io_write_ensure, (VALUE)&io_write_arguments);
414
+ }
415
+
211
416
  static
212
417
  int make_timeout(VALUE duration) {
213
418
  if (duration == Qnil) {
@@ -272,13 +477,13 @@ VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
272
477
  .timeout = 0
273
478
  };
274
479
 
275
- select_internal_without_gvl(&arguments);
480
+ select_internal_with_gvl(&arguments);
276
481
 
277
482
  if (arguments.count == 0) {
278
483
  arguments.timeout = make_timeout(duration);
279
484
 
280
485
  if (arguments.timeout != 0) {
281
- select_internal_with_gvl(&arguments);
486
+ select_internal_without_gvl(&arguments);
282
487
  }
283
488
  }
284
489
 
@@ -288,7 +493,7 @@ VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
288
493
 
289
494
  // fprintf(stderr, "-> fiber=%p descriptor=%d\n", (void*)fiber, events[i].data.fd);
290
495
 
291
- rb_funcall(fiber, id_transfer, 1, result);
496
+ Event_Backend_transfer_result(fiber, result);
292
497
  }
293
498
 
294
499
  return INT2NUM(arguments.count);
@@ -296,14 +501,17 @@ VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
296
501
 
297
502
  void Init_Event_Backend_EPoll(VALUE Event_Backend) {
298
503
  id_fileno = rb_intern("fileno");
299
- id_transfer = rb_intern("transfer");
300
504
 
301
505
  Event_Backend_EPoll = rb_define_class_under(Event_Backend, "EPoll", rb_cObject);
302
506
 
303
507
  rb_define_alloc_func(Event_Backend_EPoll, Event_Backend_EPoll_allocate);
304
508
  rb_define_method(Event_Backend_EPoll, "initialize", Event_Backend_EPoll_initialize, 1);
509
+ rb_define_method(Event_Backend_EPoll, "select", Event_Backend_EPoll_select, 1);
305
510
  rb_define_method(Event_Backend_EPoll, "close", Event_Backend_EPoll_close, 0);
306
511
 
307
512
  rb_define_method(Event_Backend_EPoll, "io_wait", Event_Backend_EPoll_io_wait, 3);
308
- rb_define_method(Event_Backend_EPoll, "select", Event_Backend_EPoll_select, 1);
513
+ rb_define_method(Event_Backend_EPoll, "io_read", Event_Backend_EPoll_io_read, 5);
514
+ rb_define_method(Event_Backend_EPoll, "io_write", Event_Backend_EPoll_io_write, 5);
515
+
516
+ rb_define_method(Event_Backend_EPoll, "process_wait", Event_Backend_EPoll_process_wait, 3);
309
517
  }