event 0.5.0 → 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: 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