polyphony 0.58 → 0.61
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/Gemfile.lock +15 -29
- data/examples/core/message_based_supervision.rb +51 -0
- data/examples/io/echo_server.rb +16 -7
- data/ext/polyphony/backend_common.c +160 -7
- data/ext/polyphony/backend_common.h +34 -2
- data/ext/polyphony/backend_io_uring.c +119 -40
- data/ext/polyphony/backend_io_uring_context.c +10 -1
- data/ext/polyphony/backend_io_uring_context.h +5 -3
- data/ext/polyphony/backend_libev.c +109 -31
- data/ext/polyphony/extconf.rb +2 -2
- data/ext/polyphony/fiber.c +1 -34
- data/ext/polyphony/polyphony.c +12 -19
- data/ext/polyphony/polyphony.h +9 -20
- data/ext/polyphony/polyphony_ext.c +0 -4
- data/ext/polyphony/queue.c +12 -12
- data/ext/polyphony/runqueue.c +21 -98
- data/ext/polyphony/runqueue.h +26 -0
- data/ext/polyphony/thread.c +6 -113
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/extensions/fiber.rb +102 -82
- data/lib/polyphony/extensions/io.rb +10 -9
- data/lib/polyphony/extensions/openssl.rb +14 -4
- data/lib/polyphony/extensions/socket.rb +15 -15
- data/lib/polyphony/extensions/thread.rb +1 -1
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +0 -7
- data/test/test_backend.rb +46 -9
- data/test/test_ext.rb +1 -1
- data/test/test_fiber.rb +106 -18
- data/test/test_global_api.rb +1 -1
- data/test/test_io.rb +29 -0
- data/test/test_supervise.rb +100 -100
- data/test/test_thread.rb +5 -11
- data/test/test_thread_pool.rb +1 -1
- data/test/test_trace.rb +28 -49
- metadata +5 -109
- data/ext/polyphony/tracing.c +0 -11
- data/lib/polyphony/adapters/trace.rb +0 -138
@@ -44,8 +44,12 @@ typedef struct Backend_t {
|
|
44
44
|
|
45
45
|
static void Backend_mark(void *ptr) {
|
46
46
|
Backend_t *backend = ptr;
|
47
|
-
|
48
|
-
|
47
|
+
backend_base_mark(&backend->base);
|
48
|
+
}
|
49
|
+
|
50
|
+
static void Backend_free(void *ptr) {
|
51
|
+
Backend_t *backend = ptr;
|
52
|
+
backend_base_finalize(&backend->base);
|
49
53
|
}
|
50
54
|
|
51
55
|
static size_t Backend_size(const void *ptr) {
|
@@ -54,7 +58,7 @@ static size_t Backend_size(const void *ptr) {
|
|
54
58
|
|
55
59
|
static const rb_data_type_t Backend_type = {
|
56
60
|
"IOUringBackend",
|
57
|
-
{Backend_mark,
|
61
|
+
{Backend_mark, Backend_free, Backend_size,},
|
58
62
|
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
59
63
|
};
|
60
64
|
|
@@ -71,7 +75,7 @@ static VALUE Backend_initialize(VALUE self) {
|
|
71
75
|
Backend_t *backend;
|
72
76
|
GetBackend(self, backend);
|
73
77
|
|
74
|
-
|
78
|
+
backend_base_initialize(&backend->base);
|
75
79
|
backend->pending_sqes = 0;
|
76
80
|
backend->prepared_limit = 2048;
|
77
81
|
|
@@ -106,13 +110,6 @@ VALUE Backend_post_fork(VALUE self) {
|
|
106
110
|
return self;
|
107
111
|
}
|
108
112
|
|
109
|
-
unsigned int Backend_pending_count(VALUE self) {
|
110
|
-
Backend_t *backend;
|
111
|
-
GetBackend(self, backend);
|
112
|
-
|
113
|
-
return backend->base.pending_count;
|
114
|
-
}
|
115
|
-
|
116
113
|
typedef struct poll_context {
|
117
114
|
struct io_uring *ring;
|
118
115
|
struct io_uring_cqe *cqe;
|
@@ -189,24 +186,63 @@ void io_uring_backend_poll(Backend_t *backend) {
|
|
189
186
|
io_uring_cqe_seen(&backend->ring, poll_ctx.cqe);
|
190
187
|
}
|
191
188
|
|
192
|
-
VALUE Backend_poll(VALUE self, VALUE
|
193
|
-
int
|
189
|
+
inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
190
|
+
int is_blocking = blocking == Qtrue;
|
194
191
|
Backend_t *backend;
|
195
192
|
GetBackend(self, backend);
|
196
193
|
|
197
|
-
|
194
|
+
backend->base.poll_count++;
|
195
|
+
|
196
|
+
if (!is_blocking && backend->pending_sqes) {
|
198
197
|
backend->pending_sqes = 0;
|
199
198
|
io_uring_submit(&backend->ring);
|
200
199
|
}
|
201
200
|
|
202
|
-
COND_TRACE(2, SYM_fiber_event_poll_enter,
|
203
|
-
if (
|
201
|
+
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_enter, rb_fiber_current());
|
202
|
+
// if (SHOULD_TRACE(&backend->base))
|
203
|
+
// printf(
|
204
|
+
// "io_uring_poll(blocking_mode: %d, pending: %d, taken: %d, available: %d, runqueue: %d\n",
|
205
|
+
// is_blocking,
|
206
|
+
// backend->base.pending_count,
|
207
|
+
// backend->store.taken_count,
|
208
|
+
// backend->store.available_count,
|
209
|
+
// backend->base.runqueue.entries.count
|
210
|
+
// );
|
211
|
+
if (is_blocking) io_uring_backend_poll(backend);
|
204
212
|
io_uring_backend_handle_ready_cqes(backend);
|
205
|
-
COND_TRACE(2, SYM_fiber_event_poll_leave,
|
213
|
+
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_leave, rb_fiber_current());
|
206
214
|
|
207
215
|
return self;
|
208
216
|
}
|
209
217
|
|
218
|
+
inline void Backend_schedule_fiber(VALUE thread, VALUE self, VALUE fiber, VALUE value, int prioritize) {
|
219
|
+
Backend_t *backend;
|
220
|
+
GetBackend(self, backend);
|
221
|
+
|
222
|
+
backend_base_schedule_fiber(thread, self, &backend->base, fiber, value, prioritize);
|
223
|
+
}
|
224
|
+
|
225
|
+
inline void Backend_unschedule_fiber(VALUE self, VALUE fiber) {
|
226
|
+
Backend_t *backend;
|
227
|
+
GetBackend(self, backend);
|
228
|
+
|
229
|
+
runqueue_delete(&backend->base.runqueue, fiber);
|
230
|
+
}
|
231
|
+
|
232
|
+
inline VALUE Backend_switch_fiber(VALUE self) {
|
233
|
+
Backend_t *backend;
|
234
|
+
GetBackend(self, backend);
|
235
|
+
|
236
|
+
return backend_base_switch_fiber(self, &backend->base);
|
237
|
+
}
|
238
|
+
|
239
|
+
inline struct backend_stats backend_get_stats(VALUE self) {
|
240
|
+
Backend_t *backend;
|
241
|
+
GetBackend(self, backend);
|
242
|
+
|
243
|
+
return backend_base_stats(&backend->base);
|
244
|
+
}
|
245
|
+
|
210
246
|
VALUE Backend_wakeup(VALUE self) {
|
211
247
|
Backend_t *backend;
|
212
248
|
GetBackend(self, backend);
|
@@ -242,6 +278,7 @@ int io_uring_backend_defer_submit_and_await(
|
|
242
278
|
{
|
243
279
|
VALUE switchpoint_result = Qnil;
|
244
280
|
|
281
|
+
backend->base.op_count++;
|
245
282
|
if (sqe) {
|
246
283
|
io_uring_sqe_set_data(sqe, ctx);
|
247
284
|
io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
@@ -273,17 +310,25 @@ VALUE io_uring_backend_wait_fd(Backend_t *backend, int fd, int write) {
|
|
273
310
|
io_uring_prep_poll_add(sqe, fd, write ? POLLOUT : POLLIN);
|
274
311
|
|
275
312
|
io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resumed_value);
|
313
|
+
context_store_release(&backend->store, ctx);
|
314
|
+
|
276
315
|
RB_GC_GUARD(resumed_value);
|
277
316
|
return resumed_value;
|
278
317
|
}
|
279
318
|
|
280
|
-
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
|
319
|
+
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos) {
|
281
320
|
Backend_t *backend;
|
282
321
|
rb_io_t *fptr;
|
283
322
|
long dynamic_len = length == Qnil;
|
284
323
|
long buffer_size = dynamic_len ? 4096 : NUM2INT(length);
|
285
|
-
|
286
|
-
|
324
|
+
long buf_pos = NUM2INT(pos);
|
325
|
+
if (str != Qnil) {
|
326
|
+
int current_len = RSTRING_LEN(str);
|
327
|
+
if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
|
328
|
+
}
|
329
|
+
else buf_pos = 0;
|
330
|
+
int shrinkable = io_setstrbuf(&str, buf_pos + buffer_size);
|
331
|
+
char *buf = RSTRING_PTR(str) + buf_pos;
|
287
332
|
long total = 0;
|
288
333
|
int read_to_eof = RTEST(to_eof);
|
289
334
|
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
@@ -320,9 +365,9 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
320
365
|
if (!dynamic_len) break;
|
321
366
|
|
322
367
|
// resize buffer
|
323
|
-
rb_str_resize(str, total);
|
368
|
+
rb_str_resize(str, buf_pos + total);
|
324
369
|
rb_str_modify_expand(str, buffer_size);
|
325
|
-
buf = RSTRING_PTR(str) + total;
|
370
|
+
buf = RSTRING_PTR(str) + buf_pos + total;
|
326
371
|
shrinkable = 0;
|
327
372
|
buffer_size += buffer_size;
|
328
373
|
}
|
@@ -330,7 +375,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
330
375
|
}
|
331
376
|
}
|
332
377
|
|
333
|
-
io_set_read_length(str, total, shrinkable);
|
378
|
+
io_set_read_length(str, buf_pos + total, shrinkable);
|
334
379
|
io_enc_str(str, fptr);
|
335
380
|
|
336
381
|
if (!total) return Qnil;
|
@@ -338,12 +383,12 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
338
383
|
return str;
|
339
384
|
}
|
340
385
|
|
341
|
-
VALUE Backend_read_loop(VALUE self, VALUE io) {
|
386
|
+
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
342
387
|
Backend_t *backend;
|
343
388
|
rb_io_t *fptr;
|
344
389
|
VALUE str;
|
345
390
|
long total;
|
346
|
-
long len =
|
391
|
+
long len = NUM2INT(maxlen);
|
347
392
|
int shrinkable;
|
348
393
|
char *buf;
|
349
394
|
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
@@ -551,13 +596,19 @@ VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
|
|
551
596
|
Backend_writev(self, argv[0], argc - 1, argv + 1);
|
552
597
|
}
|
553
598
|
|
554
|
-
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
599
|
+
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
555
600
|
Backend_t *backend;
|
556
601
|
rb_io_t *fptr;
|
557
602
|
long dynamic_len = length == Qnil;
|
558
603
|
long len = dynamic_len ? 4096 : NUM2INT(length);
|
559
|
-
|
560
|
-
|
604
|
+
long buf_pos = NUM2INT(pos);
|
605
|
+
if (str != Qnil) {
|
606
|
+
int current_len = RSTRING_LEN(str);
|
607
|
+
if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
|
608
|
+
}
|
609
|
+
else buf_pos = 0;
|
610
|
+
int shrinkable = io_setstrbuf(&str, buf_pos + len);
|
611
|
+
char *buf = RSTRING_PTR(str) + buf_pos;
|
561
612
|
long total = 0;
|
562
613
|
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
563
614
|
|
@@ -589,7 +640,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
|
589
640
|
}
|
590
641
|
}
|
591
642
|
|
592
|
-
io_set_read_length(str, total, shrinkable);
|
643
|
+
io_set_read_length(str, buf_pos + total, shrinkable);
|
593
644
|
io_enc_str(str, fptr);
|
594
645
|
|
595
646
|
if (!total) return Qnil;
|
@@ -597,12 +648,12 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
|
597
648
|
return str;
|
598
649
|
}
|
599
650
|
|
600
|
-
VALUE Backend_recv_loop(VALUE self, VALUE io) {
|
651
|
+
VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
601
652
|
Backend_t *backend;
|
602
653
|
rb_io_t *fptr;
|
603
654
|
VALUE str;
|
604
655
|
long total;
|
605
|
-
long len =
|
656
|
+
long len = NUM2INT(maxlen);
|
606
657
|
int shrinkable;
|
607
658
|
char *buf;
|
608
659
|
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
@@ -992,6 +1043,7 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
992
1043
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
993
1044
|
io_uring_sqe_set_data(sqe, ctx);
|
994
1045
|
io_uring_backend_defer_submit(backend);
|
1046
|
+
backend->base.op_count++;
|
995
1047
|
|
996
1048
|
struct Backend_timeout_ctx timeout_ctx = {backend, ctx};
|
997
1049
|
result = rb_ensure(Backend_timeout_ensure_safe, Qnil, Backend_timeout_ensure, (VALUE)&timeout_ctx);
|
@@ -1159,6 +1211,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1159
1211
|
sqe_count++;
|
1160
1212
|
}
|
1161
1213
|
|
1214
|
+
backend->base.op_count += sqe_count;
|
1162
1215
|
ctx->ref_count = sqe_count + 1;
|
1163
1216
|
io_uring_backend_defer_submit(backend);
|
1164
1217
|
resume_value = backend_await((struct Backend_base *)backend);
|
@@ -1187,10 +1240,10 @@ VALUE Backend_idle_gc_period_set(VALUE self, VALUE period) {
|
|
1187
1240
|
return self;
|
1188
1241
|
}
|
1189
1242
|
|
1190
|
-
VALUE
|
1243
|
+
VALUE Backend_idle_proc_set(VALUE self, VALUE block) {
|
1191
1244
|
Backend_t *backend;
|
1192
1245
|
GetBackend(self, backend);
|
1193
|
-
backend->base.
|
1246
|
+
backend->base.idle_proc = block;
|
1194
1247
|
return self;
|
1195
1248
|
}
|
1196
1249
|
|
@@ -1295,6 +1348,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1295
1348
|
if (prefix != Qnil) {
|
1296
1349
|
splice_chunks_get_sqe(backend, &ctx, &sqe, OP_WRITE);
|
1297
1350
|
splice_chunks_prep_write(ctx, sqe, dest_fptr->fd, prefix);
|
1351
|
+
backend->base.op_count++;
|
1298
1352
|
}
|
1299
1353
|
|
1300
1354
|
while (1) {
|
@@ -1304,7 +1358,8 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1304
1358
|
|
1305
1359
|
splice_chunks_get_sqe(backend, &ctx, &sqe, OP_SPLICE);
|
1306
1360
|
splice_chunks_prep_splice(ctx, sqe, src_fptr->fd, pipefd[1], maxlen);
|
1307
|
-
|
1361
|
+
backend->base.op_count++;
|
1362
|
+
|
1308
1363
|
SPLICE_CHUNKS_AWAIT_OPS(backend, &ctx, &chunk_len, &switchpoint_result);
|
1309
1364
|
if (chunk_len == 0) break;
|
1310
1365
|
|
@@ -1316,15 +1371,18 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1316
1371
|
chunk_prefix_str = (TYPE(chunk_prefix) == T_STRING) ? chunk_prefix : rb_funcall(chunk_prefix, ID_call, 1, chunk_len_value);
|
1317
1372
|
splice_chunks_get_sqe(backend, &ctx, &sqe, OP_WRITE);
|
1318
1373
|
splice_chunks_prep_write(ctx, sqe, dest_fptr->fd, chunk_prefix_str);
|
1374
|
+
backend->base.op_count++;
|
1319
1375
|
}
|
1320
1376
|
|
1321
1377
|
splice_chunks_get_sqe(backend, &ctx, &sqe, OP_SPLICE);
|
1322
1378
|
splice_chunks_prep_splice(ctx, sqe, pipefd[0], dest_fptr->fd, chunk_len);
|
1379
|
+
backend->base.op_count++;
|
1323
1380
|
|
1324
1381
|
if (chunk_postfix != Qnil) {
|
1325
1382
|
chunk_postfix_str = (TYPE(chunk_postfix) == T_STRING) ? chunk_postfix : rb_funcall(chunk_postfix, ID_call, 1, chunk_len_value);
|
1326
1383
|
splice_chunks_get_sqe(backend, &ctx, &sqe, OP_WRITE);
|
1327
1384
|
splice_chunks_prep_write(ctx, sqe, dest_fptr->fd, chunk_postfix_str);
|
1385
|
+
backend->base.op_count++;
|
1328
1386
|
}
|
1329
1387
|
|
1330
1388
|
RB_GC_GUARD(chunk_prefix_str);
|
@@ -1334,6 +1392,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1334
1392
|
if (postfix != Qnil) {
|
1335
1393
|
splice_chunks_get_sqe(backend, &ctx, &sqe, OP_WRITE);
|
1336
1394
|
splice_chunks_prep_write(ctx, sqe, dest_fptr->fd, postfix);
|
1395
|
+
backend->base.op_count++;
|
1337
1396
|
}
|
1338
1397
|
if (ctx) {
|
1339
1398
|
SPLICE_CHUNKS_AWAIT_OPS(backend, &ctx, 0, &switchpoint_result);
|
@@ -1355,6 +1414,21 @@ error:
|
|
1355
1414
|
return RAISE_EXCEPTION(switchpoint_result);
|
1356
1415
|
}
|
1357
1416
|
|
1417
|
+
VALUE Backend_trace(int argc, VALUE *argv, VALUE self) {
|
1418
|
+
Backend_t *backend;
|
1419
|
+
GetBackend(self, backend);
|
1420
|
+
backend_trace(&backend->base, argc, argv);
|
1421
|
+
return self;
|
1422
|
+
}
|
1423
|
+
|
1424
|
+
VALUE Backend_trace_proc_set(VALUE self, VALUE block) {
|
1425
|
+
Backend_t *backend;
|
1426
|
+
GetBackend(self, backend);
|
1427
|
+
|
1428
|
+
backend->base.trace_proc = block;
|
1429
|
+
return self;
|
1430
|
+
}
|
1431
|
+
|
1358
1432
|
void Init_Backend() {
|
1359
1433
|
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
|
1360
1434
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
@@ -1362,24 +1436,27 @@ void Init_Backend() {
|
|
1362
1436
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
1363
1437
|
rb_define_method(cBackend, "finalize", Backend_finalize, 0);
|
1364
1438
|
rb_define_method(cBackend, "post_fork", Backend_post_fork, 0);
|
1439
|
+
rb_define_method(cBackend, "trace", Backend_trace, -1);
|
1440
|
+
rb_define_method(cBackend, "trace_proc=", Backend_trace_proc_set, 1);
|
1441
|
+
rb_define_method(cBackend, "stats", Backend_stats, 0);
|
1365
1442
|
|
1366
|
-
rb_define_method(cBackend, "poll", Backend_poll,
|
1443
|
+
rb_define_method(cBackend, "poll", Backend_poll, 1);
|
1367
1444
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
1368
1445
|
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
1369
1446
|
rb_define_method(cBackend, "chain", Backend_chain, -1);
|
1370
1447
|
rb_define_method(cBackend, "idle_gc_period=", Backend_idle_gc_period_set, 1);
|
1371
|
-
rb_define_method(cBackend, "
|
1448
|
+
rb_define_method(cBackend, "idle_proc=", Backend_idle_proc_set, 1);
|
1372
1449
|
rb_define_method(cBackend, "splice_chunks", Backend_splice_chunks, 7);
|
1373
1450
|
|
1374
1451
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
1375
1452
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
1376
1453
|
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
1377
1454
|
rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
|
1378
|
-
rb_define_method(cBackend, "read", Backend_read,
|
1379
|
-
rb_define_method(cBackend, "read_loop", Backend_read_loop,
|
1380
|
-
rb_define_method(cBackend, "recv", Backend_recv,
|
1455
|
+
rb_define_method(cBackend, "read", Backend_read, 5);
|
1456
|
+
rb_define_method(cBackend, "read_loop", Backend_read_loop, 2);
|
1457
|
+
rb_define_method(cBackend, "recv", Backend_recv, 4);
|
1381
1458
|
rb_define_method(cBackend, "recv_feed_loop", Backend_recv_feed_loop, 3);
|
1382
|
-
rb_define_method(cBackend, "recv_loop", Backend_recv_loop,
|
1459
|
+
rb_define_method(cBackend, "recv_loop", Backend_recv_loop, 2);
|
1383
1460
|
rb_define_method(cBackend, "send", Backend_send, 3);
|
1384
1461
|
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
1385
1462
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
@@ -1401,6 +1478,8 @@ void Init_Backend() {
|
|
1401
1478
|
SYM_send = ID2SYM(rb_intern("send"));
|
1402
1479
|
SYM_splice = ID2SYM(rb_intern("splice"));
|
1403
1480
|
SYM_write = ID2SYM(rb_intern("write"));
|
1481
|
+
|
1482
|
+
backend_setup_stats_symbols();
|
1404
1483
|
}
|
1405
1484
|
|
1406
1485
|
#endif // POLYPHONY_BACKEND_LIBURING
|
@@ -25,6 +25,8 @@ void context_store_initialize(op_context_store_t *store) {
|
|
25
25
|
store->last_id = 0;
|
26
26
|
store->available = NULL;
|
27
27
|
store->taken = NULL;
|
28
|
+
store->available_count = 0;
|
29
|
+
store->taken_count = 0;
|
28
30
|
}
|
29
31
|
|
30
32
|
inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_type type) {
|
@@ -32,12 +34,12 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
|
|
32
34
|
if (ctx) {
|
33
35
|
if (ctx->next) ctx->next->prev = NULL;
|
34
36
|
store->available = ctx->next;
|
37
|
+
store->available_count--;
|
35
38
|
}
|
36
39
|
else {
|
37
40
|
ctx = malloc(sizeof(op_context_t));
|
38
41
|
}
|
39
42
|
ctx->id = (++store->last_id);
|
40
|
-
// printf("acquire %p %d (%s)\n", ctx, ctx->id, op_type_to_str(type));
|
41
43
|
ctx->prev = NULL;
|
42
44
|
ctx->next = store->taken;
|
43
45
|
if (store->taken) store->taken->prev = ctx;
|
@@ -49,6 +51,10 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
|
|
49
51
|
ctx->ref_count = 2;
|
50
52
|
ctx->result = 0;
|
51
53
|
|
54
|
+
store->taken_count++;
|
55
|
+
|
56
|
+
// printf("acquire %p %d (%s, ref_count: %d) taken: %d\n", ctx, ctx->id, op_type_to_str(type), ctx->ref_count, store->taken_count);
|
57
|
+
|
52
58
|
return ctx;
|
53
59
|
}
|
54
60
|
|
@@ -61,6 +67,9 @@ inline int context_store_release(op_context_store_t *store, op_context_t *ctx) {
|
|
61
67
|
ctx->ref_count--;
|
62
68
|
if (ctx->ref_count) return 0;
|
63
69
|
|
70
|
+
store->taken_count--;
|
71
|
+
store->available_count++;
|
72
|
+
|
64
73
|
if (ctx->next) ctx->next->prev = ctx->prev;
|
65
74
|
if (ctx->prev) ctx->prev->next = ctx->next;
|
66
75
|
if (store->taken == ctx) store->taken = ctx->next;
|
@@ -22,7 +22,7 @@ typedef struct op_context {
|
|
22
22
|
struct op_context *prev;
|
23
23
|
struct op_context *next;
|
24
24
|
enum op_type type: 16;
|
25
|
-
unsigned int ref_count : 16;
|
25
|
+
unsigned int ref_count : 16;
|
26
26
|
int id;
|
27
27
|
int result;
|
28
28
|
VALUE fiber;
|
@@ -31,8 +31,10 @@ typedef struct op_context {
|
|
31
31
|
|
32
32
|
typedef struct op_context_store {
|
33
33
|
int last_id;
|
34
|
-
op_context_t
|
35
|
-
op_context_t
|
34
|
+
op_context_t *available;
|
35
|
+
op_context_t *taken;
|
36
|
+
int available_count;
|
37
|
+
int taken_count;
|
36
38
|
} op_context_store_t;
|
37
39
|
|
38
40
|
const char *op_type_to_str(enum op_type type);
|
@@ -75,8 +75,12 @@ typedef struct Backend_t {
|
|
75
75
|
|
76
76
|
static void Backend_mark(void *ptr) {
|
77
77
|
Backend_t *backend = ptr;
|
78
|
-
|
79
|
-
|
78
|
+
backend_base_mark(&backend->base);
|
79
|
+
}
|
80
|
+
|
81
|
+
static void Backend_free(void *ptr) {
|
82
|
+
Backend_t *backend = ptr;
|
83
|
+
backend_base_finalize(&backend->base);
|
80
84
|
}
|
81
85
|
|
82
86
|
static size_t Backend_size(const void *ptr) {
|
@@ -85,7 +89,7 @@ static size_t Backend_size(const void *ptr) {
|
|
85
89
|
|
86
90
|
static const rb_data_type_t Backend_type = {
|
87
91
|
"LibevBackend",
|
88
|
-
{Backend_mark,
|
92
|
+
{Backend_mark, Backend_free, Backend_size,},
|
89
93
|
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
90
94
|
};
|
91
95
|
|
@@ -117,7 +121,7 @@ static VALUE Backend_initialize(VALUE self) {
|
|
117
121
|
|
118
122
|
GetBackend(self, backend);
|
119
123
|
|
120
|
-
|
124
|
+
backend_base_initialize(&backend->base);
|
121
125
|
backend->ev_loop = libev_new_loop();
|
122
126
|
|
123
127
|
// start async watcher used for breaking a poll op (from another thread)
|
@@ -156,24 +160,40 @@ VALUE Backend_post_fork(VALUE self) {
|
|
156
160
|
return self;
|
157
161
|
}
|
158
162
|
|
159
|
-
inline
|
163
|
+
inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
160
164
|
Backend_t *backend;
|
161
165
|
GetBackend(self, backend);
|
162
166
|
|
163
|
-
|
167
|
+
backend->base.poll_count++;
|
168
|
+
|
169
|
+
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_enter, rb_fiber_current());
|
170
|
+
backend->base.currently_polling = 1;
|
171
|
+
ev_run(backend->ev_loop, blocking == Qtrue ? EVRUN_ONCE : EVRUN_NOWAIT);
|
172
|
+
backend->base.currently_polling = 0;
|
173
|
+
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_leave, rb_fiber_current());
|
174
|
+
|
175
|
+
return self;
|
164
176
|
}
|
165
177
|
|
166
|
-
|
178
|
+
inline void Backend_schedule_fiber(VALUE thread, VALUE self, VALUE fiber, VALUE value, int prioritize) {
|
167
179
|
Backend_t *backend;
|
168
180
|
GetBackend(self, backend);
|
169
181
|
|
170
|
-
|
171
|
-
|
172
|
-
ev_run(backend->ev_loop, nowait == Qtrue ? EVRUN_NOWAIT : EVRUN_ONCE);
|
173
|
-
backend->base.currently_polling = 0;
|
174
|
-
COND_TRACE(2, SYM_fiber_event_poll_leave, current_fiber);
|
182
|
+
backend_base_schedule_fiber(thread, self, &backend->base, fiber, value, prioritize);
|
183
|
+
}
|
175
184
|
|
176
|
-
|
185
|
+
inline void Backend_unschedule_fiber(VALUE self, VALUE fiber) {
|
186
|
+
Backend_t *backend;
|
187
|
+
GetBackend(self, backend);
|
188
|
+
|
189
|
+
runqueue_delete(&backend->base.runqueue, fiber);
|
190
|
+
}
|
191
|
+
|
192
|
+
inline VALUE Backend_switch_fiber(VALUE self) {
|
193
|
+
Backend_t *backend;
|
194
|
+
GetBackend(self, backend);
|
195
|
+
|
196
|
+
return backend_base_switch_fiber(self, &backend->base);
|
177
197
|
}
|
178
198
|
|
179
199
|
VALUE Backend_wakeup(VALUE self) {
|
@@ -193,6 +213,13 @@ VALUE Backend_wakeup(VALUE self) {
|
|
193
213
|
return Qnil;
|
194
214
|
}
|
195
215
|
|
216
|
+
inline struct backend_stats backend_get_stats(VALUE self) {
|
217
|
+
Backend_t *backend;
|
218
|
+
GetBackend(self, backend);
|
219
|
+
|
220
|
+
return backend_base_stats(&backend->base);
|
221
|
+
}
|
222
|
+
|
196
223
|
struct libev_io {
|
197
224
|
struct ev_io io;
|
198
225
|
VALUE fiber;
|
@@ -232,14 +259,20 @@ VALUE libev_wait_fd(Backend_t *backend, int fd, int events, int raise_exception)
|
|
232
259
|
return switchpoint_result;
|
233
260
|
}
|
234
261
|
|
235
|
-
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
|
262
|
+
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos) {
|
236
263
|
Backend_t *backend;
|
237
264
|
struct libev_io watcher;
|
238
265
|
rb_io_t *fptr;
|
239
266
|
long dynamic_len = length == Qnil;
|
240
267
|
long len = dynamic_len ? 4096 : NUM2INT(length);
|
241
|
-
|
242
|
-
|
268
|
+
long buf_pos = NUM2INT(pos);
|
269
|
+
if (str != Qnil) {
|
270
|
+
int current_len = RSTRING_LEN(str);
|
271
|
+
if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
|
272
|
+
}
|
273
|
+
else buf_pos = 0;
|
274
|
+
int shrinkable = io_setstrbuf(&str, buf_pos + len);
|
275
|
+
char *buf = RSTRING_PTR(str) + buf_pos;
|
243
276
|
long total = 0;
|
244
277
|
VALUE switchpoint_result = Qnil;
|
245
278
|
int read_to_eof = RTEST(to_eof);
|
@@ -255,6 +288,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
255
288
|
OBJ_TAINT(str);
|
256
289
|
|
257
290
|
while (1) {
|
291
|
+
backend->base.op_count++;
|
258
292
|
ssize_t n = read(fptr->fd, buf, len - total);
|
259
293
|
if (n < 0) {
|
260
294
|
int e = errno;
|
@@ -275,9 +309,9 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
275
309
|
if (total == len) {
|
276
310
|
if (!dynamic_len) break;
|
277
311
|
|
278
|
-
rb_str_resize(str, total);
|
312
|
+
rb_str_resize(str, buf_pos + total);
|
279
313
|
rb_str_modify_expand(str, len);
|
280
|
-
buf = RSTRING_PTR(str) + total;
|
314
|
+
buf = RSTRING_PTR(str) + buf_pos + total;
|
281
315
|
shrinkable = 0;
|
282
316
|
len += len;
|
283
317
|
}
|
@@ -285,7 +319,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
285
319
|
}
|
286
320
|
}
|
287
321
|
|
288
|
-
io_set_read_length(str, total, shrinkable);
|
322
|
+
io_set_read_length(str, buf_pos + total, shrinkable);
|
289
323
|
io_enc_str(str, fptr);
|
290
324
|
|
291
325
|
if (total == 0) return Qnil;
|
@@ -298,17 +332,17 @@ error:
|
|
298
332
|
return RAISE_EXCEPTION(switchpoint_result);
|
299
333
|
}
|
300
334
|
|
301
|
-
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
302
|
-
return Backend_read(self, io, str, length, Qnil);
|
335
|
+
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
336
|
+
return Backend_read(self, io, str, length, Qnil, pos);
|
303
337
|
}
|
304
338
|
|
305
|
-
VALUE Backend_read_loop(VALUE self, VALUE io) {
|
339
|
+
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
306
340
|
Backend_t *backend;
|
307
341
|
struct libev_io watcher;
|
308
342
|
rb_io_t *fptr;
|
309
343
|
VALUE str;
|
310
344
|
long total;
|
311
|
-
long len =
|
345
|
+
long len = NUM2INT(maxlen);
|
312
346
|
int shrinkable;
|
313
347
|
char *buf;
|
314
348
|
VALUE switchpoint_result = Qnil;
|
@@ -325,6 +359,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io) {
|
|
325
359
|
watcher.fiber = Qnil;
|
326
360
|
|
327
361
|
while (1) {
|
362
|
+
backend->base.op_count++;
|
328
363
|
ssize_t n = read(fptr->fd, buf, len);
|
329
364
|
if (n < 0) {
|
330
365
|
int e = errno;
|
@@ -377,6 +412,7 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
377
412
|
watcher.fiber = Qnil;
|
378
413
|
|
379
414
|
while (1) {
|
415
|
+
backend->base.op_count++;
|
380
416
|
ssize_t n = read(fptr->fd, buf, len);
|
381
417
|
if (n < 0) {
|
382
418
|
int e = errno;
|
@@ -424,6 +460,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
424
460
|
watcher.fiber = Qnil;
|
425
461
|
|
426
462
|
while (left > 0) {
|
463
|
+
backend->base.op_count++;
|
427
464
|
ssize_t n = write(fptr->fd, buf, left);
|
428
465
|
if (n < 0) {
|
429
466
|
int e = errno;
|
@@ -483,6 +520,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
483
520
|
iov_ptr = iov;
|
484
521
|
|
485
522
|
while (1) {
|
523
|
+
backend->base.op_count++;
|
486
524
|
ssize_t n = writev(fptr->fd, iov_ptr, iov_count);
|
487
525
|
if (n < 0) {
|
488
526
|
int e = errno;
|
@@ -554,6 +592,7 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
554
592
|
io_verify_blocking_mode(fptr, server_socket, Qfalse);
|
555
593
|
watcher.fiber = Qnil;
|
556
594
|
while (1) {
|
595
|
+
backend->base.op_count++;
|
557
596
|
fd = accept(fptr->fd, &addr, &len);
|
558
597
|
if (fd < 0) {
|
559
598
|
int e = errno;
|
@@ -612,6 +651,7 @@ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
612
651
|
watcher.fiber = Qnil;
|
613
652
|
|
614
653
|
while (1) {
|
654
|
+
backend->base.op_count++;
|
615
655
|
fd = accept(fptr->fd, &addr, &len);
|
616
656
|
if (fd < 0) {
|
617
657
|
int e = errno;
|
@@ -671,6 +711,7 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
671
711
|
addr.sin_addr.s_addr = inet_addr(host_buf);
|
672
712
|
addr.sin_port = htons(NUM2INT(port));
|
673
713
|
|
714
|
+
backend->base.op_count++;
|
674
715
|
int result = connect(fptr->fd, (struct sockaddr *)&addr, sizeof(addr));
|
675
716
|
if (result < 0) {
|
676
717
|
int e = errno;
|
@@ -711,6 +752,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
711
752
|
watcher.fiber = Qnil;
|
712
753
|
|
713
754
|
while (left > 0) {
|
755
|
+
backend->base.op_count++;
|
714
756
|
ssize_t n = send(fptr->fd, buf, left, flags_int);
|
715
757
|
if (n < 0) {
|
716
758
|
int e = errno;
|
@@ -818,6 +860,7 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
818
860
|
|
819
861
|
watcher.ctx.fiber = Qnil;
|
820
862
|
while (1) {
|
863
|
+
backend->base.op_count++;
|
821
864
|
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
822
865
|
if (len < 0) {
|
823
866
|
int e = errno;
|
@@ -869,6 +912,7 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
869
912
|
|
870
913
|
watcher.ctx.fiber = Qnil;
|
871
914
|
while (1) {
|
915
|
+
backend->base.op_count++;
|
872
916
|
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
873
917
|
if (len < 0) {
|
874
918
|
int e = errno;
|
@@ -928,6 +972,7 @@ VALUE Backend_fake_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
928
972
|
watcher.fiber = Qnil;
|
929
973
|
|
930
974
|
while (1) {
|
975
|
+
backend->base.op_count++;
|
931
976
|
ssize_t n = read(src_fptr->fd, buf, len);
|
932
977
|
if (n < 0) {
|
933
978
|
int e = errno;
|
@@ -943,6 +988,7 @@ VALUE Backend_fake_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
943
988
|
}
|
944
989
|
|
945
990
|
while (left > 0) {
|
991
|
+
backend->base.op_count++;
|
946
992
|
ssize_t n = write(dest_fptr->fd, buf, left);
|
947
993
|
if (n < 0) {
|
948
994
|
int e = errno;
|
@@ -1003,6 +1049,7 @@ VALUE Backend_fake_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen
|
|
1003
1049
|
while (1) {
|
1004
1050
|
char *ptr = buf;
|
1005
1051
|
while (1) {
|
1052
|
+
backend->base.op_count++;
|
1006
1053
|
ssize_t n = read(src_fptr->fd, ptr, len);
|
1007
1054
|
if (n < 0) {
|
1008
1055
|
int e = errno;
|
@@ -1020,6 +1067,7 @@ VALUE Backend_fake_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen
|
|
1020
1067
|
}
|
1021
1068
|
|
1022
1069
|
while (left > 0) {
|
1070
|
+
backend->base.op_count++;
|
1023
1071
|
ssize_t n = write(dest_fptr->fd, ptr, left);
|
1024
1072
|
if (n < 0) {
|
1025
1073
|
int e = errno;
|
@@ -1059,6 +1107,7 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
1059
1107
|
GetBackend(self, backend);
|
1060
1108
|
GetOpenFile(io, fptr);
|
1061
1109
|
|
1110
|
+
backend->base.op_count++;
|
1062
1111
|
return libev_wait_fd(backend, fptr->fd, events, 1);
|
1063
1112
|
}
|
1064
1113
|
|
@@ -1082,6 +1131,7 @@ VALUE Backend_sleep(VALUE self, VALUE duration) {
|
|
1082
1131
|
watcher.fiber = rb_fiber_current();
|
1083
1132
|
ev_timer_init(&watcher.timer, Backend_timer_callback, NUM2DBL(duration), 0.);
|
1084
1133
|
ev_timer_start(backend->ev_loop, &watcher.timer);
|
1134
|
+
backend->base.op_count++;
|
1085
1135
|
|
1086
1136
|
switchpoint_result = backend_await((struct Backend_base *)backend);
|
1087
1137
|
|
@@ -1111,6 +1161,7 @@ noreturn VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
1111
1161
|
VALUE switchpoint_result = Qnil;
|
1112
1162
|
ev_timer_init(&watcher.timer, Backend_timer_callback, sleep_duration, 0.);
|
1113
1163
|
ev_timer_start(backend->ev_loop, &watcher.timer);
|
1164
|
+
backend->base.op_count++;
|
1114
1165
|
switchpoint_result = backend_await((struct Backend_base *)backend);
|
1115
1166
|
ev_timer_stop(backend->ev_loop, &watcher.timer);
|
1116
1167
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
@@ -1162,6 +1213,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
|
|
1162
1213
|
watcher.resume_value = timeout;
|
1163
1214
|
ev_timer_init(&watcher.timer, Backend_timeout_callback, NUM2DBL(duration), 0.);
|
1164
1215
|
ev_timer_start(backend->ev_loop, &watcher.timer);
|
1216
|
+
backend->base.op_count++;
|
1165
1217
|
|
1166
1218
|
struct Backend_timeout_ctx timeout_ctx = {backend, &watcher};
|
1167
1219
|
result = rb_ensure(Backend_timeout_ensure_safe, Qnil, Backend_timeout_ensure, (VALUE)&timeout_ctx);
|
@@ -1184,6 +1236,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1184
1236
|
if (fd >= 0) {
|
1185
1237
|
Backend_t *backend;
|
1186
1238
|
GetBackend(self, backend);
|
1239
|
+
backend->base.op_count++;
|
1187
1240
|
|
1188
1241
|
VALUE resume_value = libev_wait_fd(backend, fd, EV_READ, 0);
|
1189
1242
|
close(fd);
|
@@ -1227,6 +1280,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1227
1280
|
watcher.fiber = rb_fiber_current();
|
1228
1281
|
ev_child_init(&watcher.child, Backend_child_callback, NUM2INT(pid), 0);
|
1229
1282
|
ev_child_start(backend->ev_loop, &watcher.child);
|
1283
|
+
backend->base.op_count++;
|
1230
1284
|
|
1231
1285
|
switchpoint_result = backend_await((struct Backend_base *)backend);
|
1232
1286
|
|
@@ -1249,6 +1303,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1249
1303
|
|
1250
1304
|
ev_async_init(&async, Backend_async_callback);
|
1251
1305
|
ev_async_start(backend->ev_loop, &async);
|
1306
|
+
backend->base.op_count++;
|
1252
1307
|
|
1253
1308
|
switchpoint_result = backend_await((struct Backend_base *)backend);
|
1254
1309
|
|
@@ -1293,10 +1348,10 @@ VALUE Backend_idle_gc_period_set(VALUE self, VALUE period) {
|
|
1293
1348
|
return self;
|
1294
1349
|
}
|
1295
1350
|
|
1296
|
-
VALUE
|
1351
|
+
VALUE Backend_idle_proc_set(VALUE self, VALUE block) {
|
1297
1352
|
Backend_t *backend;
|
1298
1353
|
GetBackend(self, backend);
|
1299
|
-
backend->base.
|
1354
|
+
backend->base.idle_proc = block;
|
1300
1355
|
return self;
|
1301
1356
|
}
|
1302
1357
|
|
@@ -1312,6 +1367,7 @@ inline int splice_chunks_write(Backend_t *backend, int fd, VALUE str, struct lib
|
|
1312
1367
|
int len = RSTRING_LEN(str);
|
1313
1368
|
int left = len;
|
1314
1369
|
while (left > 0) {
|
1370
|
+
backend->base.op_count++;
|
1315
1371
|
ssize_t n = write(fd, buf, left);
|
1316
1372
|
if (n < 0) {
|
1317
1373
|
int err = errno;
|
@@ -1372,6 +1428,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1372
1428
|
int chunk_len;
|
1373
1429
|
// splice to pipe
|
1374
1430
|
while (1) {
|
1431
|
+
backend->base.op_count++;
|
1375
1432
|
chunk_len = splice(src_fptr->fd, 0, pipefd[1], 0, maxlen, 0);
|
1376
1433
|
if (chunk_len < 0) {
|
1377
1434
|
err = errno;
|
@@ -1397,6 +1454,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1397
1454
|
|
1398
1455
|
int left = chunk_len;
|
1399
1456
|
while (1) {
|
1457
|
+
backend->base.op_count++;
|
1400
1458
|
int n = splice(pipefd[0], 0, dest_fptr->fd, 0, left, 0);
|
1401
1459
|
if (n < 0) {
|
1402
1460
|
err = errno;
|
@@ -1443,6 +1501,21 @@ error:
|
|
1443
1501
|
return RAISE_EXCEPTION(result);
|
1444
1502
|
}
|
1445
1503
|
|
1504
|
+
VALUE Backend_trace(int argc, VALUE *argv, VALUE self) {
|
1505
|
+
Backend_t *backend;
|
1506
|
+
GetBackend(self, backend);
|
1507
|
+
backend_trace(&backend->base, argc, argv);
|
1508
|
+
return self;
|
1509
|
+
}
|
1510
|
+
|
1511
|
+
VALUE Backend_trace_proc_set(VALUE self, VALUE block) {
|
1512
|
+
Backend_t *backend;
|
1513
|
+
GetBackend(self, backend);
|
1514
|
+
|
1515
|
+
backend->base.trace_proc = block;
|
1516
|
+
return self;
|
1517
|
+
}
|
1518
|
+
|
1446
1519
|
void Init_Backend() {
|
1447
1520
|
ev_set_allocator(xrealloc);
|
1448
1521
|
|
@@ -1452,23 +1525,26 @@ void Init_Backend() {
|
|
1452
1525
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
1453
1526
|
rb_define_method(cBackend, "finalize", Backend_finalize, 0);
|
1454
1527
|
rb_define_method(cBackend, "post_fork", Backend_post_fork, 0);
|
1528
|
+
rb_define_method(cBackend, "trace", Backend_trace, -1);
|
1529
|
+
rb_define_method(cBackend, "trace_proc=", Backend_trace_proc_set, 1);
|
1530
|
+
rb_define_method(cBackend, "stats", Backend_stats, 0);
|
1455
1531
|
|
1456
|
-
rb_define_method(cBackend, "poll", Backend_poll,
|
1532
|
+
rb_define_method(cBackend, "poll", Backend_poll, 1);
|
1457
1533
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
1458
1534
|
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
1459
1535
|
rb_define_method(cBackend, "chain", Backend_chain, -1);
|
1460
1536
|
rb_define_method(cBackend, "idle_gc_period=", Backend_idle_gc_period_set, 1);
|
1461
|
-
rb_define_method(cBackend, "
|
1537
|
+
rb_define_method(cBackend, "idle_proc=", Backend_idle_proc_set, 1);
|
1462
1538
|
rb_define_method(cBackend, "splice_chunks", Backend_splice_chunks, 7);
|
1463
1539
|
|
1464
1540
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
1465
1541
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
1466
1542
|
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
1467
1543
|
rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
|
1468
|
-
rb_define_method(cBackend, "read", Backend_read,
|
1469
|
-
rb_define_method(cBackend, "read_loop", Backend_read_loop,
|
1470
|
-
rb_define_method(cBackend, "recv", Backend_recv,
|
1471
|
-
rb_define_method(cBackend, "recv_loop", Backend_read_loop,
|
1544
|
+
rb_define_method(cBackend, "read", Backend_read, 5);
|
1545
|
+
rb_define_method(cBackend, "read_loop", Backend_read_loop, 2);
|
1546
|
+
rb_define_method(cBackend, "recv", Backend_recv, 4);
|
1547
|
+
rb_define_method(cBackend, "recv_loop", Backend_read_loop, 2);
|
1472
1548
|
rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
|
1473
1549
|
rb_define_method(cBackend, "send", Backend_send, 3);
|
1474
1550
|
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
@@ -1494,6 +1570,8 @@ void Init_Backend() {
|
|
1494
1570
|
SYM_send = ID2SYM(rb_intern("send"));
|
1495
1571
|
SYM_splice = ID2SYM(rb_intern("splice"));
|
1496
1572
|
SYM_write = ID2SYM(rb_intern("write"));
|
1573
|
+
|
1574
|
+
backend_setup_stats_symbols();
|
1497
1575
|
}
|
1498
1576
|
|
1499
1577
|
#endif // POLYPHONY_BACKEND_LIBEV
|