event 0.5.0 → 0.6.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: 932f834070b1bb738a09a9cb306599f80386755e4bfa2c78b502715acecf56b7
4
- data.tar.gz: a04db89605437563a594e9012adb50a60af4a6c6dfacdd048ec0b03048f68010
3
+ metadata.gz: '0380b6d95d8bd8f8d378820eefa77e6c6f0f1aaceb2afec54cb4d38f57747cbc'
4
+ data.tar.gz: 2a0bfede977154f30a402fda4ec445eedc4daf3893bae8760eceaa1e58c999be
5
5
  SHA512:
6
- metadata.gz: 074e688c34260fe28c3f15857c731052a745605deafd7d75bd07f9e0dc59aeed34d6633a05f5259d03a357c7f5c45762ef7de53a2f5dfc5c32213471f66eb847
7
- data.tar.gz: 2214b5749ca680a7892e01539ec962b976f4fad480aa4a5d6d0d589981af8944a2ac94b03484e3e7e7936fd4bbf344418b72cb457fa229ffda11ff91bae9e5e8
6
+ metadata.gz: d12fab2ce89b8c22d583a7472670f8bdb5b5b3428832938f9c51ce3635f08bfaf7d107b6568f762849a4fa8b32fdb0d79823bbd4ebd795b690e885b0eff52798
7
+ data.tar.gz: 793cf18caeb1457cd5499ee3d0fd2108dbf46e953cbc11b80e7c800efeb6beac279395a24da420b4c751a89ee5ecd54ad53a3b3a58d4b07d75e9a89d84a8be4d
data/ext/event/backend.o CHANGED
Binary file
@@ -19,12 +19,7 @@
19
19
  // THE SOFTWARE.
20
20
 
21
21
  #include "backend.h"
22
-
23
- #if HAVE_RB_FIBER_TRANSFER_KW
24
- #define HAVE_RB_FIBER_TRANSFER 1
25
- #else
26
- #define HAVE_RB_FIBER_TRANSFER 0
27
- #endif
22
+ #include <fcntl.h>
28
23
 
29
24
  static ID id_transfer, id_wait;
30
25
  static VALUE rb_Process_Status = Qnil;
@@ -38,7 +33,7 @@ void Init_Event_Backend(VALUE Event_Backend) {
38
33
 
39
34
  VALUE
40
35
  Event_Backend_transfer(VALUE fiber) {
41
- #if HAVE_RB_FIBER_TRANSFER
36
+ #ifdef HAVE__RB_FIBER_TRANSFER
42
37
  return rb_fiber_transfer(fiber, 0, NULL);
43
38
  #else
44
39
  return rb_funcall(fiber, id_transfer, 0);
@@ -51,7 +46,7 @@ Event_Backend_transfer_result(VALUE fiber, VALUE result) {
51
46
  // return Qnil;
52
47
  // }
53
48
 
54
- #if HAVE_RB_FIBER_TRANSFER
49
+ #ifdef HAVE__RB_FIBER_TRANSFER
55
50
  return rb_fiber_transfer(fiber, 1, &result);
56
51
  #else
57
52
  return rb_funcall(fiber, id_transfer, 1, result);
@@ -62,3 +57,52 @@ VALUE Event_Backend_process_status_wait(rb_pid_t pid)
62
57
  {
63
58
  return rb_funcall(rb_Process_Status, id_wait, 2, PIDT2NUM(pid), INT2NUM(WNOHANG));
64
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
+ }
@@ -36,3 +36,10 @@ VALUE Event_Backend_transfer(VALUE fiber);
36
36
  VALUE Event_Backend_transfer_result(VALUE fiber, VALUE argument);
37
37
 
38
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);
@@ -264,6 +264,155 @@ VALUE Event_Backend_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE event
264
264
  return rb_ensure(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_ensure, (VALUE)&io_wait_arguments);
265
265
  }
266
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
+
267
416
  static
268
417
  int make_timeout(VALUE duration) {
269
418
  if (duration == Qnil) {
@@ -357,9 +506,12 @@ void Init_Event_Backend_EPoll(VALUE Event_Backend) {
357
506
 
358
507
  rb_define_alloc_func(Event_Backend_EPoll, Event_Backend_EPoll_allocate);
359
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);
360
510
  rb_define_method(Event_Backend_EPoll, "close", Event_Backend_EPoll_close, 0);
361
511
 
362
512
  rb_define_method(Event_Backend_EPoll, "io_wait", Event_Backend_EPoll_io_wait, 3);
363
- 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
+
364
516
  rb_define_method(Event_Backend_EPoll, "process_wait", Event_Backend_EPoll_process_wait, 3);
365
517
  }
@@ -181,7 +181,7 @@ VALUE Event_Backend_KQueue_process_wait(VALUE self, VALUE fiber, VALUE pid, VALU
181
181
  struct process_wait_arguments process_wait_arguments = {
182
182
  .data = data,
183
183
  .pid = NUM2PIDT(pid),
184
- .flags = NUM2INT(flags),
184
+ .flags = RB_NUM2INT(flags),
185
185
  };
186
186
 
187
187
  int waiting = process_add_filters(data->descriptor, process_wait_arguments.pid, fiber);
@@ -267,7 +267,7 @@ VALUE io_wait_rescue(VALUE _arguments, VALUE exception) {
267
267
  io_remove_filters(arguments->data->descriptor, arguments->descriptor, arguments->events);
268
268
 
269
269
  rb_exc_raise(exception);
270
- };
270
+ }
271
271
 
272
272
  static inline
273
273
  int events_from_kqueue_filter(int filter) {
@@ -283,17 +283,17 @@ VALUE io_wait_transfer(VALUE _arguments) {
283
283
 
284
284
  VALUE result = Event_Backend_transfer(arguments->data->loop);
285
285
 
286
- return INT2NUM(events_from_kqueue_filter(NUM2INT(result)));
287
- };
286
+ return INT2NUM(events_from_kqueue_filter(RB_NUM2INT(result)));
287
+ }
288
288
 
289
289
  VALUE Event_Backend_KQueue_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
290
290
  struct Event_Backend_KQueue *data = NULL;
291
291
  TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
292
292
 
293
- int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
293
+ int descriptor = RB_NUM2INT(rb_funcall(io, id_fileno, 0));
294
294
 
295
295
  struct io_wait_arguments io_wait_arguments = {
296
- .events = io_add_filters(data->descriptor, descriptor, NUM2INT(events), fiber),
296
+ .events = io_add_filters(data->descriptor, descriptor, RB_NUM2INT(events), fiber),
297
297
  .data = data,
298
298
  .descriptor = descriptor,
299
299
  };
@@ -301,6 +301,154 @@ VALUE Event_Backend_KQueue_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE even
301
301
  return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
302
302
  }
303
303
 
304
+ struct io_read_arguments {
305
+ VALUE self;
306
+ VALUE fiber;
307
+ VALUE io;
308
+
309
+ int flags;
310
+
311
+ int descriptor;
312
+
313
+ VALUE buffer;
314
+ size_t offset;
315
+ size_t length;
316
+ };
317
+
318
+ static
319
+ VALUE io_read_loop(VALUE _arguments) {
320
+ struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
321
+
322
+ size_t offset = arguments->offset;
323
+ size_t length = arguments->length;
324
+ size_t total = 0;
325
+
326
+ while (length > 0) {
327
+ char *buffer = Event_Backend_resize_to_capacity(arguments->buffer, offset, length);
328
+ ssize_t result = read(arguments->descriptor, buffer+offset, length);
329
+
330
+ if (result >= 0) {
331
+ offset += result;
332
+ length -= result;
333
+ total += result;
334
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
335
+ Event_Backend_KQueue_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(READABLE));
336
+ } else {
337
+ rb_sys_fail("Event_Backend_KQueue_io_read");
338
+ }
339
+ }
340
+
341
+ Event_Backend_resize_to_fit(arguments->buffer, arguments->offset, arguments->length);
342
+
343
+ return SIZET2NUM(total);
344
+ }
345
+
346
+ static
347
+ VALUE io_read_ensure(VALUE _arguments) {
348
+ struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
349
+
350
+ Event_Backend_nonblock_restore(arguments->descriptor, arguments->flags);
351
+
352
+ return Qnil;
353
+ }
354
+
355
+ VALUE Event_Backend_KQueue_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _offset, VALUE _length) {
356
+ struct Event_Backend_KQueue *data = NULL;
357
+ TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
358
+
359
+ int descriptor = RB_NUM2INT(rb_funcall(io, id_fileno, 0));
360
+
361
+ size_t offset = NUM2SIZET(_offset);
362
+ size_t length = NUM2SIZET(_length);
363
+
364
+ struct io_read_arguments io_read_arguments = {
365
+ .self = self,
366
+ .fiber = fiber,
367
+ .io = io,
368
+
369
+ .flags = Event_Backend_nonblock_set(descriptor),
370
+ .descriptor = descriptor,
371
+ .buffer = buffer,
372
+ .offset = offset,
373
+ .length = length,
374
+ };
375
+
376
+ return rb_ensure(io_read_loop, (VALUE)&io_read_arguments, io_read_ensure, (VALUE)&io_read_arguments);
377
+ }
378
+
379
+ struct io_write_arguments {
380
+ VALUE self;
381
+ VALUE fiber;
382
+ VALUE io;
383
+
384
+ int flags;
385
+
386
+ int descriptor;
387
+
388
+ VALUE buffer;
389
+ size_t offset;
390
+ size_t length;
391
+ };
392
+
393
+ static
394
+ VALUE io_write_loop(VALUE _arguments) {
395
+ struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;
396
+
397
+ size_t offset = arguments->offset;
398
+ size_t length = arguments->length;
399
+ size_t total = 0;
400
+
401
+ while (length > 0) {
402
+ char *buffer = Event_Backend_verify_size(arguments->buffer, offset, length);
403
+ ssize_t result = write(arguments->descriptor, buffer+offset, length);
404
+
405
+ if (result >= 0) {
406
+ length -= result;
407
+ offset += result;
408
+ total += result;
409
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
410
+ Event_Backend_KQueue_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(WRITABLE));
411
+ } else {
412
+ rb_sys_fail("Event_Backend_KQueue_io_write");
413
+ }
414
+ }
415
+
416
+ return SIZET2NUM(total);
417
+ };
418
+
419
+ static
420
+ VALUE io_write_ensure(VALUE _arguments) {
421
+ struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;
422
+
423
+ Event_Backend_nonblock_restore(arguments->descriptor, arguments->flags);
424
+
425
+ return Qnil;
426
+ };
427
+
428
+ VALUE Event_Backend_KQueue_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _offset, VALUE _length) {
429
+ struct Event_Backend_KQueue *data = NULL;
430
+ TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
431
+
432
+ int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
433
+
434
+ size_t offset = NUM2SIZET(_offset);
435
+ size_t length = NUM2SIZET(_length);
436
+
437
+ struct io_write_arguments io_write_arguments = {
438
+ .self = self,
439
+ .fiber = fiber,
440
+ .io = io,
441
+
442
+ .flags = Event_Backend_nonblock_set(descriptor),
443
+ .descriptor = descriptor,
444
+ .buffer = buffer,
445
+ .offset = offset,
446
+ .length = length,
447
+ };
448
+
449
+ return rb_ensure(io_write_loop, (VALUE)&io_write_arguments, io_write_ensure, (VALUE)&io_write_arguments);
450
+ }
451
+
304
452
  static
305
453
  struct timespec * make_timeout(VALUE duration, struct timespec * storage) {
306
454
  if (duration == Qnil) {
@@ -420,9 +568,12 @@ void Init_Event_Backend_KQueue(VALUE Event_Backend) {
420
568
 
421
569
  rb_define_alloc_func(Event_Backend_KQueue, Event_Backend_KQueue_allocate);
422
570
  rb_define_method(Event_Backend_KQueue, "initialize", Event_Backend_KQueue_initialize, 1);
571
+ rb_define_method(Event_Backend_KQueue, "select", Event_Backend_KQueue_select, 1);
423
572
  rb_define_method(Event_Backend_KQueue, "close", Event_Backend_KQueue_close, 0);
424
573
 
425
574
  rb_define_method(Event_Backend_KQueue, "io_wait", Event_Backend_KQueue_io_wait, 3);
426
- rb_define_method(Event_Backend_KQueue, "select", Event_Backend_KQueue_select, 1);
575
+ rb_define_method(Event_Backend_KQueue, "io_read", Event_Backend_KQueue_io_read, 5);
576
+ rb_define_method(Event_Backend_KQueue, "io_write", Event_Backend_KQueue_io_write, 5);
577
+
427
578
  rb_define_method(Event_Backend_KQueue, "process_wait", Event_Backend_KQueue_process_wait, 3);
428
579
  }
@@ -260,88 +260,98 @@ VALUE Event_Backend_URing_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE event
260
260
  return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
261
261
  }
262
262
 
263
- inline static
264
- void resize_to_capacity(VALUE string, size_t offset, size_t length) {
265
- size_t current_length = RSTRING_LEN(string);
266
- long difference = (long)(offset + length) - (long)current_length;
267
-
268
- difference += 1;
269
-
270
- if (difference > 0) {
271
- rb_str_modify_expand(string, difference);
272
- } else {
273
- rb_str_modify(string);
274
- }
275
- }
276
-
277
- inline static
278
- void resize_to_fit(VALUE string, size_t offset, size_t length) {
279
- size_t current_length = RSTRING_LEN(string);
280
-
281
- if (current_length < (offset + length)) {
282
- rb_str_set_len(string, offset + length);
283
- }
284
- }
285
-
286
- VALUE Event_Backend_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE offset, VALUE length) {
287
- struct Event_Backend_URing *data = NULL;
288
- TypedData_Get_Struct(self, struct Event_Backend_URing, &Event_Backend_URing_Type, data);
289
-
290
- resize_to_capacity(buffer, NUM2SIZET(offset), NUM2SIZET(length));
291
-
292
- int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
263
+ static
264
+ int io_read(struct Event_Backend_URing *data, VALUE fiber, int descriptor, char *buffer, size_t length) {
293
265
  struct io_uring_sqe *sqe = io_get_sqe(data);
294
266
  assert(sqe);
295
267
 
296
268
  struct iovec iovecs[1];
297
- iovecs[0].iov_base = RSTRING_PTR(buffer) + NUM2SIZET(offset);
298
- iovecs[0].iov_len = NUM2SIZET(length);
269
+ iovecs[0].iov_base = buffer;
270
+ iovecs[0].iov_len = length;
299
271
 
300
272
  io_uring_prep_readv(sqe, descriptor, iovecs, 1, 0);
301
273
  io_uring_sqe_set_data(sqe, (void*)fiber);
302
274
  io_uring_submit(&data->ring);
303
275
 
304
- // fprintf(stderr, "prep_readv(%p, %d, %ld)\n", sqe, descriptor, iovecs[0].iov_len);
305
-
306
- int result = NUM2INT(Event_Backend_transfer(data->loop));
307
-
308
- if (result < 0) {
309
- rb_syserr_fail(-result, strerror(-result));
310
- }
311
-
312
- resize_to_fit(buffer, NUM2SIZET(offset), (size_t)result);
313
-
314
- return INT2NUM(result);
276
+ return NUM2INT(Event_Backend_transfer(data->loop));
315
277
  }
316
278
 
317
- VALUE Event_Backend_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE offset, VALUE length) {
279
+ VALUE Event_Backend_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE _buffer, VALUE _offset, VALUE _length) {
318
280
  struct Event_Backend_URing *data = NULL;
319
281
  TypedData_Get_Struct(self, struct Event_Backend_URing, &Event_Backend_URing_Type, data);
320
282
 
321
- if ((size_t)RSTRING_LEN(buffer) < NUM2SIZET(offset) + NUM2SIZET(length)) {
322
- rb_raise(rb_eRuntimeError, "invalid offset/length exceeds bounds of buffer");
283
+ int descriptor = RB_NUM2INT(rb_funcall(io, id_fileno, 0));
284
+
285
+ size_t offset = NUM2SIZET(_offset);
286
+ size_t length = NUM2SIZET(_length);
287
+
288
+ size_t start = offset;
289
+ size_t total = 0;
290
+
291
+ while (length > 0) {
292
+ char *buffer = Event_Backend_resize_to_capacity(_buffer, offset, length);
293
+ int result = io_read(data, fiber, descriptor, buffer+offset, length);
294
+
295
+ if (result >= 0) {
296
+ offset += result;
297
+ length -= result;
298
+ total += result;
299
+ } else if (-result == EAGAIN || -result == EWOULDBLOCK) {
300
+ Event_Backend_URing_io_wait(self, fiber, io, RB_INT2NUM(READABLE));
301
+ } else {
302
+ rb_syserr_fail(-result, strerror(-result));
303
+ }
323
304
  }
324
305
 
325
- int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
306
+ Event_Backend_resize_to_fit(_buffer, start, total);
307
+
308
+ return SIZET2NUM(total);
309
+ }
310
+
311
+ static
312
+ int io_write(struct Event_Backend_URing *data, VALUE fiber, int descriptor, char *buffer, size_t length) {
326
313
  struct io_uring_sqe *sqe = io_get_sqe(data);
314
+ assert(sqe);
327
315
 
328
316
  struct iovec iovecs[1];
329
- iovecs[0].iov_base = RSTRING_PTR(buffer) + NUM2SIZET(offset);
330
- iovecs[0].iov_len = NUM2SIZET(length);
317
+ iovecs[0].iov_base = buffer;
318
+ iovecs[0].iov_len = length;
331
319
 
332
320
  io_uring_prep_writev(sqe, descriptor, iovecs, 1, 0);
333
321
  io_uring_sqe_set_data(sqe, (void*)fiber);
334
322
  io_uring_submit(&data->ring);
335
323
 
336
- // fprintf(stderr, "prep_writev(%p, %d, %ld)\n", sqe, descriptor, iovecs[0].iov_len);
324
+ return NUM2INT(Event_Backend_transfer(data->loop));
325
+ }
326
+
327
+ VALUE Event_Backend_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE _buffer, VALUE _offset, VALUE _length) {
328
+ struct Event_Backend_URing *data = NULL;
329
+ TypedData_Get_Struct(self, struct Event_Backend_URing, &Event_Backend_URing_Type, data);
330
+
331
+ int descriptor = RB_NUM2INT(rb_funcall(io, id_fileno, 0));
337
332
 
338
- int result = NUM2INT(Event_Backend_transfer(data->loop));
333
+ size_t offset = NUM2SIZET(_offset);
334
+ size_t length = NUM2SIZET(_length);
339
335
 
340
- if (result < 0) {
341
- rb_syserr_fail(-result, strerror(-result));
336
+ char *buffer = Event_Backend_verify_size(_buffer, offset, length);
337
+
338
+ size_t total = 0;
339
+
340
+ while (length > 0) {
341
+ int result = io_write(data, fiber, descriptor, buffer+offset, length);
342
+
343
+ if (result >= 0) {
344
+ length -= result;
345
+ offset += result;
346
+ total += result;
347
+ } else if (-result == EAGAIN || -result == EWOULDBLOCK) {
348
+ Event_Backend_URing_io_wait(self, fiber, io, RB_INT2NUM(WRITABLE));
349
+ } else {
350
+ rb_syserr_fail(-result, strerror(-result));
351
+ }
342
352
  }
343
353
 
344
- return INT2NUM(result);
354
+ return SIZET2NUM(total);
345
355
  }
346
356
 
347
357
  static
@@ -477,12 +487,12 @@ void Init_Event_Backend_URing(VALUE Event_Backend) {
477
487
 
478
488
  rb_define_alloc_func(Event_Backend_URing, Event_Backend_URing_allocate);
479
489
  rb_define_method(Event_Backend_URing, "initialize", Event_Backend_URing_initialize, 1);
490
+ rb_define_method(Event_Backend_URing, "select", Event_Backend_URing_select, 1);
480
491
  rb_define_method(Event_Backend_URing, "close", Event_Backend_URing_close, 0);
481
492
 
482
493
  rb_define_method(Event_Backend_URing, "io_wait", Event_Backend_URing_io_wait, 3);
483
- rb_define_method(Event_Backend_URing, "select", Event_Backend_URing_select, 1);
484
-
485
494
  rb_define_method(Event_Backend_URing, "io_read", Event_Backend_URing_io_read, 5);
486
495
  rb_define_method(Event_Backend_URing, "io_write", Event_Backend_URing_io_write, 5);
496
+
487
497
  rb_define_method(Event_Backend_URing, "process_wait", Event_Backend_URing_process_wait, 3);
488
498
  }
Binary file
data/ext/event/extconf.rb CHANGED
@@ -33,8 +33,7 @@ $CFLAGS << " -Wall"
33
33
  $srcs = ["event.c", "backend/backend.c"]
34
34
  $VPATH << "$(srcdir)/backend"
35
35
 
36
- # have_func('rb_fiber_transfer')
37
- have_func('rb_fiber_transfer_kw')
36
+ have_func('&rb_fiber_transfer')
38
37
 
39
38
  if have_library('uring') and have_header('liburing.h')
40
39
  $srcs << "backend/uring.c"
data/ext/event/kqueue.o CHANGED
Binary file
data/ext/event/mkmf.log CHANGED
@@ -1,4 +1,4 @@
1
- have_func: checking for rb_fiber_transfer_kw()... -------------------- no
1
+ have_func: checking for &rb_fiber_transfer()... -------------------- no
2
2
 
3
3
  "clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/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.1/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
4
  checked program was:
@@ -12,9 +12,9 @@ checked program was:
12
12
  /* end */
13
13
 
14
14
  "clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/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.1/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 "
15
- conftest.c:14:57: error: use of undeclared identifier 'rb_fiber_transfer_kw'
16
- int t(void) { void ((*volatile p)()); p = (void ((*)()))rb_fiber_transfer_kw; return !p; }
17
- ^
15
+ conftest.c:14:76: error: use of undeclared identifier 'rb_fiber_transfer'
16
+ int t(void) { const volatile void *volatile p; p = (const volatile void *)&rb_fiber_transfer; return !p; }
17
+ ^
18
18
  1 error generated.
19
19
  checked program was:
20
20
  /* begin */
@@ -31,32 +31,7 @@ checked program was:
31
31
  11:
32
32
  12: return !!argv[argc];
33
33
  13: }
34
- 14: int t(void) { void ((*volatile p)()); p = (void ((*)()))rb_fiber_transfer_kw; return !p; }
35
- /* end */
36
-
37
- "clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/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.1/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 "
38
- Undefined symbols for architecture x86_64:
39
- "_rb_fiber_transfer_kw", referenced from:
40
- _t in conftest-3b7f21.o
41
- ld: symbol(s) not found for architecture x86_64
42
- clang: error: linker command failed with exit code 1 (use -v to see invocation)
43
- checked program was:
44
- /* begin */
45
- 1: #include "ruby.h"
46
- 2:
47
- 3: /*top*/
48
- 4: extern int t(void);
49
- 5: int main(int argc, char **argv)
50
- 6: {
51
- 7: if (argc > 1000000) {
52
- 8: int (* volatile tp)(void)=(int (*)(void))&t;
53
- 9: printf("%d", (*tp)());
54
- 10: }
55
- 11:
56
- 12: return !!argv[argc];
57
- 13: }
58
- 14: extern void rb_fiber_transfer_kw();
59
- 15: int t(void) { rb_fiber_transfer_kw(); return 0; }
34
+ 14: int t(void) { const volatile void *volatile p; p = (const volatile void *)&rb_fiber_transfer; return !p; }
60
35
  /* end */
61
36
 
62
37
  --------------------
@@ -52,7 +52,50 @@ module Event
52
52
  @readable.delete(io) if remove_readable
53
53
  @writable.delete(io) if remove_writable
54
54
  end
55
-
55
+
56
+ def io_read(fiber, io, buffer, offset, length)
57
+ buffer.force_encoding(Encoding::BINARY)
58
+
59
+ while length > 0
60
+ case result = io.read_nonblock(length, exception: false)
61
+ when :wait_readable
62
+ self.io_wait(fiber, io, READABLE)
63
+ when :wait_writable
64
+ self.io_wait(fiber, io, WRITABLE)
65
+ else
66
+ result.force_encoding(Encoding::BINARY)
67
+ buffer[offset, result.bytesize] = result
68
+
69
+ offset += result.bytesize
70
+ length -= result.bytesize
71
+ end
72
+ end
73
+ rescue EOFError
74
+ return nil
75
+ end
76
+
77
+ def io_write(fiber, io, buffer, offset, length)
78
+ buffer.force_encoding(Encoding::BINARY)
79
+
80
+ total = 0
81
+
82
+ while length > 0
83
+ chunk = buffer[offset, length]
84
+ case result = io.write_nonblock(chunk, exception: false)
85
+ when :wait_readable
86
+ self.io_wait(fiber, io, READABLE)
87
+ when :wait_writable
88
+ self.io_wait(fiber, io, WRITABLE)
89
+ else
90
+ offset += result
91
+ length -= result
92
+ total += result
93
+ end
94
+ end
95
+
96
+ return total
97
+ end
98
+
56
99
  def process_wait(fiber, pid, flags)
57
100
  r, w = IO.pipe
58
101
 
data/lib/event/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Event
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
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.5.0
4
+ version: 0.6.0
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-06-12 00:00:00.000000000 Z
11
+ date: 2021-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bake