polyphony 0.78 → 0.79
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/examples/core/pingpong.rb +7 -4
- data/ext/polyphony/backend_common.c +14 -7
- data/ext/polyphony/backend_common.h +1 -1
- data/ext/polyphony/backend_io_uring.c +19 -3
- data/ext/polyphony/backend_libev.c +33 -17
- data/ext/polyphony/fiber.c +27 -27
- data/ext/polyphony/polyphony.c +1 -8
- data/ext/polyphony/polyphony.h +10 -7
- data/ext/polyphony/thread.c +6 -2
- data/lib/polyphony/core/debug.rb +144 -0
- data/lib/polyphony/extensions/fiber.rb +6 -4
- data/lib/polyphony/version.rb +1 -1
- data/test/test_io.rb +7 -7
- data/test/test_signal.rb +15 -15
- data/test/test_thread.rb +1 -1
- data/test/test_trace.rb +102 -24
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34ed5a7685a8986f1fe5fd6cd714ee049633952746ecb8bced1aee73553c6c99
|
4
|
+
data.tar.gz: 03ded408e8849a921d0cfbbe1a232c5cea83cfbd58710efade4900f6240f511c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91fe5a0979c0158315e942bba88f563a47926e78ad3da0ff8e483ee91aff1482af1f2fc3e3aa4cacd49e787531627bfc3295d45439e99d8400b4736b1a749443
|
7
|
+
data.tar.gz: 3c1eaaccec661c4f3e4c07853fbaaaab19222837d5ac25b4098856bd1b1367833cbc35a58602fb9c30ff8e7cd63d04f79206bf07438a1e842eb86871c8036063
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/examples/core/pingpong.rb
CHANGED
@@ -3,18 +3,21 @@
|
|
3
3
|
require 'bundler/setup'
|
4
4
|
require 'polyphony'
|
5
5
|
|
6
|
-
|
6
|
+
require 'polyphony/core/debug'
|
7
|
+
Polyphony::Trace.start_event_firehose(STDOUT)
|
8
|
+
|
9
|
+
pong = spin_loop(:pong) do
|
7
10
|
msg, ping = receive
|
8
11
|
puts msg
|
9
12
|
ping << 'pong'
|
10
13
|
end
|
11
14
|
|
12
|
-
ping = spin do
|
13
|
-
|
15
|
+
ping = spin(:ping) do
|
16
|
+
1.times do
|
14
17
|
pong << ['ping', Fiber.current]
|
15
18
|
msg = receive
|
16
19
|
puts msg
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
20
|
-
ping.await
|
23
|
+
ping.await
|
@@ -65,7 +65,7 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
|
|
65
65
|
|
66
66
|
base->switch_count++;
|
67
67
|
if (SHOULD_TRACE(base))
|
68
|
-
TRACE(base, 3,
|
68
|
+
TRACE(base, 3, SYM_block, current_fiber, CALLER());
|
69
69
|
|
70
70
|
while (1) {
|
71
71
|
next = runqueue_shift(&base->runqueue);
|
@@ -96,8 +96,6 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
|
|
96
96
|
if (next.fiber == Qnil) return Qnil;
|
97
97
|
|
98
98
|
// run next fiber
|
99
|
-
COND_TRACE(base, 3, SYM_fiber_run, next.fiber, next.value);
|
100
|
-
|
101
99
|
rb_ivar_set(next.fiber, ID_ivar_runnable, Qnil);
|
102
100
|
RB_GC_GUARD(next.fiber);
|
103
101
|
RB_GC_GUARD(next.value);
|
@@ -112,7 +110,7 @@ void backend_base_schedule_fiber(VALUE thread, VALUE backend, struct Backend_bas
|
|
112
110
|
if (rb_fiber_alive_p(fiber) != Qtrue) return;
|
113
111
|
already_runnable = rb_ivar_get(fiber, ID_ivar_runnable) != Qnil;
|
114
112
|
|
115
|
-
COND_TRACE(base,
|
113
|
+
COND_TRACE(base, 5, SYM_schedule, fiber, value, prioritize ? Qtrue : Qfalse, CALLER());
|
116
114
|
|
117
115
|
runqueue = rb_ivar_get(fiber, ID_ivar_parked) == Qtrue ? &base->parked_runqueue : &base->runqueue;
|
118
116
|
|
@@ -244,15 +242,24 @@ inline VALUE backend_await(struct Backend_base *backend) {
|
|
244
242
|
VALUE ret;
|
245
243
|
backend->pending_count++;
|
246
244
|
ret = Thread_switch_fiber(rb_thread_current());
|
245
|
+
|
246
|
+
// run next fiber
|
247
|
+
COND_TRACE(backend, 4, SYM_unblock, rb_fiber_current(), ret, CALLER());
|
248
|
+
|
247
249
|
backend->pending_count--;
|
248
250
|
RB_GC_GUARD(ret);
|
249
251
|
return ret;
|
250
252
|
}
|
251
253
|
|
252
|
-
inline VALUE backend_snooze() {
|
254
|
+
inline VALUE backend_snooze(struct Backend_base *backend) {
|
253
255
|
VALUE ret;
|
254
|
-
|
255
|
-
|
256
|
+
VALUE fiber = rb_fiber_current();
|
257
|
+
VALUE thread = rb_thread_current();
|
258
|
+
Fiber_make_runnable(fiber, Qnil);
|
259
|
+
ret = Thread_switch_fiber(thread);
|
260
|
+
|
261
|
+
COND_TRACE(backend, 4, SYM_unblock, fiber, ret, CALLER());
|
262
|
+
|
256
263
|
return ret;
|
257
264
|
}
|
258
265
|
|
@@ -80,7 +80,7 @@ void fptr_finalize(rb_io_t *fptr);
|
|
80
80
|
|
81
81
|
struct backend_stats backend_get_stats(VALUE self);
|
82
82
|
VALUE backend_await(struct Backend_base *backend);
|
83
|
-
VALUE backend_snooze();
|
83
|
+
VALUE backend_snooze(struct Backend_base *backend);
|
84
84
|
|
85
85
|
// macros for doing read loops
|
86
86
|
#define READ_LOOP_PREPARE_STR() { \
|
@@ -216,12 +216,12 @@ inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
|
216
216
|
io_uring_submit(&backend->ring);
|
217
217
|
}
|
218
218
|
|
219
|
-
COND_TRACE(&backend->base, 2,
|
219
|
+
COND_TRACE(&backend->base, 2, SYM_enter_poll, rb_fiber_current());
|
220
220
|
|
221
221
|
if (is_blocking) io_uring_backend_poll(backend);
|
222
222
|
io_uring_backend_handle_ready_cqes(backend);
|
223
223
|
|
224
|
-
COND_TRACE(&backend->base, 2,
|
224
|
+
COND_TRACE(&backend->base, 2, SYM_leave_poll, rb_fiber_current());
|
225
225
|
|
226
226
|
return self;
|
227
227
|
}
|
@@ -1108,7 +1108,7 @@ VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
1108
1108
|
if (!completed) return resume_value;
|
1109
1109
|
}
|
1110
1110
|
else {
|
1111
|
-
resume_value = backend_snooze();
|
1111
|
+
resume_value = backend_snooze(&backend->base);
|
1112
1112
|
RAISE_IF_EXCEPTION(resume_value);
|
1113
1113
|
}
|
1114
1114
|
|
@@ -1591,6 +1591,22 @@ VALUE Backend_trace_proc_set(VALUE self, VALUE block) {
|
|
1591
1591
|
return self;
|
1592
1592
|
}
|
1593
1593
|
|
1594
|
+
VALUE Backend_snooze(VALUE self) {
|
1595
|
+
VALUE ret;
|
1596
|
+
VALUE fiber = rb_fiber_current();
|
1597
|
+
Backend_t *backend;
|
1598
|
+
GetBackend(self, backend);
|
1599
|
+
|
1600
|
+
Fiber_make_runnable(fiber, Qnil);
|
1601
|
+
ret = Thread_switch_fiber(rb_thread_current());
|
1602
|
+
|
1603
|
+
COND_TRACE(&backend->base, 4, SYM_unblock, rb_fiber_current(), ret, CALLER());
|
1604
|
+
|
1605
|
+
RAISE_IF_EXCEPTION(ret);
|
1606
|
+
RB_GC_GUARD(ret);
|
1607
|
+
return ret;
|
1608
|
+
}
|
1609
|
+
|
1594
1610
|
void Backend_park_fiber(VALUE self, VALUE fiber) {
|
1595
1611
|
Backend_t *backend;
|
1596
1612
|
GetBackend(self, backend);
|
@@ -168,7 +168,7 @@ inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
|
168
168
|
|
169
169
|
backend->base.poll_count++;
|
170
170
|
|
171
|
-
COND_TRACE(&backend->base, 2,
|
171
|
+
COND_TRACE(&backend->base, 2, SYM_enter_poll, rb_fiber_current());
|
172
172
|
|
173
173
|
ev_run:
|
174
174
|
backend->base.currently_polling = 1;
|
@@ -177,7 +177,7 @@ ev_run:
|
|
177
177
|
backend->base.currently_polling = 0;
|
178
178
|
if (errno == EINTR && runqueue_empty_p(&backend->base.runqueue)) goto ev_run;
|
179
179
|
|
180
|
-
COND_TRACE(&backend->base, 2,
|
180
|
+
COND_TRACE(&backend->base, 2, SYM_leave_poll, rb_fiber_current());
|
181
181
|
|
182
182
|
return self;
|
183
183
|
}
|
@@ -305,7 +305,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
305
305
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
306
306
|
}
|
307
307
|
else {
|
308
|
-
switchpoint_result = backend_snooze();
|
308
|
+
switchpoint_result = backend_snooze(&backend->base);
|
309
309
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
310
310
|
|
311
311
|
if (n == 0) break; // EOF
|
@@ -375,7 +375,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
375
375
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
376
376
|
}
|
377
377
|
else {
|
378
|
-
switchpoint_result = backend_snooze();
|
378
|
+
switchpoint_result = backend_snooze(&backend->base);
|
379
379
|
|
380
380
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
381
381
|
|
@@ -428,7 +428,7 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
428
428
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
429
429
|
}
|
430
430
|
else {
|
431
|
-
switchpoint_result = backend_snooze();
|
431
|
+
switchpoint_result = backend_snooze(&backend->base);
|
432
432
|
|
433
433
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
434
434
|
|
@@ -483,7 +483,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
483
483
|
}
|
484
484
|
|
485
485
|
if (watcher.fiber == Qnil) {
|
486
|
-
switchpoint_result = backend_snooze();
|
486
|
+
switchpoint_result = backend_snooze(&backend->base);
|
487
487
|
|
488
488
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
489
489
|
}
|
@@ -558,7 +558,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
558
558
|
}
|
559
559
|
}
|
560
560
|
if (watcher.fiber == Qnil) {
|
561
|
-
switchpoint_result = backend_snooze();
|
561
|
+
switchpoint_result = backend_snooze(&backend->base);
|
562
562
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
563
563
|
}
|
564
564
|
|
@@ -611,7 +611,7 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
611
611
|
else {
|
612
612
|
VALUE socket;
|
613
613
|
rb_io_t *fp;
|
614
|
-
switchpoint_result = backend_snooze();
|
614
|
+
switchpoint_result = backend_snooze(&backend->base);
|
615
615
|
|
616
616
|
if (TEST_EXCEPTION(switchpoint_result)) {
|
617
617
|
close(fd); // close fd since we're raising an exception
|
@@ -669,7 +669,7 @@ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
669
669
|
}
|
670
670
|
else {
|
671
671
|
rb_io_t *fp;
|
672
|
-
switchpoint_result = backend_snooze();
|
672
|
+
switchpoint_result = backend_snooze(&backend->base);
|
673
673
|
|
674
674
|
if (TEST_EXCEPTION(switchpoint_result)) {
|
675
675
|
close(fd); // close fd since we're raising an exception
|
@@ -727,7 +727,7 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
727
727
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
728
728
|
}
|
729
729
|
else {
|
730
|
-
switchpoint_result = backend_snooze();
|
730
|
+
switchpoint_result = backend_snooze(&backend->base);
|
731
731
|
|
732
732
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
733
733
|
}
|
@@ -774,7 +774,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
774
774
|
}
|
775
775
|
|
776
776
|
if (watcher.fiber == Qnil) {
|
777
|
-
switchpoint_result = backend_snooze();
|
777
|
+
switchpoint_result = backend_snooze(&backend->base);
|
778
778
|
|
779
779
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
780
780
|
}
|
@@ -880,7 +880,7 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
880
880
|
}
|
881
881
|
|
882
882
|
if (watcher.ctx.fiber == Qnil) {
|
883
|
-
switchpoint_result = backend_snooze();
|
883
|
+
switchpoint_result = backend_snooze(&backend->base);
|
884
884
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
885
885
|
}
|
886
886
|
|
@@ -935,7 +935,7 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
935
935
|
}
|
936
936
|
|
937
937
|
if (watcher.ctx.fiber == Qnil) {
|
938
|
-
switchpoint_result = backend_snooze();
|
938
|
+
switchpoint_result = backend_snooze(&backend->base);
|
939
939
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
940
940
|
}
|
941
941
|
|
@@ -1009,7 +1009,7 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1009
1009
|
}
|
1010
1010
|
|
1011
1011
|
if (watcher.fiber == Qnil) {
|
1012
|
-
switchpoint_result = backend_snooze();
|
1012
|
+
switchpoint_result = backend_snooze(&backend->base);
|
1013
1013
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1014
1014
|
}
|
1015
1015
|
|
@@ -1089,7 +1089,7 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1089
1089
|
|
1090
1090
|
done:
|
1091
1091
|
if (watcher.fiber == Qnil) {
|
1092
|
-
switchpoint_result = backend_snooze();
|
1092
|
+
switchpoint_result = backend_snooze(&backend->base);
|
1093
1093
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1094
1094
|
}
|
1095
1095
|
|
@@ -1171,7 +1171,7 @@ noreturn VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
1171
1171
|
RAISE_IF_EXCEPTION(resume_value);
|
1172
1172
|
}
|
1173
1173
|
else {
|
1174
|
-
resume_value = backend_snooze();
|
1174
|
+
resume_value = backend_snooze(&backend->base);
|
1175
1175
|
RAISE_IF_EXCEPTION(resume_value);
|
1176
1176
|
}
|
1177
1177
|
|
@@ -1530,7 +1530,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1530
1530
|
}
|
1531
1531
|
|
1532
1532
|
if (watcher.ctx.fiber == Qnil) {
|
1533
|
-
result = backend_snooze();
|
1533
|
+
result = backend_snooze(&backend->base);
|
1534
1534
|
if (TEST_EXCEPTION(result)) goto error;
|
1535
1535
|
}
|
1536
1536
|
RB_GC_GUARD(str);
|
@@ -1564,6 +1564,22 @@ VALUE Backend_trace_proc_set(VALUE self, VALUE block) {
|
|
1564
1564
|
return self;
|
1565
1565
|
}
|
1566
1566
|
|
1567
|
+
VALUE Backend_snooze(VALUE self) {
|
1568
|
+
VALUE ret;
|
1569
|
+
VALUE fiber = rb_fiber_current();
|
1570
|
+
Backend_t *backend;
|
1571
|
+
GetBackend(self, backend);
|
1572
|
+
|
1573
|
+
Fiber_make_runnable(fiber, Qnil);
|
1574
|
+
ret = Thread_switch_fiber(rb_thread_current());
|
1575
|
+
|
1576
|
+
COND_TRACE(&backend->base, 4, SYM_unblock, rb_fiber_current(), ret, CALLER());
|
1577
|
+
|
1578
|
+
RAISE_IF_EXCEPTION(ret);
|
1579
|
+
RB_GC_GUARD(ret);
|
1580
|
+
return ret;
|
1581
|
+
}
|
1582
|
+
|
1567
1583
|
void Backend_park_fiber(VALUE self, VALUE fiber) {
|
1568
1584
|
Backend_t *backend;
|
1569
1585
|
GetBackend(self, backend);
|
data/ext/polyphony/fiber.c
CHANGED
@@ -10,13 +10,13 @@ VALUE SYM_running;
|
|
10
10
|
VALUE SYM_runnable;
|
11
11
|
VALUE SYM_waiting;
|
12
12
|
|
13
|
-
VALUE
|
14
|
-
VALUE
|
15
|
-
VALUE
|
16
|
-
VALUE
|
17
|
-
VALUE
|
18
|
-
VALUE
|
19
|
-
VALUE
|
13
|
+
VALUE SYM_spin;
|
14
|
+
VALUE SYM_enter_poll;
|
15
|
+
VALUE SYM_leave_poll;
|
16
|
+
VALUE SYM_unblock;
|
17
|
+
VALUE SYM_schedule;
|
18
|
+
VALUE SYM_block;
|
19
|
+
VALUE SYM_terminate;
|
20
20
|
|
21
21
|
static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self) {
|
22
22
|
VALUE arg = (argc == 0) ? Qnil : argv[0];
|
@@ -157,24 +157,24 @@ void Init_Fiber() {
|
|
157
157
|
rb_global_variable(&SYM_runnable);
|
158
158
|
rb_global_variable(&SYM_waiting);
|
159
159
|
|
160
|
-
ID_ivar_auto_watcher
|
161
|
-
ID_ivar_mailbox
|
162
|
-
ID_ivar_result
|
163
|
-
ID_ivar_waiting_fibers
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
rb_global_variable(&
|
174
|
-
rb_global_variable(&
|
175
|
-
rb_global_variable(&
|
176
|
-
rb_global_variable(&
|
177
|
-
rb_global_variable(&
|
178
|
-
rb_global_variable(&
|
179
|
-
rb_global_variable(&
|
160
|
+
ID_ivar_auto_watcher = rb_intern("@auto_watcher");
|
161
|
+
ID_ivar_mailbox = rb_intern("@mailbox");
|
162
|
+
ID_ivar_result = rb_intern("@result");
|
163
|
+
ID_ivar_waiting_fibers = rb_intern("@waiting_fibers");
|
164
|
+
|
165
|
+
SYM_spin = ID2SYM(rb_intern("spin"));
|
166
|
+
SYM_enter_poll = ID2SYM(rb_intern("enter_poll"));
|
167
|
+
SYM_leave_poll = ID2SYM(rb_intern("leave_poll"));
|
168
|
+
SYM_unblock = ID2SYM(rb_intern("unblock"));
|
169
|
+
SYM_schedule = ID2SYM(rb_intern("schedule"));
|
170
|
+
SYM_block = ID2SYM(rb_intern("block"));
|
171
|
+
SYM_terminate = ID2SYM(rb_intern("terminate"));
|
172
|
+
|
173
|
+
rb_global_variable(&SYM_spin);
|
174
|
+
rb_global_variable(&SYM_enter_poll);
|
175
|
+
rb_global_variable(&SYM_leave_poll);
|
176
|
+
rb_global_variable(&SYM_unblock);
|
177
|
+
rb_global_variable(&SYM_schedule);
|
178
|
+
rb_global_variable(&SYM_block);
|
179
|
+
rb_global_variable(&SYM_terminate);
|
180
180
|
}
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -27,14 +27,7 @@ ID ID_W;
|
|
27
27
|
ID ID_RW;
|
28
28
|
|
29
29
|
VALUE Polyphony_snooze(VALUE self) {
|
30
|
-
|
31
|
-
VALUE fiber = rb_fiber_current();
|
32
|
-
|
33
|
-
Fiber_make_runnable(fiber, Qnil);
|
34
|
-
ret = Thread_switch_fiber(rb_thread_current());
|
35
|
-
RAISE_IF_EXCEPTION(ret);
|
36
|
-
RB_GC_GUARD(ret);
|
37
|
-
return ret;
|
30
|
+
return Backend_snooze(BACKEND());
|
38
31
|
}
|
39
32
|
|
40
33
|
static VALUE Polyphony_suspend(VALUE self) {
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -61,13 +61,13 @@ extern ID ID_switch_fiber;
|
|
61
61
|
extern ID ID_to_s;
|
62
62
|
extern ID ID_transfer;
|
63
63
|
|
64
|
-
extern VALUE
|
65
|
-
extern VALUE
|
66
|
-
extern VALUE
|
67
|
-
extern VALUE
|
68
|
-
extern VALUE
|
69
|
-
extern VALUE
|
70
|
-
extern VALUE
|
64
|
+
extern VALUE SYM_spin;
|
65
|
+
extern VALUE SYM_enter_poll;
|
66
|
+
extern VALUE SYM_leave_poll;
|
67
|
+
extern VALUE SYM_unblock;
|
68
|
+
extern VALUE SYM_schedule;
|
69
|
+
extern VALUE SYM_block;
|
70
|
+
extern VALUE SYM_terminate;
|
71
71
|
|
72
72
|
VALUE Fiber_auto_watcher(VALUE self);
|
73
73
|
void Fiber_make_runnable(VALUE fiber, VALUE value);
|
@@ -121,11 +121,14 @@ VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
|
|
121
121
|
VALUE Backend_wakeup(VALUE self);
|
122
122
|
VALUE Backend_run_idle_tasks(VALUE self);
|
123
123
|
VALUE Backend_switch_fiber(VALUE self);
|
124
|
+
|
124
125
|
void Backend_schedule_fiber(VALUE thread, VALUE self, VALUE fiber, VALUE value, int prioritize);
|
125
126
|
void Backend_unschedule_fiber(VALUE self, VALUE fiber);
|
126
127
|
void Backend_park_fiber(VALUE self, VALUE fiber);
|
127
128
|
void Backend_unpark_fiber(VALUE self, VALUE fiber);
|
128
129
|
|
130
|
+
VALUE Backend_snooze(VALUE self);
|
131
|
+
|
129
132
|
void Thread_schedule_fiber(VALUE thread, VALUE fiber, VALUE value);
|
130
133
|
void Thread_schedule_fiber_with_priority(VALUE thread, VALUE fiber, VALUE value);
|
131
134
|
VALUE Thread_switch_fiber(VALUE thread);
|
data/ext/polyphony/thread.c
CHANGED
@@ -23,11 +23,15 @@ VALUE Thread_fiber_unschedule(VALUE self, VALUE fiber) {
|
|
23
23
|
}
|
24
24
|
|
25
25
|
inline void Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
|
26
|
-
|
26
|
+
Backend_schedule_fiber(self, rb_ivar_get(self, ID_ivar_backend), fiber, value, 0);
|
27
|
+
|
28
|
+
// schedule_fiber(self, fiber, value, 0);
|
27
29
|
}
|
28
30
|
|
29
31
|
inline void Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE value) {
|
30
|
-
|
32
|
+
Backend_schedule_fiber(self, rb_ivar_get(self, ID_ivar_backend), fiber, value, 1);
|
33
|
+
|
34
|
+
// schedule_fiber(self, fiber, value, 1);
|
31
35
|
}
|
32
36
|
|
33
37
|
VALUE Thread_switch_fiber(VALUE self) {
|
data/lib/polyphony/core/debug.rb
CHANGED
@@ -13,3 +13,147 @@ module ::Kernel
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
module Polyphony
|
18
|
+
module Trace
|
19
|
+
class << self
|
20
|
+
def start_event_firehose(io = nil, &block)
|
21
|
+
Thread.backend.trace_proc = firehose_proc(io, block)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def firehose_proc(io, block)
|
27
|
+
if io
|
28
|
+
->(*e) { io.orig_write("#{trace_event_info(e).inspect}\n") }
|
29
|
+
elsif block
|
30
|
+
->(*e) { block.(trace_event_info(e)) }
|
31
|
+
else
|
32
|
+
raise "Please provide an io or a block"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def trace_event_info(e)
|
37
|
+
{
|
38
|
+
stamp: format_current_time,
|
39
|
+
event: e[0]
|
40
|
+
}.merge(
|
41
|
+
send(:"event_props_#{e[0]}", e)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
def format_trace_event_message(e)
|
46
|
+
props = send(:"event_props_#{e[0]}", e).merge(
|
47
|
+
timestamp: format_current_time,
|
48
|
+
event: e[0]
|
49
|
+
)
|
50
|
+
# templ = send(:"event_format_#{e[0]}", e)
|
51
|
+
|
52
|
+
# msg = format("%<timestamp>s #{templ}\n", **props)
|
53
|
+
end
|
54
|
+
|
55
|
+
def format_current_time
|
56
|
+
Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
57
|
+
end
|
58
|
+
|
59
|
+
def generic_event_format
|
60
|
+
'%<event>-12.12s'
|
61
|
+
end
|
62
|
+
|
63
|
+
def fiber_event_format
|
64
|
+
"#{generic_event_format} %<fiber>-44.44s"
|
65
|
+
end
|
66
|
+
|
67
|
+
def event_props_enter_poll(e)
|
68
|
+
{}
|
69
|
+
end
|
70
|
+
|
71
|
+
def event_format_enter_poll(e)
|
72
|
+
generic_event_format
|
73
|
+
end
|
74
|
+
|
75
|
+
def event_props_leave_poll(e)
|
76
|
+
{}
|
77
|
+
end
|
78
|
+
|
79
|
+
def event_format_leave_poll(e)
|
80
|
+
generic_event_format
|
81
|
+
end
|
82
|
+
|
83
|
+
def event_props_schedule(e)
|
84
|
+
{
|
85
|
+
fiber: e[1],
|
86
|
+
value: e[2],
|
87
|
+
caller: e[4],
|
88
|
+
source_fiber: Fiber.current
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def event_format_schedule(e)
|
93
|
+
"#{fiber_event_format} %<value>-24.24p %<caller>-120.120s <= %<origin_fiber>s"
|
94
|
+
end
|
95
|
+
|
96
|
+
def event_props_unblock(e)
|
97
|
+
{
|
98
|
+
fiber: e[1],
|
99
|
+
value: e[2],
|
100
|
+
caller: e[3],
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
def event_format_unblock(e)
|
105
|
+
"#{fiber_event_format} %<value>-24.24p %<caller>-120.120s"
|
106
|
+
end
|
107
|
+
|
108
|
+
def event_props_terminate(e)
|
109
|
+
{
|
110
|
+
fiber: e[1],
|
111
|
+
value: e[2],
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def event_format_terminate(e)
|
116
|
+
"#{fiber_event_format} %<value>-24.24p"
|
117
|
+
end
|
118
|
+
|
119
|
+
def event_props_block(e)
|
120
|
+
{
|
121
|
+
fiber: e[1],
|
122
|
+
caller: e[2]
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
def event_format_block(e)
|
127
|
+
"#{fiber_event_format} #{' ' * 24} %<caller>-120.120s"
|
128
|
+
end
|
129
|
+
|
130
|
+
def event_props_spin(e)
|
131
|
+
{
|
132
|
+
fiber: e[1],
|
133
|
+
caller: e[2],
|
134
|
+
source_fiber: Fiber.current
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
def event_format_spin(e)
|
139
|
+
"#{fiber_event_format} #{' ' * 24} %<caller>-120.120s <= %<origin_fiber>s"
|
140
|
+
end
|
141
|
+
|
142
|
+
def fibe_repr(fiber)
|
143
|
+
format("%-6x %-20.20s %-10.10s", fiber.object_id, fiber.tag, "(#{fiber.state})")
|
144
|
+
end
|
145
|
+
|
146
|
+
def fiber_compact_repr(fiber)
|
147
|
+
if fiber.tag
|
148
|
+
format("%-6x %-.20s %-.10s", fiber.object_id, fiber.tag, "(#{fiber.state})")
|
149
|
+
else
|
150
|
+
format("%-6x %-.10s", fiber.object_id, "(#{fiber.state})")
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def caller_repr(c)
|
155
|
+
c.map { |i| i.gsub('/home/sharon/repo/polyphony/lib/polyphony', '') }.join(' ')
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -250,16 +250,17 @@ module Polyphony
|
|
250
250
|
def schedule_priority_oob_fiber(&block)
|
251
251
|
oob_fiber = Fiber.new do
|
252
252
|
Fiber.current.setup_raw
|
253
|
+
Thread.backend.trace(:unblock, oob_fiber, nil, @caller)
|
253
254
|
result = block.call
|
254
255
|
rescue Exception => e
|
255
256
|
Thread.current.schedule_and_wakeup(Thread.main.main_fiber, e)
|
256
257
|
result = e
|
257
258
|
ensure
|
258
|
-
Thread.backend.trace(:
|
259
|
+
Thread.backend.trace(:terminate, Fiber.current, result)
|
259
260
|
suspend
|
260
261
|
end
|
261
262
|
prepare_oob_fiber(oob_fiber, block)
|
262
|
-
Thread.backend.trace(:
|
263
|
+
Thread.backend.trace(:spin, oob_fiber, caller)
|
263
264
|
oob_fiber.schedule_with_priority(nil)
|
264
265
|
end
|
265
266
|
|
@@ -355,12 +356,13 @@ module Polyphony
|
|
355
356
|
@parent = parent
|
356
357
|
@caller = caller
|
357
358
|
@block = block
|
358
|
-
Thread.backend.trace(:
|
359
|
+
Thread.backend.trace(:spin, self, Kernel.caller[1..-1])
|
359
360
|
schedule
|
360
361
|
end
|
361
362
|
|
362
363
|
def run(first_value)
|
363
364
|
setup first_value
|
365
|
+
Thread.backend.trace(:unblock, self, first_value, @caller)
|
364
366
|
result = @block.(first_value)
|
365
367
|
finalize result
|
366
368
|
rescue Polyphony::Restart => e
|
@@ -402,7 +404,7 @@ module Polyphony
|
|
402
404
|
|
403
405
|
def finalize(result, uncaught_exception = false)
|
404
406
|
result, uncaught_exception = finalize_children(result, uncaught_exception)
|
405
|
-
Thread.backend.trace(:
|
407
|
+
Thread.backend.trace(:terminate, self, result)
|
406
408
|
@result = result
|
407
409
|
|
408
410
|
inform_monitors(result, uncaught_exception)
|
data/lib/polyphony/version.rb
CHANGED
data/test/test_io.rb
CHANGED
@@ -309,13 +309,13 @@ class IOClassMethodsTest < MiniTest::Test
|
|
309
309
|
assert_equal BIN_DATA, s
|
310
310
|
end
|
311
311
|
|
312
|
-
def test_foreach
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
end
|
312
|
+
# def test_foreach
|
313
|
+
# skip 'IO.foreach is not yet implemented'
|
314
|
+
# lines = []
|
315
|
+
# IO.foreach(__FILE__) { |l| lines << l }
|
316
|
+
# assert_equal "# frozen_string_literal: true\n", lines[0]
|
317
|
+
# assert_equal "end\n", lines[-1]
|
318
|
+
# end
|
319
319
|
|
320
320
|
def test_read_class_method
|
321
321
|
s = IO.read(__FILE__)
|
data/test/test_signal.rb
CHANGED
@@ -33,24 +33,24 @@ class SignalTrapTest < Minitest::Test
|
|
33
33
|
Fiber.current.tag = :main
|
34
34
|
|
35
35
|
expected = [
|
36
|
-
[:
|
37
|
-
[:
|
38
|
-
[:
|
39
|
-
[:
|
40
|
-
[:
|
41
|
-
[:
|
42
|
-
[:
|
43
|
-
[:
|
44
|
-
[:
|
45
|
-
[:
|
46
|
-
[:
|
47
|
-
[:
|
36
|
+
[:block, :main],
|
37
|
+
[:enter_poll, :main],
|
38
|
+
[:spin, :oob],
|
39
|
+
[:schedule, :oob],
|
40
|
+
[:leave_poll, :main],
|
41
|
+
[:unblock, :oob],
|
42
|
+
[:terminate, :oob],
|
43
|
+
[:block, :oob],
|
44
|
+
[:enter_poll, :oob],
|
45
|
+
[:schedule, :main],
|
46
|
+
[:leave_poll, :oob],
|
47
|
+
[:unblock, :main]
|
48
48
|
]
|
49
49
|
if Thread.backend.kind == :libev
|
50
50
|
expected += [
|
51
|
-
[:
|
52
|
-
[:
|
53
|
-
[:
|
51
|
+
[:schedule, :main],
|
52
|
+
[:block, :main],
|
53
|
+
[:unblock, :main]
|
54
54
|
]
|
55
55
|
end
|
56
56
|
|
data/test/test_thread.rb
CHANGED
@@ -132,7 +132,7 @@ class ThreadTest < MiniTest::Test
|
|
132
132
|
Thread.backend.trace_proc = proc {|*r| records << r }
|
133
133
|
suspend
|
134
134
|
assert_equal [
|
135
|
-
[:
|
135
|
+
[:block, Fiber.current, ["#{__FILE__}:#{__LINE__ - 2}:in `test_that_suspend_returns_immediately_if_no_watchers'"] + caller]
|
136
136
|
], records
|
137
137
|
ensure
|
138
138
|
Thread.backend.trace_proc = nil
|
data/test/test_trace.rb
CHANGED
@@ -1,17 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'helper'
|
4
|
+
require 'polyphony/core/debug'
|
4
5
|
|
5
6
|
class TraceTest < MiniTest::Test
|
6
7
|
def test_tracing_enabled
|
7
8
|
events = []
|
8
|
-
|
9
|
+
|
10
|
+
Thread.backend.trace_proc = proc { |*e|
|
11
|
+
case e[0]
|
12
|
+
when :schedule
|
13
|
+
e = e[0..3]
|
14
|
+
when :block
|
15
|
+
e = e[0..1]
|
16
|
+
when :unblock
|
17
|
+
e = e[0..2]
|
18
|
+
end
|
19
|
+
events << e
|
20
|
+
}
|
9
21
|
snooze
|
10
22
|
|
11
23
|
assert_equal [
|
12
|
-
[:
|
13
|
-
[:
|
14
|
-
[:
|
24
|
+
[:schedule, Fiber.current, nil, false],
|
25
|
+
[:block, Fiber.current],
|
26
|
+
[:unblock, Fiber.current, nil]
|
15
27
|
], events
|
16
28
|
ensure
|
17
29
|
Thread.backend.trace_proc = nil
|
@@ -19,7 +31,17 @@ class TraceTest < MiniTest::Test
|
|
19
31
|
|
20
32
|
def test_2_fiber_trace
|
21
33
|
events = []
|
22
|
-
Thread.backend.trace_proc = proc { |*e|
|
34
|
+
Thread.backend.trace_proc = proc { |*e|
|
35
|
+
case e[0]
|
36
|
+
when :schedule
|
37
|
+
e = e[0..3]
|
38
|
+
when :spin, :block
|
39
|
+
e = e[0..1]
|
40
|
+
when :unblock
|
41
|
+
e = e[0..2]
|
42
|
+
end
|
43
|
+
events << e
|
44
|
+
}
|
23
45
|
|
24
46
|
f = spin { sleep 0; :byebye }
|
25
47
|
l0 = __LINE__ + 1
|
@@ -28,28 +50,84 @@ class TraceTest < MiniTest::Test
|
|
28
50
|
|
29
51
|
Thread.backend.trace_proc = nil
|
30
52
|
|
31
|
-
# remove caller info for :fiber_switchpoint events
|
32
|
-
events.each {|e| e.pop if e[0] == :fiber_switchpoint }
|
33
|
-
|
34
53
|
assert_equal [
|
35
|
-
[:
|
36
|
-
[:
|
37
|
-
[:
|
38
|
-
[:
|
39
|
-
[:
|
40
|
-
[:
|
41
|
-
[:
|
42
|
-
[:
|
43
|
-
[:
|
44
|
-
[:
|
45
|
-
[:
|
46
|
-
[:
|
47
|
-
[:
|
48
|
-
[:
|
49
|
-
[:
|
50
|
-
[:
|
54
|
+
[:spin, f],
|
55
|
+
[:schedule, f, nil, false],
|
56
|
+
[:block, Fiber.current],
|
57
|
+
[:unblock, f, nil],
|
58
|
+
[:block, f],
|
59
|
+
[:enter_poll, f],
|
60
|
+
[:schedule, f, nil, false],
|
61
|
+
[:leave_poll, f],
|
62
|
+
[:unblock, f, nil],
|
63
|
+
[:terminate, f, :byebye],
|
64
|
+
[:block, f],
|
65
|
+
[:block, Fiber.current],
|
66
|
+
[:enter_poll, Fiber.current],
|
67
|
+
[:schedule, Fiber.current, nil, false],
|
68
|
+
[:leave_poll, Fiber.current],
|
69
|
+
[:unblock, Fiber.current, nil]
|
51
70
|
], events
|
52
71
|
ensure
|
53
72
|
Thread.backend.trace_proc = nil
|
54
73
|
end
|
74
|
+
|
75
|
+
def test_event_firehose
|
76
|
+
buffer = []
|
77
|
+
Polyphony::Trace.start_event_firehose { |e| buffer << e }
|
78
|
+
|
79
|
+
f1 = spin(:f1) do
|
80
|
+
receive
|
81
|
+
end
|
82
|
+
|
83
|
+
f1 << :foo
|
84
|
+
f1.await
|
85
|
+
|
86
|
+
Thread.backend.trace_proc = nil
|
87
|
+
|
88
|
+
buffer.each { |e| e.delete(:stamp); e.delete(:caller) }
|
89
|
+
|
90
|
+
main = Fiber.current
|
91
|
+
assert_equal(
|
92
|
+
[
|
93
|
+
{ event: :spin, fiber: f1, source_fiber: main },
|
94
|
+
{ event: :schedule, fiber: f1, value: nil, source_fiber: main },
|
95
|
+
{ event: :block, fiber: main },
|
96
|
+
{ event: :unblock, fiber: f1, value: nil },
|
97
|
+
{ event: :schedule, fiber: f1, value: nil, source_fiber: f1 },
|
98
|
+
{ event: :block, fiber: f1, },
|
99
|
+
{ event: :enter_poll },
|
100
|
+
{ event: :leave_poll },
|
101
|
+
{ event: :unblock, fiber: f1, value: nil },
|
102
|
+
{ event: :terminate, fiber: f1, value: :foo },
|
103
|
+
{ event: :schedule, fiber: main, value: nil, source_fiber: f1 },
|
104
|
+
{ event: :block, fiber: f1 },
|
105
|
+
{ event: :unblock, fiber: main, value: nil }
|
106
|
+
], buffer
|
107
|
+
)
|
108
|
+
ensure
|
109
|
+
Thread.backend.trace_proc = nil
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_event_firehose_with_io
|
113
|
+
r, w = IO.pipe
|
114
|
+
Polyphony::Trace.start_event_firehose(w)
|
115
|
+
|
116
|
+
f1 = spin(:f1) do
|
117
|
+
receive
|
118
|
+
end
|
119
|
+
|
120
|
+
f1 << :foo
|
121
|
+
f1.await
|
122
|
+
|
123
|
+
Thread.backend.trace_proc = nil
|
124
|
+
w.close
|
125
|
+
|
126
|
+
log = r.read
|
127
|
+
assert_equal 13, log.lines.size
|
128
|
+
|
129
|
+
# TODO: make sure log is formatted correctly
|
130
|
+
ensure
|
131
|
+
Thread.backend.trace_proc = nil
|
132
|
+
end
|
55
133
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: polyphony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.79'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
11
|
+
date: 2022-02-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|