polyphony 0.71 → 0.72
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/FUNDING.yml +1 -0
- data/CHANGELOG.md +18 -4
- data/Gemfile.lock +1 -1
- data/TODO.md +1 -1
- data/bin/pdbg +1 -1
- data/bin/polyphony-debug +0 -0
- data/bin/stress.rb +0 -0
- data/bin/test +0 -0
- data/docs/_user-guide/all-about-timers.md +1 -1
- data/docs/api-reference/fiber.md +2 -2
- data/docs/faq.md +1 -1
- data/docs/getting-started/overview.md +8 -8
- data/docs/getting-started/tutorial.md +3 -3
- data/docs/main-concepts/concurrency.md +1 -1
- data/docs/main-concepts/extending.md +3 -3
- data/docs/main-concepts/fiber-scheduling.md +1 -1
- data/examples/core/calc.rb +37 -0
- data/examples/core/calc_with_restart.rb +40 -0
- data/examples/core/calc_with_supervise.rb +37 -0
- data/examples/core/message_based_supervision.rb +1 -1
- data/examples/io/rack_server.rb +1 -1
- data/examples/io/tunnel.rb +1 -1
- data/examples/performance/fiber_transfer.rb +1 -1
- data/examples/performance/line_splitting.rb +1 -1
- data/examples/performance/thread-vs-fiber/compare.rb +1 -1
- data/ext/polyphony/backend_common.c +8 -8
- data/ext/polyphony/backend_io_uring.c +26 -33
- data/ext/polyphony/backend_io_uring_context.c +1 -1
- data/ext/polyphony/backend_io_uring_context.h +1 -1
- data/ext/polyphony/backend_libev.c +11 -11
- data/ext/polyphony/extconf.rb +24 -13
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/runqueue_ring_buffer.c +3 -2
- data/lib/polyphony/adapters/irb.rb +11 -1
- data/lib/polyphony/core/global_api.rb +3 -3
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/debugger.rb +3 -3
- data/lib/polyphony/extensions/fiber.rb +19 -8
- data/lib/polyphony/extensions/io.rb +2 -2
- data/lib/polyphony/extensions/openssl.rb +20 -5
- data/lib/polyphony/extensions/socket.rb +3 -4
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/coverage.rb +2 -2
- data/test/test_backend.rb +12 -12
- data/test/test_event.rb +1 -1
- data/test/test_ext.rb +1 -1
- data/test/test_fiber.rb +31 -7
- data/test/test_global_api.rb +2 -2
- data/test/test_io.rb +3 -3
- data/test/test_queue.rb +6 -6
- data/test/test_socket.rb +12 -10
- data/test/test_supervise.rb +85 -0
- data/test/test_sync.rb +2 -2
- data/test/test_thread.rb +22 -2
- data/test/test_thread_pool.rb +1 -1
- data/test/test_throttler.rb +1 -1
- data/test/test_timer.rb +2 -2
- data/test/test_trace.rb +1 -1
- metadata +7 -3
@@ -141,7 +141,7 @@ static inline void io_uring_backend_handle_completion(struct io_uring_cqe *cqe,
|
|
141
141
|
context_store_release(&backend->store, ctx);
|
142
142
|
}
|
143
143
|
|
144
|
-
// adapted from io_uring_peek_batch_cqe in queue.c
|
144
|
+
// adapted from io_uring_peek_batch_cqe in queue.c
|
145
145
|
// this peeks at cqes and handles each available cqe
|
146
146
|
void io_uring_backend_handle_ready_cqes(Backend_t *backend) {
|
147
147
|
struct io_uring *ring = &backend->ring;
|
@@ -200,19 +200,12 @@ inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
|
200
200
|
}
|
201
201
|
|
202
202
|
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_enter, rb_fiber_current());
|
203
|
-
|
204
|
-
// printf(
|
205
|
-
// "io_uring_poll(blocking_mode: %d, pending: %d, taken: %d, available: %d, runqueue: %d\n",
|
206
|
-
// is_blocking,
|
207
|
-
// backend->base.pending_count,
|
208
|
-
// backend->store.taken_count,
|
209
|
-
// backend->store.available_count,
|
210
|
-
// backend->base.runqueue.entries.count
|
211
|
-
// );
|
203
|
+
|
212
204
|
if (is_blocking) io_uring_backend_poll(backend);
|
213
205
|
io_uring_backend_handle_ready_cqes(backend);
|
214
|
-
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_leave, rb_fiber_current());
|
215
206
|
|
207
|
+
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_leave, rb_fiber_current());
|
208
|
+
|
216
209
|
return self;
|
217
210
|
}
|
218
211
|
|
@@ -255,7 +248,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
255
248
|
io_uring_prep_nop(sqe);
|
256
249
|
backend->pending_sqes = 0;
|
257
250
|
io_uring_submit(&backend->ring);
|
258
|
-
|
251
|
+
|
259
252
|
return Qtrue;
|
260
253
|
}
|
261
254
|
|
@@ -411,7 +404,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
411
404
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
412
405
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
413
406
|
io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
|
414
|
-
|
407
|
+
|
415
408
|
ssize_t result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
416
409
|
int completed = context_store_release(&backend->store, ctx);
|
417
410
|
if (!completed) {
|
@@ -461,7 +454,7 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
461
454
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
462
455
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
463
456
|
io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
|
464
|
-
|
457
|
+
|
465
458
|
ssize_t result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
466
459
|
int completed = context_store_release(&backend->store, ctx);
|
467
460
|
if (!completed) {
|
@@ -507,7 +500,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
507
500
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITE);
|
508
501
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
509
502
|
io_uring_prep_write(sqe, fptr->fd, buf, left, 0);
|
510
|
-
|
503
|
+
|
511
504
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
512
505
|
int completed = context_store_release(&backend->store, ctx);
|
513
506
|
if (!completed) {
|
@@ -516,7 +509,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
516
509
|
return resume_value;
|
517
510
|
}
|
518
511
|
RB_GC_GUARD(resume_value);
|
519
|
-
|
512
|
+
|
520
513
|
if (result < 0)
|
521
514
|
rb_syserr_fail(-result, strerror(-result));
|
522
515
|
else {
|
@@ -559,7 +552,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
559
552
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITEV);
|
560
553
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
561
554
|
io_uring_prep_writev(sqe, fptr->fd, iov_ptr, iov_count, -1);
|
562
|
-
|
555
|
+
|
563
556
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
564
557
|
int completed = context_store_release(&backend->store, ctx);
|
565
558
|
if (!completed) {
|
@@ -635,7 +628,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
635
628
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
636
629
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
637
630
|
io_uring_prep_recv(sqe, fptr->fd, buf, len - total, 0);
|
638
|
-
|
631
|
+
|
639
632
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
640
633
|
int completed = context_store_release(&backend->store, ctx);
|
641
634
|
if (!completed) {
|
@@ -685,7 +678,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
685
678
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
686
679
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
687
680
|
io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
|
688
|
-
|
681
|
+
|
689
682
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
690
683
|
int completed = context_store_release(&backend->store, ctx);
|
691
684
|
if (!completed) {
|
@@ -734,7 +727,7 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method)
|
|
734
727
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
735
728
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
736
729
|
io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
|
737
|
-
|
730
|
+
|
738
731
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
739
732
|
int completed = context_store_release(&backend->store, ctx);
|
740
733
|
if (!completed) {
|
@@ -780,7 +773,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
780
773
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SEND);
|
781
774
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
782
775
|
io_uring_prep_send(sqe, fptr->fd, buf, left, flags_int);
|
783
|
-
|
776
|
+
|
784
777
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
785
778
|
int completed = context_store_release(&backend->store, ctx);
|
786
779
|
if (!completed) {
|
@@ -817,7 +810,7 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE soc
|
|
817
810
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_ACCEPT);
|
818
811
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
819
812
|
io_uring_prep_accept(sqe, fptr->fd, &addr, &len, 0);
|
820
|
-
|
813
|
+
|
821
814
|
int fd = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
822
815
|
int completed = context_store_release(&backend->store, ctx);
|
823
816
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -888,7 +881,7 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
888
881
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
|
889
882
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
890
883
|
io_uring_prep_splice(sqe, src_fptr->fd, -1, dest_fptr->fd, -1, NUM2INT(maxlen), 0);
|
891
|
-
|
884
|
+
|
892
885
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
893
886
|
int completed = context_store_release(&backend->store, ctx);
|
894
887
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -944,7 +937,7 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
944
937
|
RAISE_IF_EXCEPTION(resume_value);
|
945
938
|
if (!completed) return resume_value;
|
946
939
|
RB_GC_GUARD(resume_value);
|
947
|
-
|
940
|
+
|
948
941
|
if (result < 0) rb_syserr_fail(-result, strerror(-result));
|
949
942
|
return sock;
|
950
943
|
}
|
@@ -981,7 +974,7 @@ inline struct __kernel_timespec duration_to_timespec(VALUE duration) {
|
|
981
974
|
int io_uring_backend_submit_timeout_and_await(Backend_t *backend, double duration, VALUE *resume_value) {
|
982
975
|
struct __kernel_timespec ts = double_to_timespec(duration);
|
983
976
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
984
|
-
|
977
|
+
|
985
978
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
|
986
979
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
987
980
|
io_uring_backend_defer_submit_and_await(backend, sqe, ctx, resume_value);
|
@@ -1010,7 +1003,7 @@ VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
1010
1003
|
if (next_time == 0.) next_time = current_time() + interval_d;
|
1011
1004
|
double sleep_duration = next_time - now;
|
1012
1005
|
if (sleep_duration < 0) sleep_duration = 0;
|
1013
|
-
|
1006
|
+
|
1014
1007
|
VALUE resume_value = Qnil;
|
1015
1008
|
int completed = io_uring_backend_submit_timeout_and_await(backend, sleep_duration, &resume_value);
|
1016
1009
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -1051,7 +1044,7 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1051
1044
|
VALUE exception;
|
1052
1045
|
VALUE move_on_value = Qnil;
|
1053
1046
|
rb_scan_args(argc, argv, "21", &duration, &exception, &move_on_value);
|
1054
|
-
|
1047
|
+
|
1055
1048
|
struct __kernel_timespec ts = duration_to_timespec(duration);
|
1056
1049
|
Backend_t *backend;
|
1057
1050
|
GetBackend(self, backend);
|
@@ -1059,7 +1052,7 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1059
1052
|
VALUE timeout = rb_funcall(cTimeoutException, ID_new, 0);
|
1060
1053
|
|
1061
1054
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
1062
|
-
|
1055
|
+
|
1063
1056
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
|
1064
1057
|
ctx->resume_value = timeout;
|
1065
1058
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
@@ -1094,7 +1087,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1094
1087
|
RAISE_IF_EXCEPTION(resume_value);
|
1095
1088
|
RB_GC_GUARD(resume_value);
|
1096
1089
|
}
|
1097
|
-
|
1090
|
+
|
1098
1091
|
int status;
|
1099
1092
|
pid_t ret = waitpid(pid_int, &status, WNOHANG);
|
1100
1093
|
if (ret < 0) {
|
@@ -1244,7 +1237,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1244
1237
|
}
|
1245
1238
|
rb_raise(rb_eRuntimeError, "Invalid op specified or bad op arity");
|
1246
1239
|
}
|
1247
|
-
|
1240
|
+
|
1248
1241
|
io_uring_sqe_set_data(last_sqe, ctx);
|
1249
1242
|
unsigned int flags = (i == (argc - 1)) ? IOSQE_ASYNC : IOSQE_ASYNC | IOSQE_IO_LINK;
|
1250
1243
|
io_uring_sqe_set_flags(last_sqe, flags);
|
@@ -1259,7 +1252,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1259
1252
|
int completed = context_store_release(&backend->store, ctx);
|
1260
1253
|
if (!completed) {
|
1261
1254
|
Backend_chain_ctx_attach_buffers(ctx, argc, argv);
|
1262
|
-
|
1255
|
+
|
1263
1256
|
// op was not completed (an exception was raised), so we need to cancel it
|
1264
1257
|
ctx->result = -ECANCELED;
|
1265
1258
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
@@ -1269,7 +1262,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1269
1262
|
RAISE_IF_EXCEPTION(resume_value);
|
1270
1263
|
return resume_value;
|
1271
1264
|
}
|
1272
|
-
|
1265
|
+
|
1273
1266
|
RB_GC_GUARD(resume_value);
|
1274
1267
|
return INT2NUM(result);
|
1275
1268
|
}
|
@@ -1404,7 +1397,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1404
1397
|
|
1405
1398
|
SPLICE_CHUNKS_AWAIT_OPS(backend, &ctx, &chunk_len, &switchpoint_result);
|
1406
1399
|
if (chunk_len == 0) break;
|
1407
|
-
|
1400
|
+
|
1408
1401
|
total += chunk_len;
|
1409
1402
|
chunk_len_value = INT2NUM(chunk_len);
|
1410
1403
|
|
@@ -64,7 +64,7 @@ inline int context_store_release(op_context_store_t *store, op_context_t *ctx) {
|
|
64
64
|
// printf("release %p %d (%s, ref_count: %d)\n", ctx, ctx->id, op_type_to_str(ctx->type), ctx->ref_count);
|
65
65
|
|
66
66
|
assert(ctx->ref_count);
|
67
|
-
|
67
|
+
|
68
68
|
ctx->ref_count--;
|
69
69
|
if (ctx->ref_count) return 0;
|
70
70
|
|
@@ -118,7 +118,7 @@ inline struct ev_loop *libev_new_loop() {
|
|
118
118
|
|
119
119
|
static VALUE Backend_initialize(VALUE self) {
|
120
120
|
Backend_t *backend;
|
121
|
-
|
121
|
+
|
122
122
|
GetBackend(self, backend);
|
123
123
|
|
124
124
|
backend_base_initialize(&backend->base);
|
@@ -188,7 +188,7 @@ inline void Backend_unschedule_fiber(VALUE self, VALUE fiber) {
|
|
188
188
|
Backend_t *backend;
|
189
189
|
GetBackend(self, backend);
|
190
190
|
|
191
|
-
runqueue_delete(&backend->base.runqueue, fiber);
|
191
|
+
runqueue_delete(&backend->base.runqueue, fiber);
|
192
192
|
}
|
193
193
|
|
194
194
|
inline VALUE Backend_switch_fiber(VALUE self) {
|
@@ -971,7 +971,7 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
971
971
|
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
972
972
|
|
973
973
|
watcher.fiber = Qnil;
|
974
|
-
|
974
|
+
|
975
975
|
while (1) {
|
976
976
|
backend->base.op_count++;
|
977
977
|
ssize_t n = read(src_fptr->fd, buf, len);
|
@@ -1047,7 +1047,7 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1047
1047
|
|
1048
1048
|
watcher.fiber = Qnil;
|
1049
1049
|
|
1050
|
-
while (1) {
|
1050
|
+
while (1) {
|
1051
1051
|
char *ptr = buf;
|
1052
1052
|
while (1) {
|
1053
1053
|
backend->base.op_count++;
|
@@ -1159,8 +1159,8 @@ noreturn VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
1159
1159
|
if (next_time == 0.) next_time = current_time() + interval_d;
|
1160
1160
|
double sleep_duration = next_time - now;
|
1161
1161
|
if (sleep_duration < 0) sleep_duration = 0;
|
1162
|
-
|
1163
|
-
VALUE switchpoint_result = Qnil;
|
1162
|
+
|
1163
|
+
VALUE switchpoint_result = Qnil;
|
1164
1164
|
ev_timer_init(&watcher.timer, Backend_timer_callback, sleep_duration, 0.);
|
1165
1165
|
ev_timer_start(backend->ev_loop, &watcher.timer);
|
1166
1166
|
backend->base.op_count++;
|
@@ -1219,7 +1219,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
|
|
1219
1219
|
|
1220
1220
|
struct Backend_timeout_ctx timeout_ctx = {backend, &watcher};
|
1221
1221
|
result = rb_ensure(Backend_timeout_ensure_safe, Qnil, Backend_timeout_ensure, (VALUE)&timeout_ctx);
|
1222
|
-
|
1222
|
+
|
1223
1223
|
if (result == timeout) {
|
1224
1224
|
if (exception == Qnil) return move_on_value;
|
1225
1225
|
RAISE_EXCEPTION(backend_timeout_exception(exception));
|
@@ -1337,7 +1337,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1337
1337
|
else
|
1338
1338
|
rb_raise(rb_eRuntimeError, "Invalid op specified or bad op arity");
|
1339
1339
|
}
|
1340
|
-
|
1340
|
+
|
1341
1341
|
RB_GC_GUARD(result);
|
1342
1342
|
return result;
|
1343
1343
|
}
|
@@ -1386,14 +1386,14 @@ inline int splice_chunks_write(Backend_t *backend, int fd, VALUE str, struct lib
|
|
1386
1386
|
return 0;
|
1387
1387
|
}
|
1388
1388
|
|
1389
|
-
static inline int splice_chunks_splice(Backend_t *backend, int src_fd, int dest_fd, int maxlen,
|
1389
|
+
static inline int splice_chunks_splice(Backend_t *backend, int src_fd, int dest_fd, int maxlen,
|
1390
1390
|
struct libev_rw_io *watcher, VALUE *result, int *chunk_len) {
|
1391
1391
|
#ifdef POLYPHONY_LINUX
|
1392
1392
|
backend->base.op_count++;
|
1393
1393
|
while (1) {
|
1394
1394
|
*chunk_len = splice(src_fd, 0, dest_fd, 0, maxlen, 0);
|
1395
1395
|
if (*chunk_len >= 0) return 0;
|
1396
|
-
|
1396
|
+
|
1397
1397
|
int err = errno;
|
1398
1398
|
if (err != EWOULDBLOCK && err != EAGAIN) return err;
|
1399
1399
|
|
@@ -1489,7 +1489,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1489
1489
|
err = splice_chunks_splice(backend, src_fptr->fd, pipefd[1], maxlen, &watcher, &result, &chunk_len);
|
1490
1490
|
if (err == -1) goto error; else if (err) goto syscallerror;
|
1491
1491
|
if (chunk_len == 0) break;
|
1492
|
-
|
1492
|
+
|
1493
1493
|
total += chunk_len;
|
1494
1494
|
chunk_len_value = INT2NUM(chunk_len);
|
1495
1495
|
|
data/ext/polyphony/extconf.rb
CHANGED
@@ -3,32 +3,43 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'mkmf'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
|
7
|
+
KERNEL_INFO_RE = /Linux (\d)\.(\d+)\.(?:\d+)\-(?:\d+\-)?(\w+)/
|
8
|
+
def get_config
|
9
|
+
config = { linux: !!(RUBY_PLATFORM =~ /linux/) }
|
10
|
+
return config if !config[:linux]
|
11
|
+
|
12
|
+
kernel_info = `uname -sr`
|
13
|
+
m = kernel_info.match(KERNEL_INFO_RE)
|
14
|
+
raise "Could not parse Linux kernel information (#{kernel_info.inspect})" if !m
|
15
|
+
|
16
|
+
version, major_revision, distribution = m[1].to_i, m[2].to_i, m[3]
|
17
|
+
config[:pidfd_open] = (version == 5) && (major_revision >= 3)
|
18
|
+
|
19
|
+
force_libev = ENV['POLYPHONY_USE_LIBEV'] != nil
|
20
|
+
config[:io_uring] = !force_libev &&
|
21
|
+
(version == 5) && (major_revision >= 6) && (distribution != 'linuxkit')
|
22
|
+
config
|
15
23
|
end
|
16
24
|
|
17
|
-
|
18
|
-
|
25
|
+
config = get_config
|
26
|
+
puts "Building Polyphony... (#{config.inspect})"
|
27
|
+
|
28
|
+
$defs << '-DPOLYPHONY_USE_PIDFD_OPEN' if config[:pidfd_open]
|
29
|
+
if config[:io_uring]
|
19
30
|
$defs << "-DPOLYPHONY_BACKEND_LIBURING"
|
20
31
|
$defs << "-DPOLYPHONY_UNSET_NONBLOCK" if RUBY_VERSION =~ /^3/
|
21
32
|
$CFLAGS << " -Wno-pointer-arith"
|
22
33
|
else
|
23
34
|
$defs << "-DPOLYPHONY_BACKEND_LIBEV"
|
24
|
-
$defs << "-DPOLYPHONY_LINUX" if linux
|
35
|
+
$defs << "-DPOLYPHONY_LINUX" if config[:linux]
|
25
36
|
$defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
|
26
37
|
$defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
|
27
38
|
$defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
|
28
39
|
$defs << '-DEV_USE_EPOLL' if have_header('sys/epoll.h')
|
29
40
|
$defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
|
30
41
|
$defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
|
31
|
-
$defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
|
42
|
+
$defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
|
32
43
|
|
33
44
|
$CFLAGS << " -Wno-comment"
|
34
45
|
$CFLAGS << " -Wno-unused-result"
|
data/ext/polyphony/queue.c
CHANGED
@@ -162,12 +162,12 @@ VALUE Queue_cap(VALUE self, VALUE cap) {
|
|
162
162
|
Queue_t *queue;
|
163
163
|
GetQueue(self, queue);
|
164
164
|
queue->capacity = new_capacity;
|
165
|
-
|
165
|
+
|
166
166
|
if (queue->capacity)
|
167
167
|
queue_schedule_blocked_fibers_to_capacity(queue);
|
168
168
|
else
|
169
169
|
queue_schedule_all_blocked_fibers(&queue->push_queue);
|
170
|
-
|
170
|
+
|
171
171
|
return self;
|
172
172
|
}
|
173
173
|
|
@@ -61,8 +61,9 @@ inline void runqueue_ring_buffer_push(runqueue_ring_buffer *buffer, VALUE fiber,
|
|
61
61
|
|
62
62
|
inline void runqueue_ring_buffer_mark(runqueue_ring_buffer *buffer) {
|
63
63
|
for (unsigned int i = 0; i < buffer->count; i++) {
|
64
|
-
|
65
|
-
rb_gc_mark(
|
64
|
+
runqueue_entry entry = buffer->entries[(buffer->head + i) % buffer->size];
|
65
|
+
rb_gc_mark(entry.fiber);
|
66
|
+
rb_gc_mark(entry.value);
|
66
67
|
}
|
67
68
|
}
|
68
69
|
|
@@ -3,26 +3,36 @@
|
|
3
3
|
require 'polyphony'
|
4
4
|
|
5
5
|
if Object.constants.include?(:Reline)
|
6
|
+
puts "reline"
|
6
7
|
class Reline::ANSI
|
7
8
|
def self.select(read_ios = [], write_ios = [], error_ios = [], timeout = nil)
|
8
|
-
p [:select, read_ios]
|
9
|
+
# p [:select, read_ios, timeout]
|
10
|
+
# puts caller.join("\n")
|
9
11
|
raise if read_ios.size > 1
|
10
12
|
raise if write_ios.size > 0
|
11
13
|
raise if error_ios.size > 0
|
12
14
|
|
15
|
+
# p 1
|
13
16
|
fiber = Fiber.current
|
14
17
|
timer = spin do
|
15
18
|
sleep timeout
|
16
19
|
fiber.cancel
|
17
20
|
end
|
21
|
+
# p 2
|
18
22
|
read_ios.each do |io|
|
23
|
+
# p wait: io
|
19
24
|
Polyphony.backend_wait_io(io, false)
|
25
|
+
# p :done_wait
|
20
26
|
return [io]
|
21
27
|
end
|
28
|
+
# p 3
|
22
29
|
rescue Polyphony::Cancel
|
30
|
+
# p :cancel
|
23
31
|
return nil
|
24
32
|
ensure
|
33
|
+
# p :ensure
|
25
34
|
timer.stop
|
35
|
+
# p :ensure_done
|
26
36
|
end
|
27
37
|
end
|
28
38
|
else
|
@@ -73,7 +73,7 @@ module Polyphony
|
|
73
73
|
|
74
74
|
def spin_scope
|
75
75
|
raise unless block_given?
|
76
|
-
|
76
|
+
|
77
77
|
spin do
|
78
78
|
result = yield
|
79
79
|
Fiber.current.await_all_children
|
@@ -122,8 +122,8 @@ module Polyphony
|
|
122
122
|
Fiber.current.receive_all_pending
|
123
123
|
end
|
124
124
|
|
125
|
-
def supervise(*args, &block)
|
126
|
-
Fiber.current.supervise(*args, &block)
|
125
|
+
def supervise(*args, **opts, &block)
|
126
|
+
Fiber.current.supervise(*args, **opts, &block)
|
127
127
|
end
|
128
128
|
|
129
129
|
def sleep(duration = nil)
|
data/lib/polyphony/core/timer.rb
CHANGED
@@ -44,7 +44,7 @@ module Polyphony
|
|
44
44
|
ensure
|
45
45
|
@timeouts.delete(fiber)
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def cancel_after(interval, with_exception: Polyphony::Cancel)
|
49
49
|
fiber = Fiber.current
|
50
50
|
@timeouts[fiber] = {
|
@@ -74,7 +74,7 @@ module Polyphony
|
|
74
74
|
def reset
|
75
75
|
record = @timeouts[Fiber.current]
|
76
76
|
return unless record
|
77
|
-
|
77
|
+
|
78
78
|
record[:target_stamp] = now + record[:interval]
|
79
79
|
end
|
80
80
|
|
data/lib/polyphony/debugger.rb
CHANGED
@@ -9,11 +9,11 @@ module Polyphony
|
|
9
9
|
:return,
|
10
10
|
:b_call,
|
11
11
|
:b_return
|
12
|
-
]
|
12
|
+
]
|
13
13
|
|
14
14
|
def self.start_debug_server(socket_path)
|
15
15
|
server = DebugServer.new(socket_path)
|
16
|
-
controller = DebugController.new(server)
|
16
|
+
controller = DebugController.new(server)
|
17
17
|
trace = TracePoint.new(*TP_EVENTS) { |tp| controller.handle_tp(trace, tp) }
|
18
18
|
trace.enable
|
19
19
|
|
@@ -124,7 +124,7 @@ module Polyphony
|
|
124
124
|
h
|
125
125
|
end
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
def cmd_step(cmd)
|
129
129
|
tp = nil
|
130
130
|
fiber = nil
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'fiber'
|
4
|
-
|
5
4
|
require_relative '../core/exceptions'
|
6
5
|
|
7
6
|
module Polyphony
|
@@ -19,7 +18,7 @@ module Polyphony
|
|
19
18
|
alias_method :stop, :interrupt
|
20
19
|
|
21
20
|
def restart(value = nil)
|
22
|
-
raise "Can'
|
21
|
+
raise "Can't restart main fiber" if @main
|
23
22
|
|
24
23
|
if @running
|
25
24
|
schedule Polyphony::Restart.new(value)
|
@@ -83,6 +82,8 @@ module Polyphony
|
|
83
82
|
def supervise(*fibers, **opts, &block)
|
84
83
|
block ||= supervise_opts_to_block(opts)
|
85
84
|
|
85
|
+
@supervise_mode = true
|
86
|
+
fibers = children if fibers.empty?
|
86
87
|
fibers.each do |f|
|
87
88
|
f.attach_to(self) unless f.parent == self
|
88
89
|
f.monitor(self)
|
@@ -94,15 +95,18 @@ module Polyphony
|
|
94
95
|
(fiber, result) = mailbox.shift
|
95
96
|
block&.call(fiber, result)
|
96
97
|
end
|
98
|
+
ensure
|
99
|
+
@supervise_mode = false
|
97
100
|
end
|
98
101
|
|
99
102
|
def supervise_opts_to_block(opts)
|
100
103
|
block = opts[:on_done] || opts[:on_error]
|
101
|
-
|
104
|
+
restart = opts[:restart]
|
105
|
+
return nil unless block || restart
|
102
106
|
|
103
107
|
error_only = !!opts[:on_error]
|
104
|
-
restart_always =
|
105
|
-
restart_on_error =
|
108
|
+
restart_always = (restart == :always) || (restart == true)
|
109
|
+
restart_on_error = restart == :on_error
|
106
110
|
|
107
111
|
->(f, r) do
|
108
112
|
is_error = r.is_a?(Exception)
|
@@ -149,7 +153,7 @@ module Polyphony
|
|
149
153
|
|
150
154
|
def select(*fibers)
|
151
155
|
return nil if fibers.empty?
|
152
|
-
|
156
|
+
|
153
157
|
current_fiber = self.current
|
154
158
|
mailbox = current_fiber.monitor_mailbox
|
155
159
|
fibers.each do |f|
|
@@ -163,7 +167,7 @@ module Polyphony
|
|
163
167
|
while true
|
164
168
|
(fiber, result) = mailbox.shift
|
165
169
|
next unless fibers.include?(fiber)
|
166
|
-
|
170
|
+
|
167
171
|
fibers.each { |f| f.unmonitor(current_fiber) }
|
168
172
|
if result.is_a?(Exception)
|
169
173
|
raise result
|
@@ -197,6 +201,7 @@ module Polyphony
|
|
197
201
|
|
198
202
|
def add_child(child_fiber)
|
199
203
|
(@children ||= {})[child_fiber] = true
|
204
|
+
child_fiber.monitor(self) if @supervise_mode
|
200
205
|
end
|
201
206
|
|
202
207
|
def remove_child(child_fiber)
|
@@ -207,6 +212,7 @@ module Polyphony
|
|
207
212
|
f = Fiber.new { |v| f.run(v) }
|
208
213
|
f.prepare(tag, block, orig_caller, self)
|
209
214
|
(@children ||= {})[f] = true
|
215
|
+
f.monitor(self) if @supervise_mode
|
210
216
|
f
|
211
217
|
end
|
212
218
|
|
@@ -237,10 +243,15 @@ module Polyphony
|
|
237
243
|
end
|
238
244
|
end
|
239
245
|
|
246
|
+
def attach_all_children_to(fiber)
|
247
|
+
@children&.keys.each { |c| c.attach_to(fiber) }
|
248
|
+
end
|
249
|
+
|
240
250
|
def detach
|
241
251
|
@parent.remove_child(self)
|
242
252
|
@parent = @thread.main_fiber
|
243
253
|
@parent.add_child(self)
|
254
|
+
self
|
244
255
|
end
|
245
256
|
|
246
257
|
def attach_to(fiber)
|
@@ -328,7 +339,7 @@ module Polyphony
|
|
328
339
|
# the children are shut down, it is returned along with the uncaught_exception
|
329
340
|
# flag set. Otherwise, it returns the given arguments.
|
330
341
|
def finalize_children(result, uncaught_exception)
|
331
|
-
shutdown_all_children
|
342
|
+
shutdown_all_children(graceful_shutdown?)
|
332
343
|
[result, uncaught_exception]
|
333
344
|
rescue Exception => e
|
334
345
|
[e, true]
|
@@ -103,7 +103,7 @@ class ::IO
|
|
103
103
|
alias_method :orig_getc, :getc
|
104
104
|
def getc
|
105
105
|
return @read_buffer.slice!(0) if @read_buffer && !@read_buffer.empty?
|
106
|
-
|
106
|
+
|
107
107
|
@read_buffer ||= +''
|
108
108
|
Polyphony.backend_read(self, @read_buffer, 8192, false, -1)
|
109
109
|
return @read_buffer.slice!(0) if !@read_buffer.empty?
|
@@ -116,7 +116,7 @@ class ::IO
|
|
116
116
|
if buf
|
117
117
|
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
@read_buffer ||= +''
|
121
121
|
result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
|
122
122
|
return nil unless result
|