polyphony 0.72 → 0.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +2 -2
- data/.gitignore +3 -1
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +2 -2
- data/docs/api-reference/exception.md +5 -1
- data/examples/core/ring.rb +29 -0
- data/ext/polyphony/backend_common.c +7 -1
- data/ext/polyphony/backend_common.h +1 -1
- data/ext/polyphony/backend_io_uring.c +31 -28
- data/ext/polyphony/backend_libev.c +27 -21
- data/ext/polyphony/extconf.rb +1 -0
- data/ext/polyphony/polyphony.h +5 -1
- data/ext/polyphony/thread.c +1 -1
- data/lib/polyphony/{extensions → core}/debug.rb +0 -0
- data/lib/polyphony/core/global_api.rb +0 -3
- data/lib/polyphony/extensions/exception.rb +45 -0
- data/lib/polyphony/extensions/fiber.rb +0 -1
- data/lib/polyphony/extensions/{core.rb → kernel.rb} +0 -73
- data/lib/polyphony/extensions/process.rb +19 -0
- data/lib/polyphony/extensions/timeout.rb +10 -0
- data/lib/polyphony/extensions.rb +9 -0
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +2 -5
- data/test/test_global_api.rb +14 -1
- data/test/test_process_supervision.rb +1 -1
- data/test/test_signal.rb +20 -1
- metadata +14 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfcb66ef2171cc3c4216bc674c38468ef4bd23333031ec77d61d74bc17b32c33
|
4
|
+
data.tar.gz: 215cf149bd26e9d3d8c64b5c6f63eeccad86c5b6dc9ed5289bb6a1537e51ab56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9157512378e6edb0a362ea3db4fc35ecae3b6d2b54c025184a39ddf5e0e85528ac97aac1f3b829b461aa85e58a1655f35c7ad4d2aec0e8dda97c75d130625b34
|
7
|
+
data.tar.gz: f90758ee02b5dd28f488372d260b73413e4d01afa14756b8bfc787cd335c42ef43fa1b5907060cb33065727e804296bc6a25fee91d40b94e390e21c6b98d903e
|
data/.github/workflows/test.yml
CHANGED
@@ -16,7 +16,7 @@ jobs:
|
|
16
16
|
runs-on: ${{matrix.os}}
|
17
17
|
steps:
|
18
18
|
- uses: actions/checkout@v1
|
19
|
-
- uses:
|
19
|
+
- uses: ruby/setup-ruby@v1
|
20
20
|
with:
|
21
21
|
ruby-version: ${{matrix.ruby}}
|
22
22
|
- name: Install dependencies
|
@@ -24,7 +24,7 @@ jobs:
|
|
24
24
|
gem install bundler
|
25
25
|
bundle install
|
26
26
|
- name: Show Linux kernel version
|
27
|
-
run: uname -
|
27
|
+
run: uname -a
|
28
28
|
- name: Compile C-extension
|
29
29
|
run: POLYPHONY_USE_LIBEV=1 bundle exec rake compile
|
30
30
|
- name: Run tests
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -3,15 +3,19 @@ layout: page
|
|
3
3
|
title: ::Exception
|
4
4
|
parent: API Reference
|
5
5
|
permalink: /api-reference/exception/
|
6
|
+
source_url: https://github.com/digital-fabric/polyphony/blob/master/lib/polyphony/extensions/core.rb
|
7
|
+
ruby_docs_url: https://rubyapi.org/3.0/o/exception
|
6
8
|
---
|
7
9
|
# ::Exception
|
8
10
|
|
9
|
-
[Ruby core Exception documentation](https://
|
11
|
+
[Ruby core Exception documentation](https://rubyapi.org/3.0/o/exception)
|
10
12
|
|
11
13
|
The core `Exception` class is enhanced to provide a better backtrace that takes
|
12
14
|
into account the fiber hierarchy. In addition, a `source_fiber` attribute allows
|
13
15
|
tracking the fiber from which an uncaught exception was propagated.
|
14
16
|
|
17
|
+
|
18
|
+
|
15
19
|
## Class Methods
|
16
20
|
|
17
21
|
## Instance methods
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
M = 100
|
7
|
+
N = 10000
|
8
|
+
|
9
|
+
GC.disable
|
10
|
+
|
11
|
+
def monotonic_clock
|
12
|
+
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
13
|
+
end
|
14
|
+
|
15
|
+
def spin_proc(next_fiber)
|
16
|
+
spin_loop { next_fiber << receive }
|
17
|
+
end
|
18
|
+
|
19
|
+
last = Fiber.current
|
20
|
+
N.times { last = spin_proc(last) }
|
21
|
+
|
22
|
+
snooze
|
23
|
+
t0 = monotonic_clock
|
24
|
+
M.times do
|
25
|
+
last << 'hello'
|
26
|
+
receive
|
27
|
+
end
|
28
|
+
elapsed = monotonic_clock - t0
|
29
|
+
puts "M=#{M} N=#{N} elapsed: #{elapsed}"
|
@@ -202,7 +202,6 @@ inline rb_encoding* io_read_encoding(rb_io_t *fptr) {
|
|
202
202
|
}
|
203
203
|
|
204
204
|
inline VALUE io_enc_str(VALUE str, rb_io_t *fptr) {
|
205
|
-
OBJ_TAINT(str);
|
206
205
|
rb_enc_associate(str, io_read_encoding(fptr));
|
207
206
|
return str;
|
208
207
|
}
|
@@ -246,6 +245,13 @@ inline double current_time() {
|
|
246
245
|
return t / 1e9;
|
247
246
|
}
|
248
247
|
|
248
|
+
inline uint64_t current_time_ns() {
|
249
|
+
struct timespec ts;
|
250
|
+
clock_gettime(CLOCK_MONOTONIC, &ts);
|
251
|
+
uint64_t ns = ts.tv_sec;
|
252
|
+
return ns * 1e9 + ts.tv_nsec;
|
253
|
+
}
|
254
|
+
|
249
255
|
inline VALUE backend_timeout_exception(VALUE exception) {
|
250
256
|
if (rb_obj_is_kind_of(exception, rb_cArray) == Qtrue)
|
251
257
|
return rb_funcall(rb_ary_entry(exception, 0), ID_new, 1, rb_ary_entry(exception, 1));
|
@@ -82,7 +82,6 @@ VALUE backend_snooze();
|
|
82
82
|
shrinkable = io_setstrbuf(&str, len); \
|
83
83
|
buf = RSTRING_PTR(str); \
|
84
84
|
total = 0; \
|
85
|
-
OBJ_TAINT(str); \
|
86
85
|
}
|
87
86
|
|
88
87
|
#define READ_LOOP_YIELD_STR() { \
|
@@ -101,6 +100,7 @@ VALUE backend_snooze();
|
|
101
100
|
|
102
101
|
void rectify_io_file_pos(rb_io_t *fptr);
|
103
102
|
double current_time();
|
103
|
+
uint64_t current_time_ns();
|
104
104
|
VALUE backend_timeout_exception(VALUE exception);
|
105
105
|
VALUE Backend_timeout_ensure_safe(VALUE arg);
|
106
106
|
VALUE Backend_timeout_ensure_safe(VALUE arg);
|
@@ -127,7 +127,7 @@ void *io_uring_backend_poll_without_gvl(void *ptr) {
|
|
127
127
|
|
128
128
|
// copied from queue.c
|
129
129
|
static inline bool cq_ring_needs_flush(struct io_uring *ring) {
|
130
|
-
|
130
|
+
return IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW;
|
131
131
|
}
|
132
132
|
|
133
133
|
static inline void io_uring_backend_handle_completion(struct io_uring_cqe *cqe, Backend_t *backend) {
|
@@ -145,9 +145,9 @@ static inline void io_uring_backend_handle_completion(struct io_uring_cqe *cqe,
|
|
145
145
|
// this peeks at cqes and handles each available cqe
|
146
146
|
void io_uring_backend_handle_ready_cqes(Backend_t *backend) {
|
147
147
|
struct io_uring *ring = &backend->ring;
|
148
|
-
|
148
|
+
bool overflow_checked = false;
|
149
149
|
struct io_uring_cqe *cqe;
|
150
|
-
|
150
|
+
unsigned head;
|
151
151
|
unsigned cqe_count;
|
152
152
|
|
153
153
|
again:
|
@@ -158,16 +158,16 @@ again:
|
|
158
158
|
}
|
159
159
|
io_uring_cq_advance(ring, cqe_count);
|
160
160
|
|
161
|
-
|
161
|
+
if (overflow_checked) goto done;
|
162
162
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
163
|
+
if (cq_ring_needs_flush(ring)) {
|
164
|
+
__sys_io_uring_enter(ring->ring_fd, 0, 0, IORING_ENTER_GETEVENTS, NULL);
|
165
|
+
overflow_checked = true;
|
166
|
+
goto again;
|
167
|
+
}
|
168
168
|
|
169
169
|
done:
|
170
|
-
|
170
|
+
return;
|
171
171
|
}
|
172
172
|
|
173
173
|
void io_uring_backend_poll(Backend_t *backend) {
|
@@ -333,7 +333,6 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
333
333
|
rb_io_check_byte_readable(fptr);
|
334
334
|
io_unset_nonblock(fptr, io);
|
335
335
|
rectify_io_file_pos(fptr);
|
336
|
-
OBJ_TAINT(str);
|
337
336
|
|
338
337
|
while (1) {
|
339
338
|
VALUE resume_value = Qnil;
|
@@ -621,7 +620,6 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
621
620
|
rb_io_check_byte_readable(fptr);
|
622
621
|
io_unset_nonblock(fptr, io);
|
623
622
|
rectify_io_file_pos(fptr);
|
624
|
-
OBJ_TAINT(str);
|
625
623
|
|
626
624
|
while (1) {
|
627
625
|
VALUE resume_value = Qnil;
|
@@ -831,7 +829,7 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE soc
|
|
831
829
|
rb_io_synchronized(fp);
|
832
830
|
|
833
831
|
// if (rsock_do_not_reverse_lookup) {
|
834
|
-
|
832
|
+
// fp->mode |= FMODE_NOREVLOOKUP;
|
835
833
|
// }
|
836
834
|
if (loop) {
|
837
835
|
rb_yield(socket);
|
@@ -962,7 +960,7 @@ inline struct __kernel_timespec double_to_timespec(double duration) {
|
|
962
960
|
double duration_fraction = modf(duration, &duration_integral);
|
963
961
|
struct __kernel_timespec ts;
|
964
962
|
ts.tv_sec = duration_integral;
|
965
|
-
|
963
|
+
ts.tv_nsec = floor(duration_fraction * 1000000000);
|
966
964
|
return ts;
|
967
965
|
}
|
968
966
|
|
@@ -994,29 +992,34 @@ VALUE Backend_sleep(VALUE self, VALUE duration) {
|
|
994
992
|
|
995
993
|
VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
996
994
|
Backend_t *backend;
|
997
|
-
|
995
|
+
uint64_t interval_ns = NUM2DBL(interval) * 1e9;
|
996
|
+
uint64_t next_time_ns = 0;
|
997
|
+
VALUE resume_value = Qnil;
|
998
|
+
|
998
999
|
GetBackend(self, backend);
|
999
|
-
double next_time = 0.;
|
1000
1000
|
|
1001
1001
|
while (1) {
|
1002
|
-
double
|
1003
|
-
if (
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1002
|
+
double now_ns = current_time_ns();
|
1003
|
+
if (next_time_ns == 0) next_time_ns = now_ns + interval_ns;
|
1004
|
+
if (next_time_ns > now_ns) {
|
1005
|
+
double sleep_duration = ((double)(next_time_ns - now_ns))/1e9;
|
1006
|
+
int completed = io_uring_backend_submit_timeout_and_await(backend, sleep_duration, &resume_value);
|
1007
|
+
RAISE_IF_EXCEPTION(resume_value);
|
1008
|
+
if (!completed) return resume_value;
|
1009
|
+
}
|
1010
|
+
else {
|
1011
|
+
resume_value = backend_snooze();
|
1012
|
+
RAISE_IF_EXCEPTION(resume_value);
|
1013
|
+
}
|
1012
1014
|
|
1013
1015
|
rb_yield(Qnil);
|
1014
1016
|
|
1015
1017
|
while (1) {
|
1016
|
-
|
1017
|
-
if (
|
1018
|
+
next_time_ns += interval_ns;
|
1019
|
+
if (next_time_ns > now_ns) break;
|
1018
1020
|
}
|
1019
1021
|
}
|
1022
|
+
RB_GC_GUARD(resume_value);
|
1020
1023
|
}
|
1021
1024
|
|
1022
1025
|
struct Backend_timeout_ctx {
|
@@ -287,7 +287,6 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
287
287
|
io_verify_blocking_mode(fptr, io, Qfalse);
|
288
288
|
rectify_io_file_pos(fptr);
|
289
289
|
watcher.fiber = Qnil;
|
290
|
-
OBJ_TAINT(str);
|
291
290
|
|
292
291
|
while (1) {
|
293
292
|
backend->base.op_count++;
|
@@ -1147,33 +1146,40 @@ VALUE Backend_sleep(VALUE self, VALUE duration) {
|
|
1147
1146
|
noreturn VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
1148
1147
|
Backend_t *backend;
|
1149
1148
|
struct libev_timer watcher;
|
1150
|
-
double interval_d = NUM2DBL(interval);
|
1151
|
-
|
1152
|
-
GetBackend(self, backend);
|
1153
1149
|
watcher.fiber = rb_fiber_current();
|
1150
|
+
uint64_t interval_ns = NUM2DBL(interval) * 1e9;
|
1151
|
+
uint64_t next_time_ns = 0;
|
1152
|
+
VALUE resume_value = Qnil;
|
1154
1153
|
|
1155
|
-
|
1154
|
+
GetBackend(self, backend);
|
1156
1155
|
|
1157
1156
|
while (1) {
|
1158
|
-
|
1159
|
-
if (
|
1160
|
-
double sleep_duration =
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1157
|
+
uint64_t now_ns = current_time_ns();
|
1158
|
+
if (next_time_ns == 0) next_time_ns = now_ns + interval_ns;
|
1159
|
+
double sleep_duration = ((double)(next_time_ns - now_ns))/1e9;
|
1160
|
+
|
1161
|
+
if (next_time_ns > now_ns) {
|
1162
|
+
double sleep_duration = ((double)(next_time_ns - now_ns))/1e9;
|
1163
|
+
ev_timer_init(&watcher.timer, Backend_timer_callback, sleep_duration, 0.);
|
1164
|
+
ev_timer_start(backend->ev_loop, &watcher.timer);
|
1165
|
+
backend->base.op_count++;
|
1166
|
+
resume_value = backend_await((struct Backend_base *)backend);
|
1167
|
+
ev_timer_stop(backend->ev_loop, &watcher.timer);
|
1168
|
+
RAISE_IF_EXCEPTION(resume_value);
|
1169
|
+
}
|
1170
|
+
else {
|
1171
|
+
resume_value = backend_snooze();
|
1172
|
+
RAISE_IF_EXCEPTION(resume_value);
|
1173
|
+
}
|
1171
1174
|
|
1172
1175
|
rb_yield(Qnil);
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
+
|
1177
|
+
while (1) {
|
1178
|
+
next_time_ns += interval_ns;
|
1179
|
+
if (next_time_ns > now_ns) break;
|
1180
|
+
}
|
1176
1181
|
}
|
1182
|
+
RB_GC_GUARD(resume_value);
|
1177
1183
|
}
|
1178
1184
|
|
1179
1185
|
struct libev_timeout {
|
data/ext/polyphony/extconf.rb
CHANGED
@@ -51,6 +51,7 @@ $defs << '-DPOLYPHONY_PLAYGROUND' if ENV['POLYPHONY_PLAYGROUND']
|
|
51
51
|
|
52
52
|
CONFIG['optflags'] << ' -fno-strict-aliasing' unless RUBY_PLATFORM =~ /mswin/
|
53
53
|
|
54
|
+
have_func('rb_fiber_transfer', 'ruby.h')
|
54
55
|
|
55
56
|
dir_config 'polyphony_ext'
|
56
57
|
create_makefile 'polyphony_ext'
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -26,7 +26,11 @@
|
|
26
26
|
#define RAISE_IF_NOT_NIL(ret) if (ret != Qnil) { RAISE_EXCEPTION(ret); }
|
27
27
|
|
28
28
|
// Fiber#transfer
|
29
|
-
#
|
29
|
+
#if HAVE_RB_FIBER_TRANSFER
|
30
|
+
#define FIBER_TRANSFER(fiber, value) rb_fiber_transfer(fiber, 1, &value)
|
31
|
+
#else
|
32
|
+
#define FIBER_TRANSFER(fiber, value) rb_funcall(fiber, ID_transfer, 1, value)
|
33
|
+
#endif
|
30
34
|
|
31
35
|
#define BACKEND() (rb_ivar_get(rb_thread_current(), ID_ivar_backend))
|
32
36
|
|
data/ext/polyphony/thread.c
CHANGED
@@ -40,7 +40,7 @@ VALUE Thread_fiber_schedule_and_wakeup(VALUE self, VALUE fiber, VALUE resume_obj
|
|
40
40
|
}
|
41
41
|
|
42
42
|
if (Backend_wakeup(rb_ivar_get(self, ID_ivar_backend)) == Qnil) {
|
43
|
-
// we're not inside
|
43
|
+
// we're not inside Backend_poll, so we just do a switchpoint
|
44
44
|
Thread_switch_fiber(self);
|
45
45
|
}
|
46
46
|
|
File without changes
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Exeption overrides
|
4
|
+
class ::Exception
|
5
|
+
class << self
|
6
|
+
attr_accessor :__disable_sanitized_backtrace__
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :source_fiber, :raising_fiber
|
10
|
+
|
11
|
+
alias_method :orig_initialize, :initialize
|
12
|
+
def initialize(*args)
|
13
|
+
@raising_fiber = Fiber.current
|
14
|
+
orig_initialize(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :orig_backtrace, :backtrace
|
18
|
+
def backtrace
|
19
|
+
unless @backtrace_called
|
20
|
+
@backtrace_called = true
|
21
|
+
return orig_backtrace
|
22
|
+
end
|
23
|
+
|
24
|
+
sanitized_backtrace
|
25
|
+
end
|
26
|
+
|
27
|
+
def sanitized_backtrace
|
28
|
+
return sanitize(orig_backtrace) unless @raising_fiber
|
29
|
+
|
30
|
+
backtrace = orig_backtrace || []
|
31
|
+
sanitize(backtrace + @raising_fiber.caller)
|
32
|
+
end
|
33
|
+
|
34
|
+
POLYPHONY_DIR = File.expand_path(File.join(__dir__, '..'))
|
35
|
+
|
36
|
+
def sanitize(backtrace)
|
37
|
+
return backtrace if ::Exception.__disable_sanitized_backtrace__
|
38
|
+
|
39
|
+
backtrace.reject { |l| l[POLYPHONY_DIR] }
|
40
|
+
end
|
41
|
+
|
42
|
+
def invoke
|
43
|
+
Kernel.raise(self)
|
44
|
+
end
|
45
|
+
end
|
@@ -1,73 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'fiber'
|
4
|
-
require 'timeout'
|
5
3
|
require 'open3'
|
6
4
|
|
7
|
-
require_relative '../core/exceptions'
|
8
|
-
|
9
|
-
# Exeption overrides
|
10
|
-
class ::Exception
|
11
|
-
class << self
|
12
|
-
attr_accessor :__disable_sanitized_backtrace__
|
13
|
-
end
|
14
|
-
|
15
|
-
attr_accessor :source_fiber, :raising_fiber
|
16
|
-
|
17
|
-
alias_method :orig_initialize, :initialize
|
18
|
-
def initialize(*args)
|
19
|
-
@raising_fiber = Fiber.current
|
20
|
-
orig_initialize(*args)
|
21
|
-
end
|
22
|
-
|
23
|
-
alias_method :orig_backtrace, :backtrace
|
24
|
-
def backtrace
|
25
|
-
unless @backtrace_called
|
26
|
-
@backtrace_called = true
|
27
|
-
return orig_backtrace
|
28
|
-
end
|
29
|
-
|
30
|
-
sanitized_backtrace
|
31
|
-
end
|
32
|
-
|
33
|
-
def sanitized_backtrace
|
34
|
-
return sanitize(orig_backtrace) unless @raising_fiber
|
35
|
-
|
36
|
-
backtrace = orig_backtrace || []
|
37
|
-
sanitize(backtrace + @raising_fiber.caller)
|
38
|
-
end
|
39
|
-
|
40
|
-
POLYPHONY_DIR = File.expand_path(File.join(__dir__, '..'))
|
41
|
-
|
42
|
-
def sanitize(backtrace)
|
43
|
-
return backtrace if ::Exception.__disable_sanitized_backtrace__
|
44
|
-
|
45
|
-
backtrace.reject { |l| l[POLYPHONY_DIR] }
|
46
|
-
end
|
47
|
-
|
48
|
-
def invoke
|
49
|
-
Kernel.raise(self)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Overrides for Process
|
54
|
-
module ::Process
|
55
|
-
class << self
|
56
|
-
alias_method :orig_detach, :detach
|
57
|
-
def detach(pid)
|
58
|
-
fiber = spin { Polyphony.backend_waitpid(pid) }
|
59
|
-
fiber.define_singleton_method(:pid) { pid }
|
60
|
-
fiber
|
61
|
-
end
|
62
|
-
|
63
|
-
alias_method :orig_daemon, :daemon
|
64
|
-
def daemon(*args)
|
65
|
-
orig_daemon(*args)
|
66
|
-
Polyphony.original_pid = Process.pid
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
5
|
# Kernel extensions (methods available to all objects / call sites)
|
72
6
|
module ::Kernel
|
73
7
|
alias_method :orig_sleep, :sleep
|
@@ -159,10 +93,3 @@ module ::Kernel
|
|
159
93
|
end
|
160
94
|
end
|
161
95
|
end
|
162
|
-
|
163
|
-
# Override Timeout to use cancel scope
|
164
|
-
module ::Timeout
|
165
|
-
def self.timeout(sec, klass = Timeout::Error, message = 'execution expired', &block)
|
166
|
-
cancel_after(sec, with_exception: [klass, message], &block)
|
167
|
-
end
|
168
|
-
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Overrides for Process
|
4
|
+
module ::Process
|
5
|
+
class << self
|
6
|
+
alias_method :orig_detach, :detach
|
7
|
+
def detach(pid)
|
8
|
+
fiber = spin { Polyphony.backend_waitpid(pid) }
|
9
|
+
fiber.define_singleton_method(:pid) { pid }
|
10
|
+
fiber
|
11
|
+
end
|
12
|
+
|
13
|
+
alias_method :orig_daemon, :daemon
|
14
|
+
def daemon(*args)
|
15
|
+
orig_daemon(*args)
|
16
|
+
Polyphony.original_pid = Process.pid
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
# Override Timeout to use cancel scope
|
6
|
+
module ::Timeout
|
7
|
+
def self.timeout(sec, klass = Timeout::Error, message = 'execution expired', &block)
|
8
|
+
cancel_after(sec, with_exception: [klass, message], &block)
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './extensions/exception'
|
4
|
+
require_relative './extensions/fiber'
|
5
|
+
require_relative './extensions/io'
|
6
|
+
require_relative './extensions/kernel'
|
7
|
+
require_relative './extensions/process'
|
8
|
+
require_relative './extensions/thread'
|
9
|
+
require_relative './extensions/timeout'
|
data/lib/polyphony/version.rb
CHANGED
data/lib/polyphony.rb
CHANGED
@@ -2,15 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'fiber'
|
4
4
|
require_relative './polyphony_ext'
|
5
|
-
|
6
|
-
require_relative './polyphony/extensions/core'
|
7
|
-
require_relative './polyphony/extensions/thread'
|
8
|
-
require_relative './polyphony/extensions/fiber'
|
9
|
-
require_relative './polyphony/extensions/io'
|
5
|
+
require_relative './polyphony/extensions'
|
10
6
|
|
11
7
|
Thread.current.setup_fiber_scheduling
|
12
8
|
Thread.current.backend = Polyphony::Backend.new
|
13
9
|
|
10
|
+
require_relative './polyphony/core/exceptions'
|
14
11
|
require_relative './polyphony/core/global_api'
|
15
12
|
require_relative './polyphony/core/resource_pool'
|
16
13
|
require_relative './polyphony/core/sync'
|
data/test/test_global_api.rb
CHANGED
@@ -412,7 +412,7 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
412
412
|
f = after(0.001) { buffer << 2 }
|
413
413
|
snooze
|
414
414
|
assert_equal [], buffer
|
415
|
-
sleep 0.
|
415
|
+
sleep 0.0015
|
416
416
|
assert_equal [2], buffer
|
417
417
|
end
|
418
418
|
|
@@ -429,6 +429,19 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
429
429
|
assert_in_range 4..6, buffer.size
|
430
430
|
end
|
431
431
|
|
432
|
+
def test_every_with_slow_op
|
433
|
+
skip unless IS_LINUX
|
434
|
+
|
435
|
+
buffer = []
|
436
|
+
t0 = Time.now
|
437
|
+
f = spin do
|
438
|
+
every(0.01) { sleep 0.05; buffer << 1 }
|
439
|
+
end
|
440
|
+
sleep 0.15
|
441
|
+
f.stop
|
442
|
+
assert_in_range 2..3, buffer.size
|
443
|
+
end
|
444
|
+
|
432
445
|
def test_sleep
|
433
446
|
t0 = Time.now
|
434
447
|
sleep 0.1
|
data/test/test_signal.rb
CHANGED
@@ -93,4 +93,23 @@ class SignalTrapTest < Minitest::Test
|
|
93
93
|
buffer = i.read
|
94
94
|
assert_equal "INT\n", buffer
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
|
+
def test_busy_signal_handling
|
98
|
+
i, o = IO.pipe
|
99
|
+
pid = Polyphony.fork do
|
100
|
+
main = Fiber.current
|
101
|
+
trap('INT') { o.puts 'INT'; o.close; main.stop }
|
102
|
+
i.close
|
103
|
+
f1 = spin_loop { snooze }
|
104
|
+
f2 = spin_loop { snooze }
|
105
|
+
f1.await
|
106
|
+
end
|
107
|
+
|
108
|
+
o.close
|
109
|
+
sleep 0.1
|
110
|
+
Process.kill('INT', pid)
|
111
|
+
Thread.current.backend.waitpid(pid)
|
112
|
+
buffer = i.read
|
113
|
+
assert_equal "INT\n", buffer
|
114
|
+
end
|
115
|
+
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.73'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -136,7 +136,7 @@ dependencies:
|
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: 1.1.4
|
139
|
-
description:
|
139
|
+
description:
|
140
140
|
email: sharon@noteflakes.com
|
141
141
|
executables: []
|
142
142
|
extensions:
|
@@ -233,6 +233,7 @@ files:
|
|
233
233
|
- examples/core/queue.rb
|
234
234
|
- examples/core/recurrent-timer.rb
|
235
235
|
- examples/core/resource_delegate.rb
|
236
|
+
- examples/core/ring.rb
|
236
237
|
- examples/core/spin.rb
|
237
238
|
- examples/core/spin_error_backtrace.rb
|
238
239
|
- examples/core/supervise-process.rb
|
@@ -354,6 +355,7 @@ files:
|
|
354
355
|
- lib/polyphony/adapters/redis.rb
|
355
356
|
- lib/polyphony/adapters/sequel.rb
|
356
357
|
- lib/polyphony/core/channel.rb
|
358
|
+
- lib/polyphony/core/debug.rb
|
357
359
|
- lib/polyphony/core/exceptions.rb
|
358
360
|
- lib/polyphony/core/global_api.rb
|
359
361
|
- lib/polyphony/core/resource_pool.rb
|
@@ -362,13 +364,16 @@ files:
|
|
362
364
|
- lib/polyphony/core/throttler.rb
|
363
365
|
- lib/polyphony/core/timer.rb
|
364
366
|
- lib/polyphony/debugger.rb
|
365
|
-
- lib/polyphony/extensions
|
366
|
-
- lib/polyphony/extensions/
|
367
|
+
- lib/polyphony/extensions.rb
|
368
|
+
- lib/polyphony/extensions/exception.rb
|
367
369
|
- lib/polyphony/extensions/fiber.rb
|
368
370
|
- lib/polyphony/extensions/io.rb
|
371
|
+
- lib/polyphony/extensions/kernel.rb
|
369
372
|
- lib/polyphony/extensions/openssl.rb
|
373
|
+
- lib/polyphony/extensions/process.rb
|
370
374
|
- lib/polyphony/extensions/socket.rb
|
371
375
|
- lib/polyphony/extensions/thread.rb
|
376
|
+
- lib/polyphony/extensions/timeout.rb
|
372
377
|
- lib/polyphony/net.rb
|
373
378
|
- lib/polyphony/version.rb
|
374
379
|
- polyphony.gemspec
|
@@ -406,7 +411,7 @@ metadata:
|
|
406
411
|
documentation_uri: https://digital-fabric.github.io/polyphony/
|
407
412
|
homepage_uri: https://digital-fabric.github.io/polyphony/
|
408
413
|
changelog_uri: https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md
|
409
|
-
post_install_message:
|
414
|
+
post_install_message:
|
410
415
|
rdoc_options:
|
411
416
|
- "--title"
|
412
417
|
- polyphony
|
@@ -425,8 +430,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
425
430
|
- !ruby/object:Gem::Version
|
426
431
|
version: '0'
|
427
432
|
requirements: []
|
428
|
-
rubygems_version: 3.
|
429
|
-
signing_key:
|
433
|
+
rubygems_version: 3.3.0.dev
|
434
|
+
signing_key:
|
430
435
|
specification_version: 4
|
431
436
|
summary: Fine grained concurrency for Ruby
|
432
437
|
test_files: []
|