polyphony 0.81.1 → 0.84
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 +4 -4
- data/.github/workflows/test.yml +1 -1
- data/.gitmodules +3 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +14 -0
- data/bin/test +1 -1
- data/ext/polyphony/backend_common.c +33 -10
- data/ext/polyphony/backend_common.h +20 -2
- data/ext/polyphony/backend_io_uring.c +182 -220
- data/ext/polyphony/backend_libev.c +212 -197
- data/ext/polyphony/extconf.rb +21 -2
- data/ext/polyphony/io_extensions.c +440 -0
- data/ext/polyphony/pipe.c +109 -0
- data/ext/polyphony/polyphony.c +50 -1
- data/ext/polyphony/polyphony.h +6 -11
- data/ext/polyphony/polyphony_ext.c +7 -2
- data/ext/polyphony/zlib_conf.rb +119 -0
- data/lib/polyphony/extensions/io.rb +20 -2
- data/lib/polyphony/extensions/pipe.rb +171 -0
- data/lib/polyphony/extensions.rb +1 -0
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +4 -0
- data/test/helper.rb +4 -0
- data/test/test_backend.rb +3 -48
- data/test/test_global_api.rb +23 -23
- data/test/test_io.rb +426 -0
- data/test/test_pipe.rb +41 -0
- data/test/test_process_supervision.rb +1 -1
- data/test/test_raw_buffer.rb +37 -0
- data/test/test_socket.rb +50 -0
- metadata +8 -13
- data/ext/liburing/liburing/README.md +0 -4
- data/ext/liburing/liburing/barrier.h +0 -73
- data/ext/liburing/liburing/compat.h +0 -15
- data/ext/liburing/liburing/io_uring.h +0 -343
- data/ext/liburing/liburing.h +0 -585
- data/ext/liburing/queue.c +0 -333
- data/ext/liburing/register.c +0 -187
- data/ext/liburing/setup.c +0 -210
- data/ext/liburing/syscall.c +0 -54
- data/ext/liburing/syscall.h +0 -18
- data/ext/polyphony/liburing.c +0 -8
@@ -266,41 +266,74 @@ VALUE libev_wait_fd(Backend_t *backend, int fd, int events, int raise_exception)
|
|
266
266
|
return switchpoint_result;
|
267
267
|
}
|
268
268
|
|
269
|
+
static inline int fd_from_io(VALUE io, rb_io_t **fptr, int write_mode, int rectify_file_pos) {
|
270
|
+
if (rb_obj_class(io) == cPipe) {
|
271
|
+
*fptr = NULL;
|
272
|
+
Pipe_verify_blocking_mode(io, Qfalse);
|
273
|
+
return Pipe_get_fd(io, write_mode);
|
274
|
+
}
|
275
|
+
else {
|
276
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
277
|
+
if (underlying_io != Qnil) io = underlying_io;
|
278
|
+
|
279
|
+
GetOpenFile(io, *fptr);
|
280
|
+
io_verify_blocking_mode(*fptr, io, Qfalse);
|
281
|
+
if (rectify_file_pos) rectify_io_file_pos(*fptr);
|
282
|
+
|
283
|
+
return (*fptr)->fd;
|
284
|
+
}
|
285
|
+
}
|
286
|
+
|
269
287
|
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos) {
|
270
288
|
Backend_t *backend;
|
271
289
|
struct libev_io watcher;
|
290
|
+
int fd;
|
272
291
|
rb_io_t *fptr;
|
273
|
-
|
274
|
-
|
292
|
+
|
293
|
+
struct io_buffer buffer = get_io_buffer(str);
|
275
294
|
long buf_pos = NUM2INT(pos);
|
276
|
-
|
277
|
-
|
278
|
-
if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
|
279
|
-
}
|
280
|
-
else buf_pos = 0;
|
281
|
-
int shrinkable = io_setstrbuf(&str, buf_pos + len);
|
282
|
-
char *buf = RSTRING_PTR(str) + buf_pos;
|
295
|
+
int shrinkable_string = 0;
|
296
|
+
int expandable_buffer = 0;
|
283
297
|
long total = 0;
|
284
298
|
VALUE switchpoint_result = Qnil;
|
285
299
|
int read_to_eof = RTEST(to_eof);
|
286
|
-
|
300
|
+
|
301
|
+
if (buffer.raw) {
|
302
|
+
if (buf_pos < 0 || buf_pos > buffer.len) buf_pos = buffer.len;
|
303
|
+
buffer.ptr += buf_pos;
|
304
|
+
buffer.len -= buf_pos;
|
305
|
+
}
|
306
|
+
else {
|
307
|
+
expandable_buffer = length == Qnil;
|
308
|
+
long expected_read_length = expandable_buffer ? 4096 : FIX2INT(length);
|
309
|
+
long string_cap = rb_str_capacity(str);
|
310
|
+
if (buf_pos < 0 || buf_pos > buffer.len) buf_pos = buffer.len;
|
311
|
+
|
312
|
+
if (string_cap < expected_read_length + buf_pos) {
|
313
|
+
shrinkable_string = io_setstrbuf(&str, expected_read_length + buf_pos);
|
314
|
+
buffer.ptr = RSTRING_PTR(str) + buf_pos;
|
315
|
+
buffer.len = expected_read_length;
|
316
|
+
}
|
317
|
+
else {
|
318
|
+
buffer.ptr += buf_pos;
|
319
|
+
buffer.len = string_cap - buf_pos;
|
320
|
+
if (buffer.len > expected_read_length)
|
321
|
+
buffer.len = expected_read_length;
|
322
|
+
}
|
323
|
+
}
|
287
324
|
|
288
325
|
GetBackend(self, backend);
|
289
|
-
|
290
|
-
GetOpenFile(io, fptr);
|
291
|
-
rb_io_check_byte_readable(fptr);
|
292
|
-
io_verify_blocking_mode(fptr, io, Qfalse);
|
293
|
-
rectify_io_file_pos(fptr);
|
326
|
+
fd = fd_from_io(io, &fptr, 0, 1);
|
294
327
|
watcher.fiber = Qnil;
|
295
328
|
|
296
329
|
while (1) {
|
297
330
|
backend->base.op_count++;
|
298
|
-
ssize_t
|
299
|
-
if (
|
331
|
+
ssize_t result = read(fd, buffer.ptr, buffer.len);
|
332
|
+
if (result < 0) {
|
300
333
|
int e = errno;
|
301
334
|
if (e != EWOULDBLOCK && e != EAGAIN) rb_syserr_fail(e, strerror(e));
|
302
335
|
|
303
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
336
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_READ);
|
304
337
|
|
305
338
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
306
339
|
}
|
@@ -308,32 +341,39 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
308
341
|
switchpoint_result = backend_snooze(&backend->base);
|
309
342
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
310
343
|
|
311
|
-
if (
|
312
|
-
|
344
|
+
if (!result) break; // EOF
|
345
|
+
|
346
|
+
total += result;
|
313
347
|
if (!read_to_eof) break;
|
314
348
|
|
315
|
-
if (
|
316
|
-
if (!
|
349
|
+
if (result == buffer.len) {
|
350
|
+
if (!expandable_buffer) break;
|
317
351
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
352
|
+
// resize buffer to double its capacity
|
353
|
+
rb_str_resize(str, total + buf_pos);
|
354
|
+
rb_str_modify_expand(str, rb_str_capacity(str));
|
355
|
+
shrinkable_string = 0;
|
356
|
+
buffer.ptr = RSTRING_PTR(str) + total + buf_pos;
|
357
|
+
buffer.len = rb_str_capacity(str) - total - buf_pos;
|
358
|
+
}
|
359
|
+
else {
|
360
|
+
buffer.ptr += result;
|
361
|
+
buffer.len -= result;
|
362
|
+
if (!buffer.len) break;
|
323
363
|
}
|
324
|
-
else buf += n;
|
325
364
|
}
|
326
365
|
}
|
327
366
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
367
|
+
if (!buffer.raw) {
|
368
|
+
io_set_read_length(str, buf_pos + total, shrinkable_string);
|
369
|
+
if (fptr) io_enc_str(str, fptr);
|
370
|
+
}
|
371
|
+
if (!total) return Qnil;
|
332
372
|
|
333
373
|
RB_GC_GUARD(watcher.fiber);
|
334
374
|
RB_GC_GUARD(switchpoint_result);
|
335
375
|
|
336
|
-
return str;
|
376
|
+
return buffer.raw ? INT2FIX(total) : str;
|
337
377
|
error:
|
338
378
|
return RAISE_EXCEPTION(switchpoint_result);
|
339
379
|
}
|
@@ -345,6 +385,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
345
385
|
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
346
386
|
Backend_t *backend;
|
347
387
|
struct libev_io watcher;
|
388
|
+
int fd;
|
348
389
|
rb_io_t *fptr;
|
349
390
|
VALUE str;
|
350
391
|
long total;
|
@@ -352,26 +393,21 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
352
393
|
int shrinkable;
|
353
394
|
char *buf;
|
354
395
|
VALUE switchpoint_result = Qnil;
|
355
|
-
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
356
396
|
|
357
397
|
READ_LOOP_PREPARE_STR();
|
358
398
|
|
359
399
|
GetBackend(self, backend);
|
360
|
-
|
361
|
-
GetOpenFile(io, fptr);
|
362
|
-
rb_io_check_byte_readable(fptr);
|
363
|
-
io_verify_blocking_mode(fptr, io, Qfalse);
|
364
|
-
rectify_io_file_pos(fptr);
|
400
|
+
fd = fd_from_io(io, &fptr, 0, 1);
|
365
401
|
watcher.fiber = Qnil;
|
366
402
|
|
367
403
|
while (1) {
|
368
404
|
backend->base.op_count++;
|
369
|
-
ssize_t n = read(
|
405
|
+
ssize_t n = read(fd, buf, len);
|
370
406
|
if (n < 0) {
|
371
407
|
int e = errno;
|
372
408
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
373
409
|
|
374
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
410
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_READ);
|
375
411
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
376
412
|
}
|
377
413
|
else {
|
@@ -397,6 +433,7 @@ error:
|
|
397
433
|
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
398
434
|
Backend_t *backend;
|
399
435
|
struct libev_io watcher;
|
436
|
+
int fd;
|
400
437
|
rb_io_t *fptr;
|
401
438
|
VALUE str;
|
402
439
|
long total;
|
@@ -404,27 +441,22 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
404
441
|
int shrinkable;
|
405
442
|
char *buf;
|
406
443
|
VALUE switchpoint_result = Qnil;
|
407
|
-
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
408
444
|
ID method_id = SYM2ID(method);
|
409
445
|
|
410
446
|
READ_LOOP_PREPARE_STR();
|
411
447
|
|
412
448
|
GetBackend(self, backend);
|
413
|
-
|
414
|
-
GetOpenFile(io, fptr);
|
415
|
-
rb_io_check_byte_readable(fptr);
|
416
|
-
io_verify_blocking_mode(fptr, io, Qfalse);
|
417
|
-
rectify_io_file_pos(fptr);
|
449
|
+
fd = fd_from_io(io, &fptr, 0, 1);
|
418
450
|
watcher.fiber = Qnil;
|
419
451
|
|
420
452
|
while (1) {
|
421
453
|
backend->base.op_count++;
|
422
|
-
ssize_t n = read(
|
454
|
+
ssize_t n = read(fd, buf, len);
|
423
455
|
if (n < 0) {
|
424
456
|
int e = errno;
|
425
457
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
426
458
|
|
427
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
459
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_READ);
|
428
460
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
429
461
|
}
|
430
462
|
else {
|
@@ -450,35 +482,31 @@ error:
|
|
450
482
|
VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
451
483
|
Backend_t *backend;
|
452
484
|
struct libev_io watcher;
|
485
|
+
int fd;
|
453
486
|
rb_io_t *fptr;
|
454
487
|
VALUE switchpoint_result = Qnil;
|
455
|
-
VALUE underlying_io;
|
456
|
-
char *buf = StringValuePtr(str);
|
457
|
-
long len = RSTRING_LEN(str);
|
458
|
-
long left = len;
|
459
488
|
|
460
|
-
|
461
|
-
|
489
|
+
struct io_buffer buffer = get_io_buffer(str);
|
490
|
+
long left = buffer.len;
|
491
|
+
|
462
492
|
GetBackend(self, backend);
|
463
|
-
|
464
|
-
GetOpenFile(io, fptr);
|
465
|
-
io_verify_blocking_mode(fptr, io, Qfalse);
|
493
|
+
fd = fd_from_io(io, &fptr, 1, 0);
|
466
494
|
watcher.fiber = Qnil;
|
467
495
|
|
468
496
|
while (left > 0) {
|
469
497
|
backend->base.op_count++;
|
470
|
-
ssize_t
|
471
|
-
if (
|
498
|
+
ssize_t result = write(fd, buffer.ptr, left);
|
499
|
+
if (result < 0) {
|
472
500
|
int e = errno;
|
473
501
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
474
502
|
|
475
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
503
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_WRITE);
|
476
504
|
|
477
505
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
478
506
|
}
|
479
507
|
else {
|
480
|
-
|
481
|
-
left -=
|
508
|
+
buffer.ptr += result;
|
509
|
+
left -= result;
|
482
510
|
}
|
483
511
|
}
|
484
512
|
|
@@ -491,7 +519,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
491
519
|
RB_GC_GUARD(watcher.fiber);
|
492
520
|
RB_GC_GUARD(switchpoint_result);
|
493
521
|
|
494
|
-
return INT2NUM(len);
|
522
|
+
return INT2NUM(buffer.len);
|
495
523
|
error:
|
496
524
|
return RAISE_EXCEPTION(switchpoint_result);
|
497
525
|
}
|
@@ -499,21 +527,17 @@ error:
|
|
499
527
|
VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
500
528
|
Backend_t *backend;
|
501
529
|
struct libev_io watcher;
|
530
|
+
int fd;
|
502
531
|
rb_io_t *fptr;
|
503
532
|
VALUE switchpoint_result = Qnil;
|
504
|
-
VALUE underlying_io;
|
505
533
|
long total_length = 0;
|
506
534
|
long total_written = 0;
|
507
535
|
struct iovec *iov = 0;
|
508
536
|
struct iovec *iov_ptr = 0;
|
509
537
|
int iov_count = argc;
|
510
538
|
|
511
|
-
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
512
|
-
if (underlying_io != Qnil) io = underlying_io;
|
513
539
|
GetBackend(self, backend);
|
514
|
-
|
515
|
-
GetOpenFile(io, fptr);
|
516
|
-
io_verify_blocking_mode(fptr, io, Qfalse);
|
540
|
+
fd = fd_from_io(io, &fptr, 1, 0);
|
517
541
|
watcher.fiber = Qnil;
|
518
542
|
|
519
543
|
iov = malloc(iov_count * sizeof(struct iovec));
|
@@ -527,7 +551,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
527
551
|
|
528
552
|
while (1) {
|
529
553
|
backend->base.op_count++;
|
530
|
-
ssize_t n = writev(
|
554
|
+
ssize_t n = writev(fd, iov_ptr, iov_count);
|
531
555
|
if (n < 0) {
|
532
556
|
int e = errno;
|
533
557
|
if ((e != EWOULDBLOCK && e != EAGAIN)) {
|
@@ -535,7 +559,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
535
559
|
rb_syserr_fail(e, strerror(e));
|
536
560
|
}
|
537
561
|
|
538
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
562
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_WRITE);
|
539
563
|
|
540
564
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
541
565
|
}
|
@@ -585,26 +609,25 @@ VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
|
|
585
609
|
VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
586
610
|
Backend_t *backend;
|
587
611
|
struct libev_io watcher;
|
588
|
-
|
612
|
+
int server_fd;
|
613
|
+
rb_io_t *server_fptr;
|
589
614
|
int fd;
|
590
615
|
struct sockaddr addr;
|
591
616
|
socklen_t len = (socklen_t)sizeof addr;
|
592
617
|
VALUE switchpoint_result = Qnil;
|
593
|
-
VALUE underlying_sock = rb_ivar_get(server_socket, ID_ivar_io);
|
594
|
-
if (underlying_sock != Qnil) server_socket = underlying_sock;
|
595
618
|
|
596
619
|
GetBackend(self, backend);
|
597
|
-
|
598
|
-
io_verify_blocking_mode(fptr, server_socket, Qfalse);
|
620
|
+
server_fd = fd_from_io(server_socket, &server_fptr, 0, 0);
|
599
621
|
watcher.fiber = Qnil;
|
622
|
+
|
600
623
|
while (1) {
|
601
624
|
backend->base.op_count++;
|
602
|
-
fd = accept(
|
625
|
+
fd = accept(server_fd, &addr, &len);
|
603
626
|
if (fd < 0) {
|
604
627
|
int e = errno;
|
605
628
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
606
629
|
|
607
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
630
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, server_fd, &watcher, EV_READ);
|
608
631
|
|
609
632
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
610
633
|
}
|
@@ -642,28 +665,25 @@ error:
|
|
642
665
|
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
643
666
|
Backend_t *backend;
|
644
667
|
struct libev_io watcher;
|
645
|
-
|
646
|
-
|
668
|
+
int server_fd;
|
669
|
+
rb_io_t *server_fptr;
|
647
670
|
struct sockaddr addr;
|
648
671
|
socklen_t len = (socklen_t)sizeof addr;
|
649
672
|
VALUE switchpoint_result = Qnil;
|
650
673
|
VALUE socket = Qnil;
|
651
|
-
VALUE underlying_sock = rb_ivar_get(server_socket, ID_ivar_io);
|
652
|
-
if (underlying_sock != Qnil) server_socket = underlying_sock;
|
653
674
|
|
654
675
|
GetBackend(self, backend);
|
655
|
-
|
656
|
-
io_verify_blocking_mode(fptr, server_socket, Qfalse);
|
676
|
+
server_fd = fd_from_io(server_socket, &server_fptr, 0, 0);
|
657
677
|
watcher.fiber = Qnil;
|
658
678
|
|
659
679
|
while (1) {
|
660
680
|
backend->base.op_count++;
|
661
|
-
fd = accept(
|
681
|
+
int fd = accept(server_fd, &addr, &len);
|
662
682
|
if (fd < 0) {
|
663
683
|
int e = errno;
|
664
684
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
665
685
|
|
666
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
686
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, server_fd, &watcher, EV_READ);
|
667
687
|
|
668
688
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
669
689
|
}
|
@@ -701,28 +721,25 @@ error:
|
|
701
721
|
VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
702
722
|
Backend_t *backend;
|
703
723
|
struct libev_io watcher;
|
724
|
+
int fd;
|
704
725
|
rb_io_t *fptr;
|
705
726
|
struct sockaddr *ai_addr;
|
706
727
|
int ai_addrlen;
|
707
728
|
VALUE switchpoint_result = Qnil;
|
708
|
-
VALUE underlying_sock = rb_ivar_get(sock, ID_ivar_io);
|
709
729
|
|
710
730
|
ai_addrlen = backend_getaddrinfo(host, port, &ai_addr);
|
711
731
|
|
712
|
-
if (underlying_sock != Qnil) sock = underlying_sock;
|
713
|
-
|
714
732
|
GetBackend(self, backend);
|
715
|
-
|
716
|
-
io_verify_blocking_mode(fptr, sock, Qfalse);
|
733
|
+
fd = fd_from_io(sock, &fptr, 1, 0);
|
717
734
|
watcher.fiber = Qnil;
|
718
735
|
|
719
736
|
backend->base.op_count++;
|
720
|
-
int result = connect(
|
737
|
+
int result = connect(fd, ai_addr, ai_addrlen);
|
721
738
|
if (result < 0) {
|
722
739
|
int e = errno;
|
723
740
|
if (e != EINPROGRESS) rb_syserr_fail(e, strerror(e));
|
724
741
|
|
725
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
742
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_WRITE);
|
726
743
|
|
727
744
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
728
745
|
}
|
@@ -740,36 +757,32 @@ error:
|
|
740
757
|
VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
741
758
|
Backend_t *backend;
|
742
759
|
struct libev_io watcher;
|
760
|
+
int fd;
|
743
761
|
rb_io_t *fptr;
|
744
762
|
VALUE switchpoint_result = Qnil;
|
745
|
-
|
746
|
-
|
747
|
-
long
|
748
|
-
long left = len;
|
763
|
+
|
764
|
+
struct io_buffer buffer = get_io_buffer(str);
|
765
|
+
long left = buffer.len;
|
749
766
|
int flags_int = NUM2INT(flags);
|
750
767
|
|
751
|
-
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
752
|
-
if (underlying_io != Qnil) io = underlying_io;
|
753
768
|
GetBackend(self, backend);
|
754
|
-
|
755
|
-
GetOpenFile(io, fptr);
|
756
|
-
io_verify_blocking_mode(fptr, io, Qfalse);
|
769
|
+
fd = fd_from_io(io, &fptr, 1, 0);
|
757
770
|
watcher.fiber = Qnil;
|
758
771
|
|
759
772
|
while (left > 0) {
|
760
773
|
backend->base.op_count++;
|
761
|
-
ssize_t
|
762
|
-
if (
|
774
|
+
ssize_t result = send(fd, buffer.ptr, left, flags_int);
|
775
|
+
if (result < 0) {
|
763
776
|
int e = errno;
|
764
777
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
765
778
|
|
766
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
779
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_WRITE);
|
767
780
|
|
768
781
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
769
782
|
}
|
770
783
|
else {
|
771
|
-
|
772
|
-
left -=
|
784
|
+
buffer.ptr += result;
|
785
|
+
left -= result;
|
773
786
|
}
|
774
787
|
}
|
775
788
|
|
@@ -782,7 +795,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
782
795
|
RB_GC_GUARD(watcher.fiber);
|
783
796
|
RB_GC_GUARD(switchpoint_result);
|
784
797
|
|
785
|
-
return INT2NUM(len);
|
798
|
+
return INT2NUM(buffer.len);
|
786
799
|
error:
|
787
800
|
return RAISE_EXCEPTION(switchpoint_result);
|
788
801
|
}
|
@@ -837,41 +850,30 @@ VALUE libev_wait_rw_fd_with_watcher(Backend_t *backend, int r_fd, int w_fd, stru
|
|
837
850
|
return switchpoint_result;
|
838
851
|
}
|
839
852
|
|
840
|
-
|
841
|
-
|
842
|
-
|
843
853
|
#ifdef POLYPHONY_LINUX
|
844
854
|
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
845
855
|
Backend_t *backend;
|
846
856
|
struct libev_rw_io watcher;
|
847
857
|
VALUE switchpoint_result = Qnil;
|
848
|
-
|
858
|
+
int src_fd;
|
859
|
+
int dest_fd;
|
849
860
|
rb_io_t *src_fptr;
|
850
861
|
rb_io_t *dest_fptr;
|
851
862
|
int len;
|
852
863
|
|
853
864
|
GetBackend(self, backend);
|
854
|
-
|
855
|
-
|
856
|
-
if (underlying_io != Qnil) src = underlying_io;
|
857
|
-
GetOpenFile(src, src_fptr);
|
858
|
-
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
859
|
-
|
860
|
-
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
861
|
-
if (underlying_io != Qnil) dest = underlying_io;
|
862
|
-
dest = rb_io_get_write_io(dest);
|
863
|
-
GetOpenFile(dest, dest_fptr);
|
864
|
-
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
865
|
-
|
865
|
+
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
866
|
+
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
866
867
|
watcher.ctx.fiber = Qnil;
|
868
|
+
|
867
869
|
while (1) {
|
868
870
|
backend->base.op_count++;
|
869
|
-
len = splice(
|
871
|
+
len = splice(src_fd, 0, dest_fd, 0, NUM2INT(maxlen), 0);
|
870
872
|
if (len < 0) {
|
871
873
|
int e = errno;
|
872
874
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
873
875
|
|
874
|
-
switchpoint_result = libev_wait_rw_fd_with_watcher(backend,
|
876
|
+
switchpoint_result = libev_wait_rw_fd_with_watcher(backend, src_fd, dest_fd, &watcher);
|
875
877
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
876
878
|
}
|
877
879
|
else {
|
@@ -896,34 +898,26 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
896
898
|
Backend_t *backend;
|
897
899
|
struct libev_rw_io watcher;
|
898
900
|
VALUE switchpoint_result = Qnil;
|
899
|
-
|
901
|
+
int src_fd;
|
902
|
+
int dest_fd;
|
900
903
|
rb_io_t *src_fptr;
|
901
904
|
rb_io_t *dest_fptr;
|
902
905
|
int len;
|
903
906
|
int total = 0;
|
904
907
|
|
905
908
|
GetBackend(self, backend);
|
906
|
-
|
907
|
-
|
908
|
-
if (underlying_io != Qnil) src = underlying_io;
|
909
|
-
GetOpenFile(src, src_fptr);
|
910
|
-
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
911
|
-
|
912
|
-
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
913
|
-
if (underlying_io != Qnil) dest = underlying_io;
|
914
|
-
dest = rb_io_get_write_io(dest);
|
915
|
-
GetOpenFile(dest, dest_fptr);
|
916
|
-
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
917
|
-
|
909
|
+
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
910
|
+
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
918
911
|
watcher.ctx.fiber = Qnil;
|
912
|
+
|
919
913
|
while (1) {
|
920
914
|
backend->base.op_count++;
|
921
|
-
len = splice(
|
915
|
+
len = splice(src_fd, 0, dest_fd, 0, NUM2INT(maxlen), 0);
|
922
916
|
if (len < 0) {
|
923
917
|
int e = errno;
|
924
918
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
925
919
|
|
926
|
-
switchpoint_result = libev_wait_rw_fd_with_watcher(backend,
|
920
|
+
switchpoint_result = libev_wait_rw_fd_with_watcher(backend, src_fd, dest_fd, &watcher);
|
927
921
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
928
922
|
}
|
929
923
|
else if (len == 0) {
|
@@ -946,12 +940,58 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
946
940
|
error:
|
947
941
|
return RAISE_EXCEPTION(switchpoint_result);
|
948
942
|
}
|
943
|
+
|
944
|
+
VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
945
|
+
Backend_t *backend;
|
946
|
+
struct libev_rw_io watcher;
|
947
|
+
VALUE switchpoint_result = Qnil;
|
948
|
+
int src_fd;
|
949
|
+
int dest_fd;
|
950
|
+
rb_io_t *src_fptr;
|
951
|
+
rb_io_t *dest_fptr;
|
952
|
+
int len;
|
953
|
+
|
954
|
+
GetBackend(self, backend);
|
955
|
+
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
956
|
+
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
957
|
+
watcher.ctx.fiber = Qnil;
|
958
|
+
|
959
|
+
while (1) {
|
960
|
+
backend->base.op_count++;
|
961
|
+
len = tee(src_fd, dest_fd, NUM2INT(maxlen), 0);
|
962
|
+
if (len < 0) {
|
963
|
+
int e = errno;
|
964
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
965
|
+
|
966
|
+
switchpoint_result = libev_wait_rw_fd_with_watcher(backend, src_fd, dest_fd, &watcher);
|
967
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
968
|
+
}
|
969
|
+
else {
|
970
|
+
break;
|
971
|
+
}
|
972
|
+
}
|
973
|
+
|
974
|
+
if (watcher.ctx.fiber == Qnil) {
|
975
|
+
switchpoint_result = backend_snooze(&backend->base);
|
976
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
977
|
+
}
|
978
|
+
|
979
|
+
RB_GC_GUARD(watcher.ctx.fiber);
|
980
|
+
RB_GC_GUARD(switchpoint_result);
|
981
|
+
|
982
|
+
return INT2NUM(len);
|
983
|
+
error:
|
984
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
985
|
+
}
|
986
|
+
|
949
987
|
#else
|
988
|
+
|
950
989
|
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
951
990
|
Backend_t *backend;
|
952
991
|
struct libev_io watcher;
|
953
992
|
VALUE switchpoint_result = Qnil;
|
954
|
-
|
993
|
+
int src_fd;
|
994
|
+
int dest_fd;
|
955
995
|
rb_io_t *src_fptr;
|
956
996
|
rb_io_t *dest_fptr;
|
957
997
|
int len = NUM2INT(maxlen);
|
@@ -961,28 +1001,18 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
961
1001
|
int total = 0;
|
962
1002
|
|
963
1003
|
GetBackend(self, backend);
|
964
|
-
|
965
|
-
|
966
|
-
if (underlying_io != Qnil) src = underlying_io;
|
967
|
-
GetOpenFile(src, src_fptr);
|
968
|
-
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
969
|
-
|
970
|
-
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
971
|
-
if (underlying_io != Qnil) dest = underlying_io;
|
972
|
-
dest = rb_io_get_write_io(dest);
|
973
|
-
GetOpenFile(dest, dest_fptr);
|
974
|
-
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
975
|
-
|
1004
|
+
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
1005
|
+
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
976
1006
|
watcher.fiber = Qnil;
|
977
1007
|
|
978
1008
|
while (1) {
|
979
1009
|
backend->base.op_count++;
|
980
|
-
ssize_t n = read(
|
1010
|
+
ssize_t n = read(src_fd, buf, len);
|
981
1011
|
if (n < 0) {
|
982
1012
|
int e = errno;
|
983
1013
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
984
1014
|
|
985
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
1015
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fd, &watcher, EV_READ);
|
986
1016
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
987
1017
|
}
|
988
1018
|
else {
|
@@ -993,12 +1023,12 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
993
1023
|
|
994
1024
|
while (left > 0) {
|
995
1025
|
backend->base.op_count++;
|
996
|
-
ssize_t n = write(
|
1026
|
+
ssize_t n = write(dest_fd, buf, left);
|
997
1027
|
if (n < 0) {
|
998
1028
|
int e = errno;
|
999
1029
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
1000
1030
|
|
1001
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
1031
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fd, &watcher, EV_WRITE);
|
1002
1032
|
|
1003
1033
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1004
1034
|
}
|
@@ -1026,7 +1056,8 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1026
1056
|
Backend_t *backend;
|
1027
1057
|
struct libev_io watcher;
|
1028
1058
|
VALUE switchpoint_result = Qnil;
|
1029
|
-
|
1059
|
+
int src_fd;
|
1060
|
+
int dest_fd;
|
1030
1061
|
rb_io_t *src_fptr;
|
1031
1062
|
rb_io_t *dest_fptr;
|
1032
1063
|
int len = NUM2INT(maxlen);
|
@@ -1036,30 +1067,20 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1036
1067
|
int total = 0;
|
1037
1068
|
|
1038
1069
|
GetBackend(self, backend);
|
1039
|
-
|
1040
|
-
|
1041
|
-
if (underlying_io != Qnil) src = underlying_io;
|
1042
|
-
GetOpenFile(src, src_fptr);
|
1043
|
-
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
1044
|
-
|
1045
|
-
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
1046
|
-
if (underlying_io != Qnil) dest = underlying_io;
|
1047
|
-
dest = rb_io_get_write_io(dest);
|
1048
|
-
GetOpenFile(dest, dest_fptr);
|
1049
|
-
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
1050
|
-
|
1070
|
+
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
1071
|
+
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
1051
1072
|
watcher.fiber = Qnil;
|
1052
1073
|
|
1053
1074
|
while (1) {
|
1054
1075
|
char *ptr = buf;
|
1055
1076
|
while (1) {
|
1056
1077
|
backend->base.op_count++;
|
1057
|
-
ssize_t n = read(
|
1078
|
+
ssize_t n = read(src_fd, ptr, len);
|
1058
1079
|
if (n < 0) {
|
1059
1080
|
int e = errno;
|
1060
1081
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
1061
1082
|
|
1062
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
1083
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fd, &watcher, EV_READ);
|
1063
1084
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1064
1085
|
}
|
1065
1086
|
else if (n == 0) goto done;
|
@@ -1072,12 +1093,12 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1072
1093
|
|
1073
1094
|
while (left > 0) {
|
1074
1095
|
backend->base.op_count++;
|
1075
|
-
ssize_t n = write(
|
1096
|
+
ssize_t n = write(dest_fd, ptr, left);
|
1076
1097
|
if (n < 0) {
|
1077
1098
|
int e = errno;
|
1078
1099
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
1079
1100
|
|
1080
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend,
|
1101
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fd, &watcher, EV_WRITE);
|
1081
1102
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1082
1103
|
}
|
1083
1104
|
else {
|
@@ -1105,15 +1126,15 @@ error:
|
|
1105
1126
|
|
1106
1127
|
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
1107
1128
|
Backend_t *backend;
|
1129
|
+
int fd;
|
1108
1130
|
rb_io_t *fptr;
|
1109
|
-
int
|
1110
|
-
|
1111
|
-
if (underlying_io != Qnil) io = underlying_io;
|
1131
|
+
int write_mode = RTEST(write);
|
1132
|
+
int events = write_mode ? EV_WRITE : EV_READ;
|
1112
1133
|
GetBackend(self, backend);
|
1113
|
-
|
1134
|
+
fd = fd_from_io(io, &fptr, write_mode, 0);
|
1114
1135
|
|
1115
1136
|
backend->base.op_count++;
|
1116
|
-
return libev_wait_fd(backend,
|
1137
|
+
return libev_wait_fd(backend, fd, events, 1);
|
1117
1138
|
}
|
1118
1139
|
|
1119
1140
|
struct libev_timer {
|
@@ -1460,19 +1481,13 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1460
1481
|
int err = 0;
|
1461
1482
|
VALUE result = Qnil;
|
1462
1483
|
|
1484
|
+
int src_fd;
|
1485
|
+
int dest_fd;
|
1463
1486
|
rb_io_t *src_fptr;
|
1464
1487
|
rb_io_t *dest_fptr;
|
1465
1488
|
|
1466
|
-
|
1467
|
-
|
1468
|
-
GetOpenFile(src, src_fptr);
|
1469
|
-
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
1470
|
-
|
1471
|
-
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
1472
|
-
if (underlying_io != Qnil) dest = underlying_io;
|
1473
|
-
dest = rb_io_get_write_io(dest);
|
1474
|
-
GetOpenFile(dest, dest_fptr);
|
1475
|
-
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
1489
|
+
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
1490
|
+
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
1476
1491
|
|
1477
1492
|
struct libev_rw_io watcher;
|
1478
1493
|
watcher.ctx.fiber = Qnil;
|
@@ -1490,12 +1505,12 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1490
1505
|
fcntl(pipefd[1], F_SETFL, O_NONBLOCK);
|
1491
1506
|
|
1492
1507
|
if (prefix != Qnil) {
|
1493
|
-
err = splice_chunks_write(backend,
|
1508
|
+
err = splice_chunks_write(backend, dest_fd, prefix, &watcher, &result);
|
1494
1509
|
if (err == -1) goto error; else if (err) goto syscallerror;
|
1495
1510
|
}
|
1496
1511
|
while (1) {
|
1497
1512
|
int chunk_len = 0;
|
1498
|
-
err = splice_chunks_splice(backend,
|
1513
|
+
err = splice_chunks_splice(backend, src_fd, pipefd[1], maxlen, &watcher, &result, &chunk_len);
|
1499
1514
|
if (err == -1) goto error; else if (err) goto syscallerror;
|
1500
1515
|
if (chunk_len == 0) break;
|
1501
1516
|
|
@@ -1504,14 +1519,14 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1504
1519
|
|
1505
1520
|
if (chunk_prefix != Qnil) {
|
1506
1521
|
VALUE str = (TYPE(chunk_prefix) == T_STRING) ? chunk_prefix : rb_funcall(chunk_prefix, ID_call, 1, chunk_len_value);
|
1507
|
-
int err = splice_chunks_write(backend,
|
1522
|
+
int err = splice_chunks_write(backend, dest_fd, str, &watcher, &result);
|
1508
1523
|
if (err == -1) goto error; else if (err) goto syscallerror;
|
1509
1524
|
}
|
1510
1525
|
|
1511
1526
|
int left = chunk_len;
|
1512
1527
|
while (left > 0) {
|
1513
1528
|
int len;
|
1514
|
-
err = splice_chunks_splice(backend, pipefd[0],
|
1529
|
+
err = splice_chunks_splice(backend, pipefd[0], dest_fd, left, &watcher, &result, &len);
|
1515
1530
|
if (err == -1) goto error; else if (err) goto syscallerror;
|
1516
1531
|
|
1517
1532
|
left -= len;
|
@@ -1519,13 +1534,13 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1519
1534
|
|
1520
1535
|
if (chunk_postfix != Qnil) {
|
1521
1536
|
VALUE str = (TYPE(chunk_postfix) == T_STRING) ? chunk_postfix : rb_funcall(chunk_postfix, ID_call, 1, chunk_len_value);
|
1522
|
-
int err = splice_chunks_write(backend,
|
1537
|
+
int err = splice_chunks_write(backend, dest_fd, str, &watcher, &result);
|
1523
1538
|
if (err == -1) goto error; else if (err) goto syscallerror;
|
1524
1539
|
}
|
1525
1540
|
}
|
1526
1541
|
|
1527
1542
|
if (postfix != Qnil) {
|
1528
|
-
int err = splice_chunks_write(backend,
|
1543
|
+
int err = splice_chunks_write(backend, dest_fd, postfix, &watcher, &result);
|
1529
1544
|
if (err == -1) goto error; else if (err) goto syscallerror;
|
1530
1545
|
}
|
1531
1546
|
|