io-event 0.2.6 → 0.3.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: 2ac87cae13b6195eaa78351aff579000e12c3d9ed982d8202af4d745996a7a76
4
- data.tar.gz: 1289b6e2f4c72ec34d5cdcb1565f5a9a96135a271a33370ac57ad958e4574da1
3
+ metadata.gz: 5ea156f474e12257bd5b2db77f8f647d8291a0e4fd6c3d78914e1f26abd35c52
4
+ data.tar.gz: fe0ebd9fce449827c06faf4d59d2c1ca86e62e9ccdbada21389646cd2133d7f6
5
5
  SHA512:
6
- metadata.gz: ecfb2339742c8f6bcfcdb1d263a3355a6a28d417d626a37c1ba20f68425b8cb4fe597a04b7b3464a09fd201192d0e23957393fc7975f09a29399eb9429096b74
7
- data.tar.gz: 9690bdf7559834e9e3c5345c42fa8447188c5f2ee6a65983371432f3ffc69c1e5837f0364b57040e5e7a32f582b1d19580eb6c01d710951fa794953a2fc41079
6
+ metadata.gz: ca948d973ad94bfbb9b6c166741e5cb5cd75439bfb47d07809a8d41fdecebdf4e9df9f0862aaa716ad444ab5ab9bf4b1cc1204698a5e7bd1a7f0ae6465c0dba2
7
+ data.tar.gz: 1e27d5073302b93a1ef9d5b51c6f8a5945546cc95e2b54b0985a746fc2810318c5c4c0f1b5cbc20686f277362cf197d2162a4f95d2b4bec2ee00e11f84ed2b1a
data/ext/IO_Event.bundle CHANGED
Binary file
@@ -370,27 +370,24 @@ VALUE io_read_loop(VALUE _arguments) {
370
370
  size_t offset = 0;
371
371
  size_t length = arguments->length;
372
372
 
373
- while (length > 0) {
373
+ while (true) {
374
374
  size_t maximum_size = size - offset;
375
375
  ssize_t result = read(arguments->descriptor, (char*)base+offset, maximum_size);
376
376
 
377
- if (result == 0) {
378
- break;
379
- } else if (result > 0) {
377
+ if (result > 0) {
380
378
  offset += result;
381
-
382
- // Ensure we don't underflow length:
383
- if ((size_t)result < length)
384
- length -= result;
385
- else break;
386
- } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
379
+ if ((size_t)result >= length) break;
380
+ length -= result;
381
+ } else if (result == 0) {
382
+ break;
383
+ } else if (length > 0 && IO_Event_try_again(-result)) {
387
384
  IO_Event_Selector_EPoll_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(IO_EVENT_READABLE));
388
385
  } else {
389
- rb_sys_fail("IO_Event_Selector_EPoll_io_read:read");
386
+ return rb_fiber_scheduler_io_result(-1, -result);
390
387
  }
391
388
  }
392
389
 
393
- return SIZET2NUM(offset);
390
+ return rb_fiber_scheduler_io_result(offset, 0);
394
391
  }
395
392
 
396
393
  static
@@ -449,22 +446,24 @@ VALUE io_write_loop(VALUE _arguments) {
449
446
  rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
450
447
  }
451
448
 
452
- while (length > 0) {
453
- ssize_t result = write(arguments->descriptor, (char*)base+offset, length);
449
+ while (true) {
450
+ size_t maximum_size = size - offset;
451
+ ssize_t result = write(arguments->descriptor, (char*)base+offset, maximum_size);
454
452
 
455
- if (result >= 0) {
453
+ if (result > 0) {
456
454
  offset += result;
457
-
458
- // Result must always be <= than length:
455
+ if ((size_t)result >= length) break;
459
456
  length -= result;
460
- } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
457
+ } else if (result == 0) {
458
+ break;
459
+ } else if (length > 0 && IO_Event_try_again(errno)) {
461
460
  IO_Event_Selector_EPoll_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(IO_EVENT_WRITABLE));
462
461
  } else {
463
- rb_sys_fail("IO_Event_Selector_EPoll_io_write:write");
462
+ return rb_fiber_scheduler_io_result(-1, errno);
464
463
  }
465
464
  }
466
465
 
467
- return SIZET2NUM(offset);
466
+ return rb_fiber_scheduler_io_result(offset, 0);
468
467
  };
469
468
 
470
469
  static
@@ -26,6 +26,13 @@
26
26
  #include <time.h>
27
27
  #include <errno.h>
28
28
 
29
+ enum {
30
+ DEBUG = 0,
31
+ DEBUG_IO_READ = 0,
32
+ DEBUG_IO_WRITE = 0,
33
+ DEBUG_IO_WAIT = 0
34
+ };
35
+
29
36
  static VALUE IO_Event_Selector_KQueue = Qnil;
30
37
 
31
38
  enum {KQUEUE_MAX_EVENTS = 64};
@@ -363,6 +370,8 @@ VALUE IO_Event_Selector_KQueue_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE
363
370
  .descriptor = descriptor,
364
371
  };
365
372
 
373
+ if (DEBUG_IO_WAIT) fprintf(stderr, "IO_Event_Selector_KQueue_io_wait descriptor=%d\n", descriptor);
374
+
366
375
  return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
367
376
  }
368
377
 
@@ -392,27 +401,31 @@ VALUE io_read_loop(VALUE _arguments) {
392
401
  size_t offset = 0;
393
402
  size_t length = arguments->length;
394
403
 
395
- while (length > 0) {
404
+ if (DEBUG_IO_READ) fprintf(stderr, "io_read_loop(fd=%d, length=%zu)\n", arguments->descriptor, length);
405
+
406
+ while (true) {
396
407
  size_t maximum_size = size - offset;
408
+ if (DEBUG_IO_READ) fprintf(stderr, "read(%d, +%ld, %ld)\n", arguments->descriptor, offset, maximum_size);
397
409
  ssize_t result = read(arguments->descriptor, (char*)base+offset, maximum_size);
410
+ if (DEBUG_IO_READ) fprintf(stderr, "read(%d, +%ld, %ld) -> %lld\n", arguments->descriptor, offset, maximum_size, result);
398
411
 
399
- if (result == 0) {
400
- break;
401
- } else if (result > 0) {
412
+ if (result > 0) {
402
413
  offset += result;
403
-
404
- // Ensure we don't underflow length:
405
- if ((size_t)result < length)
406
- length -= result;
407
- else break;
408
- } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
414
+ if ((size_t)result >= length) break;
415
+ length -= result;
416
+ } else if (result == 0) {
417
+ break;
418
+ } else if (length > 0 && IO_Event_try_again(errno)) {
419
+ if (DEBUG_IO_READ) fprintf(stderr, "IO_Event_Selector_KQueue_io_wait(fd=%d, length=%zu)\n", arguments->descriptor, length);
409
420
  IO_Event_Selector_KQueue_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(IO_EVENT_READABLE));
410
421
  } else {
411
- rb_sys_fail("IO_Event_Selector_KQueue_io_read:read");
422
+ if (DEBUG_IO_READ) fprintf(stderr, "io_read_loop(fd=%d, length=%zu) -> errno=%d\n", arguments->descriptor, length, errno);
423
+ return rb_fiber_scheduler_io_result(-1, errno);
412
424
  }
413
425
  }
414
426
 
415
- return SIZET2NUM(offset);
427
+ if (DEBUG_IO_READ) fprintf(stderr, "io_read_loop(fd=%d, length=%zu) -> %zu\n", arguments->descriptor, length, offset);
428
+ return rb_fiber_scheduler_io_result(offset, 0);
416
429
  }
417
430
 
418
431
  static
@@ -474,22 +487,31 @@ VALUE io_write_loop(VALUE _arguments) {
474
487
  rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
475
488
  }
476
489
 
477
- while (length > 0) {
478
- ssize_t result = write(arguments->descriptor, (char*)base+offset, length);
490
+ if (DEBUG_IO_WRITE) fprintf(stderr, "io_write_loop(fd=%d, length=%zu)\n", arguments->descriptor, length);
491
+
492
+ while (true) {
493
+ size_t maximum_size = size - offset;
494
+ if (DEBUG_IO_WRITE) fprintf(stderr, "write(%d, +%ld, %ld, length=%zu)\n", arguments->descriptor, offset, maximum_size, length);
495
+ ssize_t result = write(arguments->descriptor, (char*)base+offset, maximum_size);
496
+ if (DEBUG_IO_WRITE) fprintf(stderr, "write(%d, +%ld, %ld) -> %lld\n", arguments->descriptor, offset, maximum_size, result);
479
497
 
480
- if (result >= 0) {
498
+ if (result > 0) {
481
499
  offset += result;
482
-
483
- // Result must always be <= than length:
500
+ if ((size_t)result >= length) break;
484
501
  length -= result;
485
- } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
486
- IO_Event_Selector_KQueue_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(IO_EVENT_WRITABLE));
502
+ } else if (result == 0) {
503
+ break;
504
+ } else if (length > 0 && IO_Event_try_again(errno)) {
505
+ if (DEBUG_IO_WRITE) fprintf(stderr, "IO_Event_Selector_KQueue_io_wait(fd=%d, length=%zu)\n", arguments->descriptor, length);
506
+ IO_Event_Selector_KQueue_io_wait(arguments->self, arguments->fiber, arguments->io, RB_INT2NUM(IO_EVENT_READABLE));
487
507
  } else {
488
- rb_sys_fail("IO_Event_Selector_KQueue_io_write:write");
508
+ if (DEBUG_IO_WRITE) fprintf(stderr, "io_write_loop(fd=%d, length=%zu) -> errno=%d\n", arguments->descriptor, length, errno);
509
+ return rb_fiber_scheduler_io_result(-1, errno);
489
510
  }
490
511
  }
491
512
 
492
- return SIZET2NUM(offset);
513
+ if (DEBUG_IO_READ) fprintf(stderr, "io_write_loop(fd=%d, length=%zu) -> %zu\n", arguments->descriptor, length, offset);
514
+ return rb_fiber_scheduler_io_result(offset, 0);
493
515
  };
494
516
 
495
517
  static
@@ -620,7 +642,9 @@ VALUE IO_Event_Selector_KQueue_select(VALUE self, VALUE duration) {
620
642
  // Non-comprehensive testing shows this gives a 1.5x speedup.
621
643
 
622
644
  // First do the syscall with no timeout to get any immediately available events:
645
+ if (DEBUG) fprintf(stderr, "\r\nselect_internal_with_gvl timeout=" PRINTF_TIMESPEC "\r\n", PRINTF_TIMESPEC_ARGS(arguments.storage));
623
646
  select_internal_with_gvl(&arguments);
647
+ if (DEBUG) fprintf(stderr, "\r\nselect_internal_with_gvl done\r\n");
624
648
 
625
649
  // If we:
626
650
  // 1. Didn't process any ready fibers, and
@@ -633,6 +657,7 @@ VALUE IO_Event_Selector_KQueue_select(VALUE self, VALUE duration) {
633
657
  if (!timeout_nonblocking(arguments.timeout)) {
634
658
  arguments.count = KQUEUE_MAX_EVENTS;
635
659
 
660
+ if (DEBUG) fprintf(stderr, "IO_Event_Selector_KQueue_select timeout=" PRINTF_TIMESPEC "\n", PRINTF_TIMESPEC_ARGS(arguments.storage));
636
661
  select_internal_without_gvl(&arguments);
637
662
  }
638
663
  }
@@ -26,6 +26,7 @@
26
26
 
27
27
  #ifdef HAVE_RUBY_IO_BUFFER_H
28
28
  #include <ruby/io/buffer.h>
29
+ #include <ruby/fiber/scheduler.h>
29
30
  #endif
30
31
 
31
32
  #include <time.h>
@@ -40,6 +41,10 @@ enum IO_Event {
40
41
 
41
42
  void Init_IO_Event_Selector();
42
43
 
44
+ static inline int IO_Event_try_again(int error) {
45
+ return error == EAGAIN || error == EWOULDBLOCK;
46
+ }
47
+
43
48
  VALUE IO_Event_Selector_fiber_transfer(VALUE fiber, int argc, VALUE *argv);
44
49
 
45
50
  #ifdef HAVE__RB_FIBER_RAISE
@@ -396,27 +396,24 @@ VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
396
396
  size_t offset = 0;
397
397
  size_t length = NUM2SIZET(_length);
398
398
 
399
- while (length > 0) {
399
+ while (true) {
400
400
  size_t maximum_size = size - offset;
401
401
  int result = io_read(data, fiber, descriptor, (char*)base+offset, maximum_size);
402
402
 
403
- if (result == 0) {
404
- break;
405
- } else if (result > 0) {
403
+ if (result > 0) {
406
404
  offset += result;
407
-
408
- // Ensure we don't underflow length:
409
- if ((size_t)result < length)
410
- length -= result;
411
- else break;
412
- } else if (-result == EAGAIN || -result == EWOULDBLOCK) {
405
+ if ((size_t)result >= length) break;
406
+ length -= result;
407
+ } else if (result == 0) {
408
+ break;
409
+ } else if (length > 0 && IO_Event_try_again(-result)) {
413
410
  IO_Event_Selector_URing_io_wait(self, fiber, io, RB_INT2NUM(IO_EVENT_READABLE));
414
411
  } else {
415
- rb_syserr_fail(-result, strerror(-result));
412
+ return rb_fiber_scheduler_io_result(-1, -result);
416
413
  }
417
414
  }
418
415
 
419
- return SIZET2NUM(offset);
416
+ return rb_fiber_scheduler_io_result(offset, 0);
420
417
  }
421
418
 
422
419
  static
@@ -452,21 +449,24 @@ VALUE IO_Event_Selector_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
452
449
  rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
453
450
  }
454
451
 
455
- while (length > 0) {
456
- int result = io_write(data, fiber, descriptor, (char*)base+offset, length);
452
+ while (true) {
453
+ size_t maximum_size = size - offset;
454
+ int result = io_write(data, fiber, descriptor, (char*)base+offset, maximum_size);
457
455
 
458
- if (result >= 0) {
456
+ if (result > 0) {
459
457
  offset += result;
460
458
  if ((size_t)result >= length) break;
461
459
  length -= result;
462
- } else if (-result == EAGAIN || -result == EWOULDBLOCK) {
460
+ } else if (result == 0) {
461
+ break;
462
+ } else if (length > 0 && IO_Event_try_again(-result)) {
463
463
  IO_Event_Selector_URing_io_wait(self, fiber, io, RB_INT2NUM(IO_EVENT_WRITABLE));
464
464
  } else {
465
- rb_syserr_fail(-result, strerror(-result));
465
+ return rb_fiber_scheduler_io_result(-1, -result);
466
466
  }
467
467
  }
468
468
 
469
- return SIZET2NUM(offset);
469
+ return rb_fiber_scheduler_io_result(offset, 0);
470
470
  }
471
471
 
472
472
  #endif
data/ext/kqueue.o CHANGED
Binary file
@@ -134,25 +134,36 @@ module IO::Event
134
134
  end
135
135
 
136
136
  if IO.const_defined?(:Buffer)
137
+ EAGAIN = Errno::EAGAIN::Errno
138
+
137
139
  def io_read(fiber, io, buffer, length)
138
140
  offset = 0
139
141
 
140
- while length > 0
141
- # The maximum size we can read:
142
+ while true
142
143
  maximum_size = buffer.size - offset
143
144
 
144
145
  case result = blocking{io.read_nonblock(maximum_size, exception: false)}
145
146
  when :wait_readable
146
- self.io_wait(fiber, io, IO::READABLE)
147
+ if length > 0
148
+ self.io_wait(fiber, io, IO::READABLE)
149
+ else
150
+ return -EAGAIN
151
+ end
147
152
  when :wait_writable
148
- self.io_wait(fiber, io, IO::WRITABLE)
153
+ if length > 0
154
+ self.io_wait(fiber, io, IO::WRITABLE)
155
+ else
156
+ return -EAGAIN
157
+ end
149
158
  else
150
159
  break unless result
151
160
 
152
161
  buffer.copy(result, offset)
153
162
 
154
- offset += result.bytesize
155
- length -= result.bytesize
163
+ size = result.bytesize
164
+ offset += size
165
+ break if size >= length
166
+ length -= size
156
167
  end
157
168
  end
158
169
 
@@ -162,16 +173,26 @@ module IO::Event
162
173
  def io_write(fiber, io, buffer, length)
163
174
  offset = 0
164
175
 
165
- while length > 0
166
- # From offset until the end:
167
- chunk = buffer.to_str(offset, length)
176
+ while true
177
+ maximum_size = buffer.size - offset
178
+
179
+ chunk = buffer.to_str(offset, maximum_size)
168
180
  case result = blocking{io.write_nonblock(chunk, exception: false)}
169
181
  when :wait_readable
170
- self.io_wait(fiber, io, IO::READABLE)
182
+ if length > 0
183
+ self.io_wait(fiber, io, IO::READABLE)
184
+ else
185
+ return -EAGAIN
186
+ end
171
187
  when :wait_writable
172
- self.io_wait(fiber, io, IO::WRITABLE)
188
+ if length > 0
189
+ self.io_wait(fiber, io, IO::WRITABLE)
190
+ else
191
+ return -EAGAIN
192
+ end
173
193
  else
174
194
  offset += result
195
+ break if result >= length
175
196
  length -= result
176
197
  end
177
198
  end
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module IO::Event
22
- VERSION = "0.2.6"
22
+ VERSION = "0.3.0"
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-event
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.3.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-12-16 00:00:00.000000000 Z
11
+ date: 2021-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bake
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.5'
61
+ version: '0.6'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.5'
68
+ version: '0.6'
69
69
  description:
70
70
  email:
71
71
  executables: []