polyphony 0.58 → 0.61
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/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
|