event 0.6.0 → 0.8.2

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: '0380b6d95d8bd8f8d378820eefa77e6c6f0f1aaceb2afec54cb4d38f57747cbc'
4
- data.tar.gz: 2a0bfede977154f30a402fda4ec445eedc4daf3893bae8760eceaa1e58c999be
3
+ metadata.gz: 62bded3e0e8e8929ef5f76b427a975f1444c215d3566423e17b6aecdcbbb1f0b
4
+ data.tar.gz: 6c241f562c00af271443406efa52c935f84fb6b30023b4c7086a8c4ee5b7b965
5
5
  SHA512:
6
- metadata.gz: d12fab2ce89b8c22d583a7472670f8bdb5b5b3428832938f9c51ce3635f08bfaf7d107b6568f762849a4fa8b32fdb0d79823bbd4ebd795b690e885b0eff52798
7
- data.tar.gz: 793cf18caeb1457cd5499ee3d0fd2108dbf46e953cbc11b80e7c800efeb6beac279395a24da420b4c751a89ee5ecd54ad53a3b3a58d4b07d75e9a89d84a8be4d
6
+ metadata.gz: 75b5af033d60eb53df18b9b6fe9805827ccd4bfef0f4e26943428ddb4aee43006ce4eb12897102d33d50b31834c7bbd0be70821f2bcd6fe30cab5a657839321a
7
+ data.tar.gz: 57d719b1318c0740c58df4476ffb44719c8ded66d78889eeb60e15aead7d86e9778ad464a460dda4a2318f3435450e43778873aac8ea7a9c0150c37f828b4646
data/ext/event/event.c CHANGED
@@ -19,10 +19,10 @@
19
19
  // THE SOFTWARE.
20
20
 
21
21
  #include "event.h"
22
- #include "backend/backend.h"
22
+ #include "selector/selector.h"
23
23
 
24
24
  VALUE Event = Qnil;
25
- VALUE Event_Backend = Qnil;
25
+ VALUE Event_Selector = Qnil;
26
26
 
27
27
  void Init_event()
28
28
  {
@@ -31,19 +31,19 @@ void Init_event()
31
31
  #endif
32
32
 
33
33
  Event = rb_define_module("Event");
34
- Event_Backend = rb_define_module_under(Event, "Backend");
34
+ Event_Selector = rb_define_module_under(Event, "Selector");
35
35
 
36
- Init_Event_Backend(Event_Backend);
36
+ Init_Event_Selector(Event_Selector);
37
37
 
38
- #ifdef EVENT_BACKEND_URING
39
- Init_Event_Backend_URing(Event_Backend);
38
+ #ifdef EVENT_SELECTOR_URING
39
+ Init_Event_Selector_URing(Event_Selector);
40
40
  #endif
41
41
 
42
- #ifdef EVENT_BACKEND_EPOLL
43
- Init_Event_Backend_EPoll(Event_Backend);
42
+ #ifdef EVENT_SELECTOR_EPOLL
43
+ Init_Event_Selector_EPoll(Event_Selector);
44
44
  #endif
45
45
 
46
- #ifdef EVENT_BACKEND_KQUEUE
47
- Init_Event_Backend_KQueue(Event_Backend);
46
+ #ifdef EVENT_SELECTOR_KQUEUE
47
+ Init_Event_Selector_KQueue(Event_Selector);
48
48
  #endif
49
49
  }
data/ext/event/event.h CHANGED
@@ -27,13 +27,13 @@
27
27
  void Init_event();
28
28
 
29
29
  #ifdef HAVE_LIBURING_H
30
- #include "backend/uring.h"
30
+ #include "selector/uring.h"
31
31
  #endif
32
32
 
33
33
  #ifdef HAVE_SYS_EPOLL_H
34
- #include "backend/epoll.h"
34
+ #include "selector/epoll.h"
35
35
  #endif
36
36
 
37
37
  #ifdef HAVE_SYS_EVENT_H
38
- #include "backend/kqueue.h"
38
+ #include "selector/kqueue.h"
39
39
  #endif
data/ext/event/extconf.rb CHANGED
@@ -30,23 +30,29 @@ dir_config(extension_name)
30
30
 
31
31
  $CFLAGS << " -Wall"
32
32
 
33
- $srcs = ["event.c", "backend/backend.c"]
34
- $VPATH << "$(srcdir)/backend"
33
+ $srcs = ["event.c", "selector/selector.c"]
34
+ $VPATH << "$(srcdir)/selector"
35
35
 
36
36
  have_func('&rb_fiber_transfer')
37
37
 
38
38
  if have_library('uring') and have_header('liburing.h')
39
- $srcs << "backend/uring.c"
39
+ $srcs << "selector/uring.c"
40
40
  end
41
41
 
42
42
  if have_header('sys/epoll.h')
43
- $srcs << "backend/epoll.c"
43
+ $srcs << "selector/epoll.c"
44
44
  end
45
45
 
46
46
  if have_header('sys/event.h')
47
- $srcs << "backend/kqueue.c"
47
+ $srcs << "selector/kqueue.c"
48
48
  end
49
49
 
50
+ have_func("rb_io_descriptor")
51
+ have_func("&rb_process_status_wait")
52
+ have_func("&rb_fiber_raise")
53
+
54
+ have_header('ruby/io/buffer.h')
55
+
50
56
  create_header
51
57
 
52
58
  # Generate the makefile to compile the native binary into `lib`:
@@ -19,7 +19,7 @@
19
19
  // THE SOFTWARE.
20
20
 
21
21
  #include "kqueue.h"
22
- #include "backend.h"
22
+ #include "selector.h"
23
23
 
24
24
  #include <sys/epoll.h>
25
25
  #include <time.h>
@@ -27,70 +27,69 @@
27
27
 
28
28
  #include "pidfd.c"
29
29
 
30
- static VALUE Event_Backend_EPoll = Qnil;
31
- static ID id_fileno;
30
+ static VALUE Event_Selector_EPoll = Qnil;
32
31
 
33
32
  enum {EPOLL_MAX_EVENTS = 64};
34
33
 
35
- struct Event_Backend_EPoll {
36
- VALUE loop;
34
+ struct Event_Selector_EPoll {
35
+ struct Event_Selector backend;
37
36
  int descriptor;
38
37
  };
39
38
 
40
- void Event_Backend_EPoll_Type_mark(void *_data)
39
+ void Event_Selector_EPoll_Type_mark(void *_data)
41
40
  {
42
- struct Event_Backend_EPoll *data = _data;
43
- rb_gc_mark(data->loop);
41
+ struct Event_Selector_EPoll *data = _data;
42
+ Event_Selector_mark(&data->backend);
44
43
  }
45
44
 
46
45
  static
47
- void close_internal(struct Event_Backend_EPoll *data) {
46
+ void close_internal(struct Event_Selector_EPoll *data) {
48
47
  if (data->descriptor >= 0) {
49
48
  close(data->descriptor);
50
49
  data->descriptor = -1;
51
50
  }
52
51
  }
53
52
 
54
- void Event_Backend_EPoll_Type_free(void *_data)
53
+ void Event_Selector_EPoll_Type_free(void *_data)
55
54
  {
56
- struct Event_Backend_EPoll *data = _data;
55
+ struct Event_Selector_EPoll *data = _data;
57
56
 
58
57
  close_internal(data);
59
58
 
60
59
  free(data);
61
60
  }
62
61
 
63
- size_t Event_Backend_EPoll_Type_size(const void *data)
62
+ size_t Event_Selector_EPoll_Type_size(const void *data)
64
63
  {
65
- return sizeof(struct Event_Backend_EPoll);
64
+ return sizeof(struct Event_Selector_EPoll);
66
65
  }
67
66
 
68
- static const rb_data_type_t Event_Backend_EPoll_Type = {
67
+ static const rb_data_type_t Event_Selector_EPoll_Type = {
69
68
  .wrap_struct_name = "Event::Backend::EPoll",
70
69
  .function = {
71
- .dmark = Event_Backend_EPoll_Type_mark,
72
- .dfree = Event_Backend_EPoll_Type_free,
73
- .dsize = Event_Backend_EPoll_Type_size,
70
+ .dmark = Event_Selector_EPoll_Type_mark,
71
+ .dfree = Event_Selector_EPoll_Type_free,
72
+ .dsize = Event_Selector_EPoll_Type_size,
74
73
  },
75
74
  .data = NULL,
76
75
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
77
76
  };
78
77
 
79
- VALUE Event_Backend_EPoll_allocate(VALUE self) {
80
- struct Event_Backend_EPoll *data = NULL;
81
- VALUE instance = TypedData_Make_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
78
+ VALUE Event_Selector_EPoll_allocate(VALUE self) {
79
+ struct Event_Selector_EPoll *data = NULL;
80
+ VALUE instance = TypedData_Make_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
82
81
 
83
- data->loop = Qnil;
82
+ Event_Selector_initialize(&data->backend, Qnil);
84
83
  data->descriptor = -1;
85
84
 
86
85
  return instance;
87
86
  }
88
87
 
89
- VALUE Event_Backend_EPoll_initialize(VALUE self, VALUE loop) {
90
- struct Event_Backend_EPoll *data = NULL;
91
- TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
88
+ VALUE Event_Selector_EPoll_initialize(VALUE self, VALUE loop) {
89
+ struct Event_Selector_EPoll *data = NULL;
90
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
92
91
 
93
- data->loop = loop;
92
+ Event_Selector_initialize(&data->backend, loop);
94
93
  int result = epoll_create1(EPOLL_CLOEXEC);
95
94
 
96
95
  if (result == -1) {
@@ -104,17 +103,62 @@ VALUE Event_Backend_EPoll_initialize(VALUE self, VALUE loop) {
104
103
  return self;
105
104
  }
106
105
 
107
- VALUE Event_Backend_EPoll_close(VALUE self) {
108
- struct Event_Backend_EPoll *data = NULL;
109
- TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
106
+ VALUE Event_Selector_EPoll_close(VALUE self) {
107
+ struct Event_Selector_EPoll *data = NULL;
108
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
110
109
 
111
110
  close_internal(data);
112
111
 
113
112
  return Qnil;
114
113
  }
115
114
 
115
+ VALUE Event_Selector_EPoll_transfer(int argc, VALUE *argv, VALUE self)
116
+ {
117
+ struct Event_Selector_EPoll *data = NULL;
118
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
119
+
120
+ Event_Selector_wait_and_transfer(&data->backend, argc, argv);
121
+
122
+ return Qnil;
123
+ }
124
+
125
+ VALUE Event_Selector_EPoll_yield(VALUE self)
126
+ {
127
+ struct Event_Selector_EPoll *data = NULL;
128
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
129
+
130
+ Event_Selector_yield(&data->backend);
131
+
132
+ return Qnil;
133
+ }
134
+
135
+ VALUE Event_Selector_EPoll_push(VALUE self, VALUE fiber)
136
+ {
137
+ struct Event_Selector_EPoll *data = NULL;
138
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
139
+
140
+ Event_Selector_queue_push(&data->backend, fiber);
141
+
142
+ return Qnil;
143
+ }
144
+
145
+ VALUE Event_Selector_EPoll_raise(int argc, VALUE *argv, VALUE self)
146
+ {
147
+ struct Event_Selector_EPoll *data = NULL;
148
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
149
+
150
+ return Event_Selector_wait_and_raise(&data->backend, argc, argv);
151
+ }
152
+
153
+ VALUE Event_Selector_EPoll_ready_p(VALUE self) {
154
+ struct Event_Selector_EPoll *data = NULL;
155
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
156
+
157
+ return data->backend.ready ? Qtrue : Qfalse;
158
+ }
159
+
116
160
  struct process_wait_arguments {
117
- struct Event_Backend_EPoll *data;
161
+ struct Event_Selector_EPoll *data;
118
162
  pid_t pid;
119
163
  int flags;
120
164
  int descriptor;
@@ -124,9 +168,9 @@ static
124
168
  VALUE process_wait_transfer(VALUE _arguments) {
125
169
  struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
126
170
 
127
- Event_Backend_transfer(arguments->data->loop);
171
+ Event_Selector_fiber_transfer(arguments->data->backend.loop, 0, NULL);
128
172
 
129
- return Event_Backend_process_status_wait(arguments->pid);
173
+ return Event_Selector_process_status_wait(arguments->pid);
130
174
  }
131
175
 
132
176
  static
@@ -140,10 +184,10 @@ VALUE process_wait_ensure(VALUE _arguments) {
140
184
  return Qnil;
141
185
  }
142
186
 
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
-
187
+ VALUE Event_Selector_EPoll_process_wait(VALUE self, VALUE fiber, VALUE pid, VALUE flags) {
188
+ struct Event_Selector_EPoll *data = NULL;
189
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
190
+
147
191
  struct process_wait_arguments process_wait_arguments = {
148
192
  .data = data,
149
193
  .pid = NUM2PIDT(pid),
@@ -171,9 +215,9 @@ static inline
171
215
  uint32_t epoll_flags_from_events(int events) {
172
216
  uint32_t flags = 0;
173
217
 
174
- if (events & READABLE) flags |= EPOLLIN;
175
- if (events & PRIORITY) flags |= EPOLLPRI;
176
- if (events & WRITABLE) flags |= EPOLLOUT;
218
+ if (events & EVENT_READABLE) flags |= EPOLLIN;
219
+ if (events & EVENT_PRIORITY) flags |= EPOLLPRI;
220
+ if (events & EVENT_WRITABLE) flags |= EPOLLOUT;
177
221
 
178
222
  flags |= EPOLLRDHUP;
179
223
  flags |= EPOLLONESHOT;
@@ -185,15 +229,15 @@ static inline
185
229
  int events_from_epoll_flags(uint32_t flags) {
186
230
  int events = 0;
187
231
 
188
- if (flags & EPOLLIN) events |= READABLE;
189
- if (flags & EPOLLPRI) events |= PRIORITY;
190
- if (flags & EPOLLOUT) events |= WRITABLE;
232
+ if (flags & EPOLLIN) events |= EVENT_READABLE;
233
+ if (flags & EPOLLPRI) events |= EVENT_PRIORITY;
234
+ if (flags & EPOLLOUT) events |= EVENT_WRITABLE;
191
235
 
192
236
  return events;
193
237
  }
194
238
 
195
239
  struct io_wait_arguments {
196
- struct Event_Backend_EPoll *data;
240
+ struct Event_Selector_EPoll *data;
197
241
  int descriptor;
198
242
  int duplicate;
199
243
  };
@@ -217,18 +261,18 @@ static
217
261
  VALUE io_wait_transfer(VALUE _arguments) {
218
262
  struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
219
263
 
220
- VALUE result = Event_Backend_transfer(arguments->data->loop);
264
+ VALUE result = Event_Selector_fiber_transfer(arguments->data->backend.loop, 0, NULL);
221
265
 
222
266
  return INT2NUM(events_from_epoll_flags(NUM2INT(result)));
223
267
  };
224
268
 
225
- VALUE Event_Backend_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
226
- struct Event_Backend_EPoll *data = NULL;
227
- TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
269
+ VALUE Event_Selector_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
270
+ struct Event_Selector_EPoll *data = NULL;
271
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
228
272
 
229
273
  struct epoll_event event = {0};
230
274
 
231
- int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
275
+ int descriptor = Event_Selector_io_descriptor(io);
232
276
  int duplicate = -1;
233
277
 
234
278
  event.events = epoll_flags_from_events(NUM2INT(events));
@@ -264,6 +308,8 @@ VALUE Event_Backend_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE event
264
308
  return rb_ensure(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_ensure, (VALUE)&io_wait_arguments);
265
309
  }
266
310
 
311
+ #ifdef HAVE_RUBY_IO_BUFFER_H
312
+
267
313
  struct io_read_arguments {
268
314
  VALUE self;
269
315
  VALUE fiber;
@@ -274,7 +320,6 @@ struct io_read_arguments {
274
320
  int descriptor;
275
321
 
276
322
  VALUE buffer;
277
- size_t offset;
278
323
  size_t length;
279
324
  };
280
325
 
@@ -282,58 +327,54 @@ static
282
327
  VALUE io_read_loop(VALUE _arguments) {
283
328
  struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
284
329
 
285
- size_t offset = arguments->offset;
330
+ void *base;
331
+ size_t size;
332
+ rb_io_buffer_get_mutable(arguments->buffer, &base, &size);
333
+
334
+ size_t offset = 0;
286
335
  size_t length = arguments->length;
287
- size_t total = 0;
288
336
 
289
337
  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);
338
+ size_t maximum_size = size - offset;
339
+ ssize_t result = read(arguments->descriptor, (char*)base+offset, maximum_size);
292
340
 
293
- if (result >= 0) {
341
+ if (result == 0) {
342
+ break;
343
+ } else if (result > 0) {
294
344
  offset += result;
295
345
  length -= result;
296
- total += result;
297
346
  } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
298
- Event_Backend_EPoll_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(READABLE));
347
+ Event_Selector_EPoll_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(EVENT_READABLE));
299
348
  } else {
300
- rb_sys_fail("Event_Backend_EPoll_io_read");
349
+ rb_sys_fail("Event_Selector_EPoll_io_read");
301
350
  }
302
351
  }
303
352
 
304
- Event_Backend_resize_to_fit(arguments->buffer, arguments->offset, arguments->length);
305
-
306
- return SIZET2NUM(total);
353
+ return SIZET2NUM(offset);
307
354
  }
308
355
 
309
356
  static
310
357
  VALUE io_read_ensure(VALUE _arguments) {
311
358
  struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
312
359
 
313
- Event_Backend_nonblock_restore(arguments->descriptor, arguments->flags);
360
+ Event_Selector_nonblock_restore(arguments->descriptor, arguments->flags);
314
361
 
315
362
  return Qnil;
316
363
  }
317
364
 
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));
365
+ VALUE Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length) {
366
+ int descriptor = Event_Selector_io_descriptor(io);
323
367
 
324
- size_t offset = NUM2SIZET(_offset);
325
368
  size_t length = NUM2SIZET(_length);
326
369
 
327
-
328
370
  struct io_read_arguments io_read_arguments = {
329
371
  .self = self,
330
372
  .fiber = fiber,
331
373
  .io = io,
332
374
 
333
- .flags = Event_Backend_nonblock_set(descriptor),
375
+ .flags = Event_Selector_nonblock_set(descriptor),
334
376
  .descriptor = descriptor,
335
377
  .buffer = buffer,
336
- .offset = offset,
337
378
  .length = length,
338
379
  };
339
380
 
@@ -350,7 +391,6 @@ struct io_write_arguments {
350
391
  int descriptor;
351
392
 
352
393
  VALUE buffer;
353
- size_t offset;
354
394
  size_t length;
355
395
  };
356
396
 
@@ -358,44 +398,45 @@ static
358
398
  VALUE io_write_loop(VALUE _arguments) {
359
399
  struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;
360
400
 
361
- size_t offset = arguments->offset;
401
+ const void *base;
402
+ size_t size;
403
+ rb_io_buffer_get_immutable(arguments->buffer, &base, &size);
404
+
405
+ size_t offset = 0;
362
406
  size_t length = arguments->length;
363
- size_t total = 0;
407
+
408
+ if (length > size) {
409
+ rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
410
+ }
364
411
 
365
412
  while (length > 0) {
366
- char *buffer = Event_Backend_verify_size(arguments->buffer, offset, length);
367
- ssize_t result = write(arguments->descriptor, buffer+offset, length);
413
+ ssize_t result = write(arguments->descriptor, (char*)base+offset, length);
368
414
 
369
415
  if (result >= 0) {
370
- length -= result;
371
416
  offset += result;
372
- total += result;
417
+ length -= result;
373
418
  } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
374
- Event_Backend_EPoll_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(WRITABLE));
419
+ Event_Selector_EPoll_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(EVENT_WRITABLE));
375
420
  } else {
376
- rb_sys_fail("Event_Backend_EPoll_io_write");
421
+ rb_sys_fail("Event_Selector_EPoll_io_write");
377
422
  }
378
423
  }
379
424
 
380
- return SIZET2NUM(total);
425
+ return SIZET2NUM(offset);
381
426
  };
382
427
 
383
428
  static
384
429
  VALUE io_write_ensure(VALUE _arguments) {
385
430
  struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;
386
431
 
387
- Event_Backend_nonblock_restore(arguments->descriptor, arguments->flags);
432
+ Event_Selector_nonblock_restore(arguments->descriptor, arguments->flags);
388
433
 
389
434
  return Qnil;
390
435
  };
391
436
 
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);
437
+ VALUE Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length) {
438
+ int descriptor = Event_Selector_io_descriptor(io);
395
439
 
396
- int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
397
-
398
- size_t offset = NUM2SIZET(_offset);
399
440
  size_t length = NUM2SIZET(_length);
400
441
 
401
442
  struct io_write_arguments io_write_arguments = {
@@ -403,16 +444,17 @@ VALUE Event_Backend_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buff
403
444
  .fiber = fiber,
404
445
  .io = io,
405
446
 
406
- .flags = Event_Backend_nonblock_set(descriptor),
447
+ .flags = Event_Selector_nonblock_set(descriptor),
407
448
  .descriptor = descriptor,
408
449
  .buffer = buffer,
409
- .offset = offset,
410
450
  .length = length,
411
451
  };
412
452
 
413
453
  return rb_ensure(io_write_loop, (VALUE)&io_write_arguments, io_write_ensure, (VALUE)&io_write_arguments);
414
454
  }
415
455
 
456
+ #endif
457
+
416
458
  static
417
459
  int make_timeout(VALUE duration) {
418
460
  if (duration == Qnil) {
@@ -433,7 +475,7 @@ int make_timeout(VALUE duration) {
433
475
  }
434
476
 
435
477
  struct select_arguments {
436
- struct Event_Backend_EPoll *data;
478
+ struct Event_Selector_EPoll *data;
437
479
 
438
480
  int count;
439
481
  struct epoll_event events[EPOLL_MAX_EVENTS];
@@ -468,9 +510,11 @@ void select_internal_with_gvl(struct select_arguments *arguments) {
468
510
  }
469
511
  }
470
512
 
471
- VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
472
- struct Event_Backend_EPoll *data = NULL;
473
- TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
513
+ VALUE Event_Selector_EPoll_select(VALUE self, VALUE duration) {
514
+ struct Event_Selector_EPoll *data = NULL;
515
+ TypedData_Get_Struct(self, struct Event_Selector_EPoll, &Event_Selector_EPoll_Type, data);
516
+
517
+ int ready = Event_Selector_queue_flush(&data->backend);
474
518
 
475
519
  struct select_arguments arguments = {
476
520
  .data = data,
@@ -478,8 +522,9 @@ VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
478
522
  };
479
523
 
480
524
  select_internal_with_gvl(&arguments);
481
-
482
- if (arguments.count == 0) {
525
+
526
+ // If the ready list was empty and no events were processed:
527
+ if (!ready && arguments.count == 0) {
483
528
  arguments.timeout = make_timeout(duration);
484
529
 
485
530
  if (arguments.timeout != 0) {
@@ -493,25 +538,34 @@ VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
493
538
 
494
539
  // fprintf(stderr, "-> fiber=%p descriptor=%d\n", (void*)fiber, events[i].data.fd);
495
540
 
496
- Event_Backend_transfer_result(fiber, result);
541
+ Event_Selector_fiber_transfer(fiber, 1, &result);
497
542
  }
498
543
 
499
544
  return INT2NUM(arguments.count);
500
545
  }
501
546
 
502
- void Init_Event_Backend_EPoll(VALUE Event_Backend) {
503
- id_fileno = rb_intern("fileno");
547
+ void Init_Event_Selector_EPoll(VALUE Event_Selector) {
548
+ Event_Selector_EPoll = rb_define_class_under(Event_Selector, "EPoll", rb_cObject);
549
+
550
+ rb_define_alloc_func(Event_Selector_EPoll, Event_Selector_EPoll_allocate);
551
+ rb_define_method(Event_Selector_EPoll, "initialize", Event_Selector_EPoll_initialize, 1);
552
+
553
+ rb_define_method(Event_Selector_EPoll, "transfer", Event_Selector_EPoll_transfer, -1);
554
+ rb_define_method(Event_Selector_EPoll, "yield", Event_Selector_EPoll_yield, 0);
555
+ rb_define_method(Event_Selector_EPoll, "push", Event_Selector_EPoll_push, 1);
556
+ rb_define_method(Event_Selector_EPoll, "raise", Event_Selector_EPoll_raise, -1);
557
+
558
+ rb_define_method(Event_Selector_EPoll, "ready?", Event_Selector_EPoll_ready_p, 0);
504
559
 
505
- Event_Backend_EPoll = rb_define_class_under(Event_Backend, "EPoll", rb_cObject);
560
+ rb_define_method(Event_Selector_EPoll, "select", Event_Selector_EPoll_select, 1);
561
+ rb_define_method(Event_Selector_EPoll, "close", Event_Selector_EPoll_close, 0);
506
562
 
507
- rb_define_alloc_func(Event_Backend_EPoll, Event_Backend_EPoll_allocate);
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);
510
- rb_define_method(Event_Backend_EPoll, "close", Event_Backend_EPoll_close, 0);
563
+ rb_define_method(Event_Selector_EPoll, "io_wait", Event_Selector_EPoll_io_wait, 3);
511
564
 
512
- rb_define_method(Event_Backend_EPoll, "io_wait", Event_Backend_EPoll_io_wait, 3);
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);
565
+ #ifdef HAVE_RUBY_IO_BUFFER_H
566
+ rb_define_method(Event_Selector_EPoll, "io_read", Event_Selector_EPoll_io_read, 4);
567
+ rb_define_method(Event_Selector_EPoll, "io_write", Event_Selector_EPoll_io_write, 4);
568
+ #endif
515
569
 
516
- rb_define_method(Event_Backend_EPoll, "process_wait", Event_Backend_EPoll_process_wait, 3);
570
+ rb_define_method(Event_Selector_EPoll, "process_wait", Event_Selector_EPoll_process_wait, 3);
517
571
  }