polyphony 0.82 → 0.84.1

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.
@@ -14,7 +14,7 @@
14
14
  #include <errno.h>
15
15
 
16
16
  #include "polyphony.h"
17
- #include "../liburing/liburing.h"
17
+ #include "liburing.h"
18
18
  #include "backend_io_uring_context.h"
19
19
  #include "ruby/thread.h"
20
20
  #include "ruby/io.h"
@@ -304,7 +304,7 @@ int io_uring_backend_defer_submit_and_await(
304
304
  // op was not completed (an exception was raised), so we need to cancel it
305
305
  ctx->result = -ECANCELED;
306
306
  sqe = io_uring_get_sqe(&backend->ring);
307
- io_uring_prep_cancel(sqe, ctx, 0);
307
+ io_uring_prep_cancel(sqe, (__u64)ctx, 0);
308
308
  backend->pending_sqes = 0;
309
309
  io_uring_submit(&backend->ring);
310
310
  }
@@ -329,8 +329,26 @@ VALUE io_uring_backend_wait_fd(Backend_t *backend, int fd, int write) {
329
329
  return resumed_value;
330
330
  }
331
331
 
332
+ static inline int fd_from_io(VALUE io, rb_io_t **fptr, int write_mode, int rectify_file_pos) {
333
+ if (rb_obj_class(io) == cPipe) {
334
+ *fptr = NULL;
335
+ return Pipe_get_fd(io, write_mode);
336
+ }
337
+ else {
338
+ VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
339
+ if (underlying_io != Qnil) io = underlying_io;
340
+
341
+ GetOpenFile(io, *fptr);
342
+ io_unset_nonblock(*fptr, io);
343
+ if (rectify_file_pos) rectify_io_file_pos(*fptr);
344
+
345
+ return (*fptr)->fd;
346
+ }
347
+ }
348
+
332
349
  VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos) {
333
350
  Backend_t *backend;
351
+ int fd;
334
352
  rb_io_t *fptr;
335
353
  struct io_buffer buffer = get_io_buffer(str);
336
354
  long buf_pos = NUM2INT(pos);
@@ -338,7 +356,6 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
338
356
  int expandable_buffer = 0;
339
357
  long total = 0;
340
358
  int read_to_eof = RTEST(to_eof);
341
- VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
342
359
 
343
360
  if (buffer.raw) {
344
361
  if (buf_pos < 0 || buf_pos > buffer.len) buf_pos = buffer.len;
@@ -365,11 +382,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
365
382
  }
366
383
 
367
384
  GetBackend(self, backend);
368
- if (underlying_io != Qnil) io = underlying_io;
369
- GetOpenFile(io, fptr);
370
- rb_io_check_byte_readable(fptr);
371
- io_unset_nonblock(fptr, io);
372
- rectify_io_file_pos(fptr);
385
+ fd = fd_from_io(io, &fptr, 0, 1);
373
386
 
374
387
  while (1) {
375
388
  VALUE resume_value = Qnil;
@@ -378,7 +391,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
378
391
  int result;
379
392
  int completed;
380
393
 
381
- io_uring_prep_read(sqe, fptr->fd, buffer.ptr, buffer.len, -1);
394
+ io_uring_prep_read(sqe, fd, buffer.ptr, buffer.len, -1);
382
395
 
383
396
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
384
397
  completed = context_store_release(&backend->store, ctx);
@@ -417,7 +430,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
417
430
 
418
431
  if (!buffer.raw) {
419
432
  io_set_read_length(str, buf_pos + total, shrinkable_string);
420
- io_enc_str(str, fptr);
433
+ if (fptr) io_enc_str(str, fptr);
421
434
  }
422
435
  if (!total) return Qnil;
423
436
 
@@ -426,22 +439,18 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
426
439
 
427
440
  VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
428
441
  Backend_t *backend;
442
+ int fd;
429
443
  rb_io_t *fptr;
430
444
  VALUE str;
431
445
  long total;
432
446
  long len = NUM2INT(maxlen);
433
447
  int shrinkable;
434
448
  char *buf;
435
- VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
436
449
 
437
450
  READ_LOOP_PREPARE_STR();
438
451
 
439
452
  GetBackend(self, backend);
440
- if (underlying_io != Qnil) io = underlying_io;
441
- GetOpenFile(io, fptr);
442
- rb_io_check_byte_readable(fptr);
443
- io_unset_nonblock(fptr, io);
444
- rectify_io_file_pos(fptr);
453
+ fd = fd_from_io(io, &fptr, 0, 1);
445
454
 
446
455
  while (1) {
447
456
  VALUE resume_value = Qnil;
@@ -450,7 +459,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
450
459
  ssize_t result;
451
460
  int completed;
452
461
 
453
- io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
462
+ io_uring_prep_read(sqe, fd, buf, len, -1);
454
463
 
455
464
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
456
465
  completed = context_store_release(&backend->store, ctx);
@@ -478,23 +487,19 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
478
487
 
479
488
  VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
480
489
  Backend_t *backend;
490
+ int fd;
481
491
  rb_io_t *fptr;
482
492
  VALUE str;
483
493
  long total;
484
494
  long len = 8192;
485
495
  int shrinkable;
486
496
  char *buf;
487
- VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
488
497
  ID method_id = SYM2ID(method);
489
498
 
490
499
  READ_LOOP_PREPARE_STR();
491
500
 
492
501
  GetBackend(self, backend);
493
- if (underlying_io != Qnil) io = underlying_io;
494
- GetOpenFile(io, fptr);
495
- rb_io_check_byte_readable(fptr);
496
- io_unset_nonblock(fptr, io);
497
- rectify_io_file_pos(fptr);
502
+ fd = fd_from_io(io, &fptr, 0, 1);
498
503
 
499
504
  while (1) {
500
505
  VALUE resume_value = Qnil;
@@ -503,7 +508,7 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
503
508
  ssize_t result;
504
509
  int completed;
505
510
 
506
- io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
511
+ io_uring_prep_read(sqe, fd, buf, len, -1);
507
512
 
508
513
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
509
514
  completed = context_store_release(&backend->store, ctx);
@@ -531,18 +536,14 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
531
536
 
532
537
  VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
533
538
  Backend_t *backend;
539
+ int fd;
534
540
  rb_io_t *fptr;
535
- VALUE underlying_io;
536
541
 
537
542
  struct io_buffer buffer = get_io_buffer(str);
538
543
  long left = buffer.len;
539
544
 
540
- underlying_io = rb_ivar_get(io, ID_ivar_io);
541
- if (underlying_io != Qnil) io = underlying_io;
542
545
  GetBackend(self, backend);
543
- io = rb_io_get_write_io(io);
544
- GetOpenFile(io, fptr);
545
- io_unset_nonblock(fptr, io);
546
+ fd = fd_from_io(io, &fptr, 1, 0);
546
547
 
547
548
  while (left > 0) {
548
549
  VALUE resume_value = Qnil;
@@ -551,7 +552,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
551
552
  int result;
552
553
  int completed;
553
554
 
554
- io_uring_prep_write(sqe, fptr->fd, buffer.ptr, left, 0);
555
+ io_uring_prep_write(sqe, fd, buffer.ptr, left, 0);
555
556
 
556
557
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
557
558
  completed = context_store_release(&backend->store, ctx);
@@ -575,20 +576,16 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
575
576
 
576
577
  VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
577
578
  Backend_t *backend;
579
+ int fd;
578
580
  rb_io_t *fptr;
579
- VALUE underlying_io;
580
581
  long total_length = 0;
581
582
  long total_written = 0;
582
583
  struct iovec *iov = 0;
583
584
  struct iovec *iov_ptr = 0;
584
585
  int iov_count = argc;
585
586
 
586
- underlying_io = rb_ivar_get(io, ID_ivar_io);
587
- if (underlying_io != Qnil) io = underlying_io;
588
587
  GetBackend(self, backend);
589
- io = rb_io_get_write_io(io);
590
- GetOpenFile(io, fptr);
591
- io_unset_nonblock(fptr, io);
588
+ fd = fd_from_io(io, &fptr, 1, 0);
592
589
 
593
590
  iov = malloc(iov_count * sizeof(struct iovec));
594
591
  for (int i = 0; i < argc; i++) {
@@ -606,7 +603,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
606
603
  int result;
607
604
  int completed;
608
605
 
609
- io_uring_prep_writev(sqe, fptr->fd, iov_ptr, iov_count, -1);
606
+ io_uring_prep_writev(sqe, fd, iov_ptr, iov_count, -1);
610
607
 
611
608
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
612
609
  completed = context_store_release(&backend->store, ctx);
@@ -656,13 +653,13 @@ VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
656
653
 
657
654
  VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
658
655
  Backend_t *backend;
656
+ int fd;
659
657
  rb_io_t *fptr;
660
658
  struct io_buffer buffer = get_io_buffer(str);
661
659
  long buf_pos = NUM2INT(pos);
662
660
  int shrinkable_string = 0;
663
661
  int expandable_buffer = 0;
664
662
  long total = 0;
665
- VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
666
663
 
667
664
  if (buffer.raw) {
668
665
  if (buf_pos < 0 || buf_pos > buffer.len) buf_pos = buffer.len;
@@ -689,11 +686,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
689
686
  }
690
687
 
691
688
  GetBackend(self, backend);
692
- if (underlying_io != Qnil) io = underlying_io;
693
- GetOpenFile(io, fptr);
694
- rb_io_check_byte_readable(fptr);
695
- io_unset_nonblock(fptr, io);
696
- rectify_io_file_pos(fptr);
689
+ fd = fd_from_io(io, &fptr, 0, 0);
697
690
 
698
691
  while (1) {
699
692
  VALUE resume_value = Qnil;
@@ -702,7 +695,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
702
695
  int result;
703
696
  int completed;
704
697
 
705
- io_uring_prep_recv(sqe, fptr->fd, buffer.ptr, buffer.len, 0);
698
+ io_uring_prep_recv(sqe, fd, buffer.ptr, buffer.len, 0);
706
699
 
707
700
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
708
701
  completed = context_store_release(&backend->store, ctx);
@@ -723,7 +716,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
723
716
 
724
717
  if (!buffer.raw) {
725
718
  io_set_read_length(str, buf_pos + total, shrinkable_string);
726
- io_enc_str(str, fptr);
719
+ if (fptr) io_enc_str(str, fptr);
727
720
  }
728
721
  if (!total) return Qnil;
729
722
 
@@ -732,22 +725,18 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
732
725
 
733
726
  VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
734
727
  Backend_t *backend;
728
+ int fd;
735
729
  rb_io_t *fptr;
736
730
  VALUE str;
737
731
  long total;
738
732
  long len = NUM2INT(maxlen);
739
733
  int shrinkable;
740
734
  char *buf;
741
- VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
742
735
 
743
736
  READ_LOOP_PREPARE_STR();
744
737
 
745
738
  GetBackend(self, backend);
746
- if (underlying_io != Qnil) io = underlying_io;
747
- GetOpenFile(io, fptr);
748
- rb_io_check_byte_readable(fptr);
749
- io_unset_nonblock(fptr, io);
750
- rectify_io_file_pos(fptr);
739
+ fd = fd_from_io(io, &fptr, 0, 0);
751
740
 
752
741
  while (1) {
753
742
  VALUE resume_value = Qnil;
@@ -756,7 +745,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
756
745
  int result;
757
746
  int completed;
758
747
 
759
- io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
748
+ io_uring_prep_recv(sqe, fd, buf, len, 0);
760
749
 
761
750
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
762
751
  completed = context_store_release(&backend->store, ctx);
@@ -783,23 +772,19 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
783
772
 
784
773
  VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
785
774
  Backend_t *backend;
775
+ int fd;
786
776
  rb_io_t *fptr;
787
777
  VALUE str;
788
778
  long total;
789
779
  long len = 8192;
790
780
  int shrinkable;
791
781
  char *buf;
792
- VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
793
782
  ID method_id = SYM2ID(method);
794
783
 
795
784
  READ_LOOP_PREPARE_STR();
796
785
 
797
786
  GetBackend(self, backend);
798
- if (underlying_io != Qnil) io = underlying_io;
799
- GetOpenFile(io, fptr);
800
- rb_io_check_byte_readable(fptr);
801
- io_unset_nonblock(fptr, io);
802
- rectify_io_file_pos(fptr);
787
+ fd = fd_from_io(io, &fptr, 0, 0);
803
788
 
804
789
  while (1) {
805
790
  VALUE resume_value = Qnil;
@@ -808,7 +793,7 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method)
808
793
  int result;
809
794
  int completed;
810
795
 
811
- io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
796
+ io_uring_prep_recv(sqe, fd, buf, len, 0);
812
797
 
813
798
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
814
799
  completed = context_store_release(&backend->store, ctx);
@@ -835,19 +820,15 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method)
835
820
 
836
821
  VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
837
822
  Backend_t *backend;
823
+ int fd;
838
824
  rb_io_t *fptr;
839
- VALUE underlying_io;
840
825
 
841
826
  struct io_buffer buffer = get_io_buffer(str);
842
827
  long left = buffer.len;
843
828
  int flags_int = NUM2INT(flags);
844
829
 
845
- underlying_io = rb_ivar_get(io, ID_ivar_io);
846
- if (underlying_io != Qnil) io = underlying_io;
847
830
  GetBackend(self, backend);
848
- io = rb_io_get_write_io(io);
849
- GetOpenFile(io, fptr);
850
- io_unset_nonblock(fptr, io);
831
+ fd = fd_from_io(io, &fptr, 1, 0);
851
832
 
852
833
  while (left > 0) {
853
834
  VALUE resume_value = Qnil;
@@ -856,7 +837,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
856
837
  int result;
857
838
  int completed;
858
839
 
859
- io_uring_prep_send(sqe, fptr->fd, buffer.ptr, left, flags_int);
840
+ io_uring_prep_send(sqe, fd, buffer.ptr, left, flags_int);
860
841
 
861
842
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
862
843
  completed = context_store_release(&backend->store, ctx);
@@ -879,15 +860,13 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
879
860
  }
880
861
 
881
862
  VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE socket_class, int loop) {
882
- rb_io_t *fptr;
863
+ int server_fd;
864
+ rb_io_t *server_fptr;
883
865
  struct sockaddr addr;
884
866
  socklen_t len = (socklen_t)sizeof addr;
885
867
  VALUE socket = Qnil;
886
- VALUE underlying_sock = rb_ivar_get(server_socket, ID_ivar_io);
887
- if (underlying_sock != Qnil) server_socket = underlying_sock;
888
868
 
889
- GetOpenFile(server_socket, fptr);
890
- io_unset_nonblock(fptr, server_socket);
869
+ server_fd = fd_from_io(server_socket, &server_fptr, 0, 0);
891
870
 
892
871
  while (1) {
893
872
  VALUE resume_value = Qnil;
@@ -896,7 +875,7 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE soc
896
875
  int fd;
897
876
  int completed;
898
877
 
899
- io_uring_prep_accept(sqe, fptr->fd, &addr, &len, 0);
878
+ io_uring_prep_accept(sqe, server_fd, &addr, &len, 0);
900
879
 
901
880
  fd = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
902
881
  completed = context_store_release(&backend->store, ctx);
@@ -946,22 +925,15 @@ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
946
925
  }
947
926
 
948
927
  VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE maxlen, int loop) {
928
+ int src_fd;
929
+ int dest_fd;
949
930
  rb_io_t *src_fptr;
950
931
  rb_io_t *dest_fptr;
951
- VALUE underlying_io;
952
932
  int total = 0;
953
933
  VALUE resume_value = Qnil;
954
934
 
955
- underlying_io = rb_ivar_get(src, ID_ivar_io);
956
- if (underlying_io != Qnil) src = underlying_io;
957
- GetOpenFile(src, src_fptr);
958
- io_unset_nonblock(src_fptr, src);
959
-
960
- underlying_io = rb_ivar_get(dest, ID_ivar_io);
961
- if (underlying_io != Qnil) dest = underlying_io;
962
- dest = rb_io_get_write_io(dest);
963
- GetOpenFile(dest, dest_fptr);
964
- io_unset_nonblock(dest_fptr, dest);
935
+ src_fd = fd_from_io(src, &src_fptr, 0, 0);
936
+ dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
965
937
 
966
938
  while (1) {
967
939
  op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
@@ -969,7 +941,7 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
969
941
  int result;
970
942
  int completed;
971
943
 
972
- io_uring_prep_splice(sqe, src_fptr->fd, -1, dest_fptr->fd, -1, NUM2INT(maxlen), 0);
944
+ io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, NUM2INT(maxlen), 0);
973
945
 
974
946
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
975
947
  completed = context_store_release(&backend->store, ctx);
@@ -989,7 +961,6 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
989
961
  VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
990
962
  Backend_t *backend;
991
963
  GetBackend(self, backend);
992
-
993
964
  return io_uring_backend_splice(backend, src, dest, maxlen, 0);
994
965
  }
995
966
 
@@ -1000,12 +971,47 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize)
1000
971
  return io_uring_backend_splice(backend, src, dest, chunksize, 1);
1001
972
  }
1002
973
 
974
+ VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
975
+ Backend_t *backend;
976
+ GetBackend(self, backend);
977
+
978
+ int src_fd;
979
+ int dest_fd;
980
+ rb_io_t *src_fptr;
981
+ rb_io_t *dest_fptr;
982
+ VALUE resume_value = Qnil;
983
+
984
+ src_fd = fd_from_io(src, &src_fptr, 0, 0);
985
+ dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
986
+
987
+ while (1) {
988
+ op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
989
+ struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
990
+ int result;
991
+ int completed;
992
+
993
+ io_uring_prep_tee(sqe, src_fd, dest_fd, NUM2INT(maxlen), 0);
994
+
995
+ result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
996
+ completed = context_store_release(&backend->store, ctx);
997
+ RAISE_IF_EXCEPTION(resume_value);
998
+ if (!completed) return resume_value;
999
+
1000
+ if (result < 0)
1001
+ rb_syserr_fail(-result, strerror(-result));
1002
+
1003
+ return INT2NUM(result);
1004
+ }
1005
+
1006
+ RB_GC_GUARD(resume_value);
1007
+ }
1008
+
1003
1009
  VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
1004
1010
  Backend_t *backend;
1011
+ int fd;
1005
1012
  rb_io_t *fptr;
1006
1013
  struct sockaddr *ai_addr;
1007
1014
  int ai_addrlen;
1008
- VALUE underlying_sock = rb_ivar_get(sock, ID_ivar_io);
1009
1015
  VALUE resume_value = Qnil;
1010
1016
  op_context_t *ctx;
1011
1017
  struct io_uring_sqe *sqe;
@@ -1014,15 +1020,11 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
1014
1020
 
1015
1021
  ai_addrlen = backend_getaddrinfo(host, port, &ai_addr);
1016
1022
 
1017
- if (underlying_sock != Qnil) sock = underlying_sock;
1018
-
1019
1023
  GetBackend(self, backend);
1020
- GetOpenFile(sock, fptr);
1021
- io_unset_nonblock(fptr, sock);
1022
-
1024
+ fd = fd_from_io(sock, &fptr, 1, 0);
1023
1025
  ctx = context_store_acquire(&backend->store, OP_CONNECT);
1024
1026
  sqe = io_uring_get_sqe(&backend->ring);
1025
- io_uring_prep_connect(sqe, fptr->fd, ai_addr, ai_addrlen);
1027
+ io_uring_prep_connect(sqe, fd, ai_addr, ai_addrlen);
1026
1028
  result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
1027
1029
  completed = context_store_release(&backend->store, ctx);
1028
1030
  RAISE_IF_EXCEPTION(resume_value);
@@ -1035,16 +1037,14 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
1035
1037
 
1036
1038
  VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
1037
1039
  Backend_t *backend;
1040
+ int fd;
1038
1041
  rb_io_t *fptr;
1039
- VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
1040
1042
  VALUE resume_value;
1043
+ int write_mode = RTEST(write);
1041
1044
 
1042
- if (underlying_io != Qnil) io = underlying_io;
1043
1045
  GetBackend(self, backend);
1044
- GetOpenFile(io, fptr);
1045
- io_unset_nonblock(fptr, io);
1046
-
1047
- resume_value = io_uring_backend_wait_fd(backend, fptr->fd, RTEST(write));
1046
+ fd = fd_from_io(io, &fptr, write_mode, 0);
1047
+ resume_value = io_uring_backend_wait_fd(backend, fd, write_mode);
1048
1048
 
1049
1049
  RAISE_IF_EXCEPTION(resume_value);
1050
1050
  RB_GC_GUARD(resume_value);
@@ -1054,24 +1054,19 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
1054
1054
  // VALUE Backend_close(VALUE self, VALUE io) {
1055
1055
  // Backend_t *backend;
1056
1056
  // rb_io_t *fptr;
1057
- // VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
1058
1057
  // VALUE resume_value = Qnil;
1059
1058
  // op_context_t *ctx;
1060
1059
  // struct io_uring_sqe *sqe;
1061
1060
  // int result;
1062
1061
  // int completed;
1063
1062
 
1064
- // if (underlying_io != Qnil) io = underlying_io;
1065
- // GetBackend(self, backend);
1066
- // GetOpenFile(io, fptr);
1067
-
1068
- // if (fptr->fd < 0) return Qnil;
1063
+ // if (fd < 0) return Qnil;
1069
1064
 
1070
1065
  // io_unset_nonblock(fptr, io);
1071
1066
 
1072
1067
  // ctx = context_store_acquire(&backend->store, OP_CLOSE);
1073
1068
  // sqe = io_uring_get_sqe(&backend->ring);
1074
- // io_uring_prep_close(sqe, fptr->fd);
1069
+ // io_uring_prep_close(sqe, fd);
1075
1070
  // result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
1076
1071
  // completed = context_store_release(&backend->store, ctx);
1077
1072
  // RAISE_IF_EXCEPTION(resume_value);
@@ -1081,7 +1076,7 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
1081
1076
  // if (result < 0) rb_syserr_fail(-result, strerror(-result));
1082
1077
 
1083
1078
  // fptr_finalize(fptr);
1084
- // // fptr->fd = -1;
1079
+ // // fd = -1;
1085
1080
  // return io;
1086
1081
  // }
1087
1082
 
@@ -1165,7 +1160,7 @@ VALUE Backend_timeout_ensure(VALUE arg) {
1165
1160
  timeout_ctx->ctx->result = -ECANCELED;
1166
1161
  // op was not completed, so we need to cancel it
1167
1162
  sqe = io_uring_get_sqe(&timeout_ctx->backend->ring);
1168
- io_uring_prep_cancel(sqe, timeout_ctx->ctx, 0);
1163
+ io_uring_prep_cancel(sqe, (__u64)timeout_ctx->ctx, 0);
1169
1164
  timeout_ctx->backend->pending_sqes = 0;
1170
1165
  io_uring_submit(&timeout_ctx->backend->ring);
1171
1166
  }
@@ -1267,56 +1262,39 @@ VALUE Backend_kind(VALUE self) {
1267
1262
  }
1268
1263
 
1269
1264
  struct io_uring_sqe *Backend_chain_prepare_write(Backend_t *backend, VALUE io, VALUE str) {
1265
+ int fd;
1270
1266
  rb_io_t *fptr;
1271
- VALUE underlying_io;
1272
1267
  struct io_uring_sqe *sqe;
1273
1268
 
1274
- underlying_io = rb_ivar_get(io, ID_ivar_io);
1275
- if (underlying_io != Qnil) io = underlying_io;
1276
- io = rb_io_get_write_io(io);
1277
- GetOpenFile(io, fptr);
1278
- io_unset_nonblock(fptr, io);
1279
-
1269
+ fd = fd_from_io(io, &fptr, 1, 0);
1280
1270
  sqe = io_uring_get_sqe(&backend->ring);
1281
- io_uring_prep_write(sqe, fptr->fd, StringValuePtr(str), RSTRING_LEN(str), 0);
1271
+ io_uring_prep_write(sqe, fd, StringValuePtr(str), RSTRING_LEN(str), 0);
1282
1272
  return sqe;
1283
1273
  }
1284
1274
 
1285
1275
  struct io_uring_sqe *Backend_chain_prepare_send(Backend_t *backend, VALUE io, VALUE str, VALUE flags) {
1276
+ int fd;
1286
1277
  rb_io_t *fptr;
1287
- VALUE underlying_io;
1288
1278
  struct io_uring_sqe *sqe;
1289
1279
 
1290
- underlying_io = rb_ivar_get(io, ID_ivar_io);
1291
- if (underlying_io != Qnil) io = underlying_io;
1292
- io = rb_io_get_write_io(io);
1293
- GetOpenFile(io, fptr);
1294
- io_unset_nonblock(fptr, io);
1280
+ fd = fd_from_io(io, &fptr, 1, 0);
1295
1281
 
1296
1282
  sqe = io_uring_get_sqe(&backend->ring);
1297
- io_uring_prep_send(sqe, fptr->fd, StringValuePtr(str), RSTRING_LEN(str), NUM2INT(flags));
1283
+ io_uring_prep_send(sqe, fd, StringValuePtr(str), RSTRING_LEN(str), NUM2INT(flags));
1298
1284
  return sqe;
1299
1285
  }
1300
1286
 
1301
1287
  struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE maxlen) {
1288
+ int src_fd;
1289
+ int dest_fd;
1302
1290
  rb_io_t *src_fptr;
1303
1291
  rb_io_t *dest_fptr;
1304
- VALUE underlying_io;
1305
1292
  struct io_uring_sqe *sqe;
1306
1293
 
1307
- underlying_io = rb_ivar_get(src, ID_ivar_io);
1308
- if (underlying_io != Qnil) src = underlying_io;
1309
- GetOpenFile(src, src_fptr);
1310
- io_unset_nonblock(src_fptr, src);
1311
-
1312
- underlying_io = rb_ivar_get(dest, ID_ivar_io);
1313
- if (underlying_io != Qnil) dest = underlying_io;
1314
- dest = rb_io_get_write_io(dest);
1315
- GetOpenFile(dest, dest_fptr);
1316
- io_unset_nonblock(dest_fptr, dest);
1317
-
1294
+ src_fd = fd_from_io(src, &src_fptr, 0, 0);
1295
+ dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
1318
1296
  sqe = io_uring_get_sqe(&backend->ring);
1319
- io_uring_prep_splice(sqe, src_fptr->fd, -1, dest_fptr->fd, -1, NUM2INT(maxlen), 0);
1297
+ io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, NUM2INT(maxlen), 0);
1320
1298
  return sqe;
1321
1299
  }
1322
1300
 
@@ -1375,7 +1353,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
1375
1353
  ctx->ref_count = sqe_count;
1376
1354
  ctx->result = -ECANCELED;
1377
1355
  sqe = io_uring_get_sqe(&backend->ring);
1378
- io_uring_prep_cancel(sqe, ctx, 0);
1356
+ io_uring_prep_cancel(sqe, (__u64)ctx, 0);
1379
1357
  backend->pending_sqes = 0;
1380
1358
  io_uring_submit(&backend->ring);
1381
1359
  }
@@ -1406,7 +1384,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
1406
1384
  // op was not completed (an exception was raised), so we need to cancel it
1407
1385
  ctx->result = -ECANCELED;
1408
1386
  sqe = io_uring_get_sqe(&backend->ring);
1409
- io_uring_prep_cancel(sqe, ctx, 0);
1387
+ io_uring_prep_cancel(sqe, (__u64)ctx, 0);
1410
1388
  backend->pending_sqes = 0;
1411
1389
  io_uring_submit(&backend->ring);
1412
1390
  RAISE_IF_EXCEPTION(resume_value);
@@ -1473,7 +1451,7 @@ static inline void splice_chunks_cancel(Backend_t *backend, op_context_t *ctx) {
1473
1451
 
1474
1452
  ctx->result = -ECANCELED;
1475
1453
  sqe = io_uring_get_sqe(&backend->ring);
1476
- io_uring_prep_cancel(sqe, ctx, 0);
1454
+ io_uring_prep_cancel(sqe, (__u64)ctx, 0);
1477
1455
  backend->pending_sqes = 0;
1478
1456
  io_uring_submit(&backend->ring);
1479
1457
  }
@@ -1509,25 +1487,17 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
1509
1487
  op_context_t *ctx = 0;
1510
1488
  struct io_uring_sqe *sqe = 0;
1511
1489
  int maxlen;
1512
- VALUE underlying_io;
1513
1490
  VALUE str = Qnil;
1514
1491
  VALUE chunk_len_value = Qnil;
1492
+ int src_fd;
1493
+ int dest_fd;
1515
1494
  rb_io_t *src_fptr;
1516
1495
  rb_io_t *dest_fptr;
1517
1496
  int pipefd[2] = { -1, -1 };
1518
1497
 
1519
1498
  GetBackend(self, backend);
1520
-
1521
- underlying_io = rb_ivar_get(src, ID_ivar_io);
1522
- if (underlying_io != Qnil) src = underlying_io;
1523
- GetOpenFile(src, src_fptr);
1524
- io_verify_blocking_mode(src_fptr, src, Qtrue);
1525
-
1526
- underlying_io = rb_ivar_get(dest, ID_ivar_io);
1527
- if (underlying_io != Qnil) dest = underlying_io;
1528
- dest = rb_io_get_write_io(dest);
1529
- GetOpenFile(dest, dest_fptr);
1530
- io_verify_blocking_mode(dest_fptr, dest, Qtrue);
1499
+ src_fd = fd_from_io(src, &src_fptr, 0, 0);
1500
+ dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
1531
1501
 
1532
1502
  maxlen = NUM2INT(chunk_size);
1533
1503
 
@@ -1538,7 +1508,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
1538
1508
 
1539
1509
  if (prefix != Qnil) {
1540
1510
  splice_chunks_get_sqe(backend, &ctx, &sqe, OP_WRITE);
1541
- splice_chunks_prep_write(ctx, sqe, dest_fptr->fd, prefix);
1511
+ splice_chunks_prep_write(ctx, sqe, dest_fd, prefix);
1542
1512
  backend->base.op_count++;
1543
1513
  }
1544
1514
 
@@ -1548,7 +1518,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
1548
1518
  VALUE chunk_postfix_str = Qnil;
1549
1519
 
1550
1520
  splice_chunks_get_sqe(backend, &ctx, &sqe, OP_SPLICE);
1551
- splice_chunks_prep_splice(ctx, sqe, src_fptr->fd, pipefd[1], maxlen);
1521
+ splice_chunks_prep_splice(ctx, sqe, src_fd, pipefd[1], maxlen);
1552
1522
  backend->base.op_count++;
1553
1523
 
1554
1524
  SPLICE_CHUNKS_AWAIT_OPS(backend, &ctx, &chunk_len, &switchpoint_result);
@@ -1561,18 +1531,18 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
1561
1531
  if (chunk_prefix != Qnil) {
1562
1532
  chunk_prefix_str = (TYPE(chunk_prefix) == T_STRING) ? chunk_prefix : rb_funcall(chunk_prefix, ID_call, 1, chunk_len_value);
1563
1533
  splice_chunks_get_sqe(backend, &ctx, &sqe, OP_WRITE);
1564
- splice_chunks_prep_write(ctx, sqe, dest_fptr->fd, chunk_prefix_str);
1534
+ splice_chunks_prep_write(ctx, sqe, dest_fd, chunk_prefix_str);
1565
1535
  backend->base.op_count++;
1566
1536
  }
1567
1537
 
1568
1538
  splice_chunks_get_sqe(backend, &ctx, &sqe, OP_SPLICE);
1569
- splice_chunks_prep_splice(ctx, sqe, pipefd[0], dest_fptr->fd, chunk_len);
1539
+ splice_chunks_prep_splice(ctx, sqe, pipefd[0], dest_fd, chunk_len);
1570
1540
  backend->base.op_count++;
1571
1541
 
1572
1542
  if (chunk_postfix != Qnil) {
1573
1543
  chunk_postfix_str = (TYPE(chunk_postfix) == T_STRING) ? chunk_postfix : rb_funcall(chunk_postfix, ID_call, 1, chunk_len_value);
1574
1544
  splice_chunks_get_sqe(backend, &ctx, &sqe, OP_WRITE);
1575
- splice_chunks_prep_write(ctx, sqe, dest_fptr->fd, chunk_postfix_str);
1545
+ splice_chunks_prep_write(ctx, sqe, dest_fd, chunk_postfix_str);
1576
1546
  backend->base.op_count++;
1577
1547
  }
1578
1548
 
@@ -1582,7 +1552,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
1582
1552
 
1583
1553
  if (postfix != Qnil) {
1584
1554
  splice_chunks_get_sqe(backend, &ctx, &sqe, OP_WRITE);
1585
- splice_chunks_prep_write(ctx, sqe, dest_fptr->fd, postfix);
1555
+ splice_chunks_prep_write(ctx, sqe, dest_fd, postfix);
1586
1556
  backend->base.op_count++;
1587
1557
  }
1588
1558
  if (ctx) {
@@ -1684,6 +1654,7 @@ void Init_Backend() {
1684
1654
  rb_define_method(cBackend, "sleep", Backend_sleep, 1);
1685
1655
  rb_define_method(cBackend, "splice", Backend_splice, 3);
1686
1656
  rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
1657
+ rb_define_method(cBackend, "tee", Backend_tee, 3);
1687
1658
  rb_define_method(cBackend, "timeout", Backend_timeout, -1);
1688
1659
  rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
1689
1660
  rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);