io-event 0.2.6 → 0.3.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: 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: []