polyphony 0.78 → 0.79
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 +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
|