polyphony 0.95 → 0.96
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 +1 -1
- data/.github/workflows/test_io_uring.yml +4 -4
- data/CHANGELOG.md +5 -0
- data/examples/adapters/redis_blpop.rb +4 -3
- data/examples/adapters/redis_channels.rb +16 -7
- data/examples/core/await.rb +1 -1
- data/examples/io/readline.rb +19 -0
- data/ext/polyphony/backend_common.c +22 -0
- data/ext/polyphony/backend_libev.c +2 -2
- data/lib/polyphony/adapters/readline.rb +6 -4
- data/lib/polyphony/adapters/redis.rb +28 -87
- data/lib/polyphony/core/channel.rb +15 -0
- data/lib/polyphony/core/sync.rb +4 -0
- data/lib/polyphony/debugger.rb +2 -2
- data/lib/polyphony/extensions.rb +0 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +4 -0
- data/polyphony.gemspec +8 -8
- data/test/helper.rb +0 -5
- data/test/test_ext.rb +63 -0
- data/test/test_thread_pool.rb +2 -2
- metadata +20 -33
- data/lib/polyphony/extensions/enumerator.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2db26acbbe9457dc3b3fcdd1e34d35e5347a2e67a5c126b9ddea672957ca3318
|
4
|
+
data.tar.gz: ac02e27bd659dafbfe0b68db9b22fc3ca8acb744ff82049dbb2bbea999f7e87e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e99fb459ea41504df54826634d219f8ef1feea3324fe6c56ab18fc46867728d57f36f4c15a35787e0ba42fe588b10d3e849badfcbee0a720c77bb1d8619e8fc3
|
7
|
+
data.tar.gz: d52ee81b1f1f5a5294cecf09837ccce8cc68f0233d73a0d868326f0a144897542f5ad3e05cc398eb4bf963742fe1fac01a096abf0d77e3201d8c50ca8880e65a
|
data/.github/workflows/test.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
name: Tests
|
1
|
+
name: Tests (io_uring)
|
2
2
|
|
3
3
|
on: [push, pull_request]
|
4
4
|
|
@@ -8,7 +8,7 @@ jobs:
|
|
8
8
|
fail-fast: false
|
9
9
|
matrix:
|
10
10
|
os: [ubuntu-latest]
|
11
|
-
ruby: ['
|
11
|
+
ruby: ['3.0', '3.1', '3.2']
|
12
12
|
|
13
13
|
name: >-
|
14
14
|
${{matrix.os}}, ${{matrix.ruby}}
|
@@ -16,7 +16,7 @@ jobs:
|
|
16
16
|
runs-on: ${{matrix.os}}
|
17
17
|
steps:
|
18
18
|
- name: Checkout repository and submodules
|
19
|
-
uses: actions/checkout@
|
19
|
+
uses: actions/checkout@v3
|
20
20
|
with:
|
21
21
|
submodules: recursive
|
22
22
|
- name: Setup Ruby
|
@@ -33,4 +33,4 @@ jobs:
|
|
33
33
|
- name: Compile C-extension
|
34
34
|
run: bundle exec rake compile
|
35
35
|
- name: Run tests
|
36
|
-
run: bundle exec ruby test/run.rb
|
36
|
+
run: bundle exec ruby test/run.rb
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
3
|
+
require 'redis'
|
4
|
+
require_relative '../../lib/polyphony/adapters/redis'
|
5
|
+
require_relative '../../lib/polyphony'
|
6
|
+
|
6
7
|
|
7
8
|
redis = Redis.new(host: ENV['REDISHOST'] || 'localhost')
|
8
9
|
|
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
3
|
+
require 'redis'
|
4
|
+
require_relative '../../lib/polyphony/adapters/redis'
|
5
|
+
require_relative '../../lib/polyphony'
|
6
|
+
require_relative '../../lib/polyphony/core/channel'
|
5
7
|
|
6
8
|
class RedisChannel < Polyphony::Channel
|
7
9
|
def self.publish_connection
|
@@ -17,20 +19,24 @@ class RedisChannel < Polyphony::Channel
|
|
17
19
|
def self.start_monitor
|
18
20
|
@channels = {}
|
19
21
|
@monitor = spin do
|
22
|
+
p start_monitor: 1
|
20
23
|
subscribe_connection.subscribe(CHANNEL_MASTER_TOPIC) do |on|
|
24
|
+
p start_monitor: 2
|
21
25
|
on.message do |topic, message|
|
26
|
+
p start_monitor: 3, topic: topic, message: message
|
22
27
|
message = Marshal.load(message)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
if CHANNEL_MASTER_TOPIC
|
29
|
+
handle_master_message(message)
|
30
|
+
else
|
31
|
+
handle_channel_message(topic, message)
|
32
|
+
end
|
28
33
|
end
|
29
34
|
end
|
30
35
|
end
|
31
36
|
end
|
32
37
|
|
33
38
|
def self.stop_monitor
|
39
|
+
p stop_monitor: 1
|
34
40
|
@monitor&.interrupt
|
35
41
|
end
|
36
42
|
|
@@ -111,10 +117,13 @@ end
|
|
111
117
|
|
112
118
|
spin do
|
113
119
|
move_on_after(3) do
|
120
|
+
p :move_on_after
|
114
121
|
throttled_loop(1) do
|
122
|
+
# p :throttled_loop
|
115
123
|
channel << Time.now
|
116
124
|
end
|
117
125
|
end
|
126
|
+
p :done
|
118
127
|
channel.close
|
119
128
|
RedisChannel.stop_monitor
|
120
129
|
end
|
data/examples/core/await.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
require 'polyphony/adapters/readline'
|
6
|
+
|
7
|
+
$counter = 0
|
8
|
+
timer = spin do
|
9
|
+
throttled_loop(5) do
|
10
|
+
$counter += 1
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
at_exit { timer.stop }
|
15
|
+
|
16
|
+
puts 'try typing $counter to see the counter incremented in the background'
|
17
|
+
loop do
|
18
|
+
puts eval Readline::readline('> ', true)
|
19
|
+
end
|
@@ -60,6 +60,23 @@ inline void conditional_nonblocking_poll(VALUE backend, struct Backend_base *bas
|
|
60
60
|
Backend_poll(backend, Qnil);
|
61
61
|
}
|
62
62
|
|
63
|
+
// Verifies that the given fiber has the @thread ivar set. If not, sets it to
|
64
|
+
// the current thread. This is essential for the correct functioning of fibers
|
65
|
+
// not created by Polyphony, such as those used by the Enumerator class, and
|
66
|
+
// probably others as well. With a nil thread ivar, a fiber can not be
|
67
|
+
// scheduled. This macro is called in backend_base_switch_fiber() and in
|
68
|
+
// backend_snooze().
|
69
|
+
//
|
70
|
+
// In order to refrain from calling rb_thread_current() multiple times, we
|
71
|
+
// allow it to be passed to this macro, and if not we call it on the spot.
|
72
|
+
#define CHECK_FIBER_THREAD_REF(fiber, current_thread) { \
|
73
|
+
VALUE thread = rb_ivar_get(fiber, ID_ivar_thread); \
|
74
|
+
if (thread == Qnil) { \
|
75
|
+
thread = (current_thread != Qnil) ? current_thread : rb_thread_current(); \
|
76
|
+
rb_ivar_set(fiber, ID_ivar_thread, thread); \
|
77
|
+
} \
|
78
|
+
}
|
79
|
+
|
63
80
|
VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
|
64
81
|
VALUE current_fiber = rb_fiber_current();
|
65
82
|
runqueue_entry next;
|
@@ -71,6 +88,8 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
|
|
71
88
|
if (SHOULD_TRACE(base))
|
72
89
|
TRACE(base, 3, SYM_block, current_fiber, CALLER());
|
73
90
|
|
91
|
+
CHECK_FIBER_THREAD_REF(current_fiber, Qnil);
|
92
|
+
|
74
93
|
while (1) {
|
75
94
|
next = runqueue_shift(&base->runqueue);
|
76
95
|
if (next.fiber != Qnil) {
|
@@ -261,6 +280,9 @@ inline VALUE backend_snooze(struct Backend_base *backend) {
|
|
261
280
|
VALUE ret;
|
262
281
|
VALUE fiber = rb_fiber_current();
|
263
282
|
VALUE thread = rb_thread_current();
|
283
|
+
|
284
|
+
CHECK_FIBER_THREAD_REF(fiber, thread);
|
285
|
+
|
264
286
|
Fiber_make_runnable(fiber, Qnil);
|
265
287
|
ret = Thread_switch_fiber(thread);
|
266
288
|
|
@@ -107,7 +107,7 @@ void break_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, in
|
|
107
107
|
// of a *blocking* event loop (waking it up) in a thread-safe, signal-safe manner
|
108
108
|
}
|
109
109
|
|
110
|
-
inline struct ev_loop *libev_new_loop() {
|
110
|
+
inline struct ev_loop *libev_new_loop(void) {
|
111
111
|
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
112
112
|
return ev_loop_new(EVFLAG_NOSIGMASK);
|
113
113
|
#else
|
@@ -1474,7 +1474,7 @@ void Backend_unpark_fiber(VALUE self, VALUE fiber) {
|
|
1474
1474
|
backend_base_unpark_fiber(&backend->base, fiber);
|
1475
1475
|
}
|
1476
1476
|
|
1477
|
-
void Init_Backend() {
|
1477
|
+
void Init_Backend(void) {
|
1478
1478
|
ev_set_allocator(xrealloc);
|
1479
1479
|
|
1480
1480
|
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
|
@@ -7,11 +7,13 @@ require 'readline'
|
|
7
7
|
# thread pool. That way, the reactor loop can keep running while waiting for
|
8
8
|
# readline to return
|
9
9
|
module ::Readline
|
10
|
-
|
10
|
+
class << self
|
11
|
+
alias_method :orig_readline, :readline
|
11
12
|
|
12
|
-
|
13
|
+
Worker = Polyphony::ThreadPool.new(1)
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
def readline(*args)
|
16
|
+
Worker.process { orig_readline(*args) }
|
17
|
+
end
|
16
18
|
end
|
17
19
|
end
|
@@ -2,94 +2,35 @@
|
|
2
2
|
|
3
3
|
require_relative '../../polyphony'
|
4
4
|
|
5
|
-
require 'redis'
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
@reader = ::Hiredis::Reader.new
|
34
|
-
end
|
35
|
-
|
36
|
-
# Returns true if connected to server.
|
37
|
-
#
|
38
|
-
# @return [bool] is connected to server
|
39
|
-
def connected?
|
40
|
-
@connection && !@connection.closed?
|
41
|
-
end
|
42
|
-
|
43
|
-
# Sets a timeout for the connection.
|
44
|
-
#
|
45
|
-
# @return [void]
|
46
|
-
def timeout=(timeout)
|
47
|
-
# ignore timeout for now
|
48
|
-
end
|
49
|
-
|
50
|
-
# Disconnects from the server.
|
51
|
-
#
|
52
|
-
# @return [void]
|
53
|
-
def disconnect
|
54
|
-
@connection.close
|
55
|
-
@connection = nil
|
56
|
-
end
|
57
|
-
|
58
|
-
# Sends a command to the server.
|
59
|
-
#
|
60
|
-
# @param command [Array] Redis command
|
61
|
-
# @return [void]
|
62
|
-
def write(command)
|
63
|
-
@connection.write(format_command(command))
|
64
|
-
end
|
65
|
-
|
66
|
-
# Formats a command for sending to server.
|
67
|
-
#
|
68
|
-
# @param args [Array] command
|
69
|
-
# @return [String] formatted command
|
70
|
-
def format_command(args)
|
71
|
-
args = args.flatten
|
72
|
-
(+"*#{args.size}\r\n").tap do |s|
|
73
|
-
args.each do |a|
|
74
|
-
a = a.to_s
|
75
|
-
s << "$#{a.bytesize}\r\n#{a}\r\n"
|
5
|
+
require 'redis-client'
|
6
|
+
|
7
|
+
class RedisClient
|
8
|
+
class RubyConnection
|
9
|
+
class BufferedIO
|
10
|
+
def fill_buffer(strict, size = @chunk_size)
|
11
|
+
remaining = size
|
12
|
+
empty_buffer = @offset >= @buffer.bytesize
|
13
|
+
|
14
|
+
loop do
|
15
|
+
max_read = [remaining, @chunk_size].max
|
16
|
+
bytes = if empty_buffer
|
17
|
+
@io.readpartial(max_read, @buffer)
|
18
|
+
else
|
19
|
+
@io.readpartial(max_read)
|
20
|
+
end
|
21
|
+
|
22
|
+
raise Errno::ECONNRESET if bytes.nil?
|
23
|
+
|
24
|
+
if empty_buffer
|
25
|
+
@offset = 0
|
26
|
+
empty_buffer = false
|
27
|
+
else
|
28
|
+
@buffer << bytes
|
29
|
+
end
|
30
|
+
remaining -= bytes.bytesize
|
31
|
+
return if !strict || remaining <= 0
|
32
|
+
end
|
76
33
|
end
|
77
34
|
end
|
78
35
|
end
|
79
|
-
|
80
|
-
# Reads from the connection, feeding incoming data to the parser.
|
81
|
-
#
|
82
|
-
# @return [void]
|
83
|
-
def read
|
84
|
-
reply = @reader.gets
|
85
|
-
return reply if reply
|
86
|
-
|
87
|
-
@connection.read_loop do |data|
|
88
|
-
@reader.feed(data)
|
89
|
-
reply = @reader.gets
|
90
|
-
return reply unless reply == false
|
91
|
-
end
|
92
|
-
end
|
93
36
|
end
|
94
|
-
|
95
|
-
Redis::Connection.drivers << Polyphony::RedisDriver
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../polyphony'
|
4
|
+
|
5
|
+
module Polyphony
|
6
|
+
# Implements a unidirectional communication channel along the lines of Go
|
7
|
+
# (buffered) channels.
|
8
|
+
class Channel < Polyphony::Queue
|
9
|
+
alias_method :receive, :shift
|
10
|
+
|
11
|
+
def close
|
12
|
+
flush_waiters(Polyphony::MoveOn.new)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/polyphony/core/sync.rb
CHANGED
@@ -101,6 +101,8 @@ module Polyphony
|
|
101
101
|
#
|
102
102
|
# @return [void]
|
103
103
|
def signal
|
104
|
+
return if @queue.empty?
|
105
|
+
|
104
106
|
fiber = @queue.shift
|
105
107
|
fiber.schedule
|
106
108
|
end
|
@@ -109,6 +111,8 @@ module Polyphony
|
|
109
111
|
#
|
110
112
|
# @return [void]
|
111
113
|
def broadcast
|
114
|
+
return if @queue.empty?
|
115
|
+
|
112
116
|
while (fiber = @queue.shift)
|
113
117
|
fiber.schedule
|
114
118
|
end
|
data/lib/polyphony/debugger.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'polyphony/
|
3
|
+
require 'polyphony/core/debug'
|
4
4
|
|
5
5
|
module Polyphony
|
6
6
|
TP_EVENTS = [
|
@@ -188,7 +188,7 @@ module Polyphony
|
|
188
188
|
def start_server_thread
|
189
189
|
@thread = Thread.new do
|
190
190
|
puts("Listening on #{@socket_path}")
|
191
|
-
FileUtils.rm(@socket_path) if File.
|
191
|
+
FileUtils.rm(@socket_path) if File.exist?(@socket_path)
|
192
192
|
socket = UNIXServer.new(@socket_path)
|
193
193
|
loop do
|
194
194
|
@client = socket.accept
|
data/lib/polyphony/extensions.rb
CHANGED
data/lib/polyphony/version.rb
CHANGED
data/lib/polyphony.rb
CHANGED
@@ -117,6 +117,10 @@ module Polyphony
|
|
117
117
|
$VERBOSE = nil
|
118
118
|
Object.const_set(:Queue, Polyphony::Queue)
|
119
119
|
Object.const_set(:Mutex, Polyphony::Mutex)
|
120
|
+
|
121
|
+
require 'monitor'
|
122
|
+
Object.const_set(:Monitor, Polyphony::Mutex)
|
123
|
+
|
120
124
|
Object.const_set(:ConditionVariable, Polyphony::ConditionVariable)
|
121
125
|
$VERBOSE = verbose
|
122
126
|
end
|
data/polyphony.gemspec
CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = 'https://digital-fabric.github.io/polyphony'
|
12
12
|
s.metadata = {
|
13
13
|
"source_code_uri" => "https://github.com/digital-fabric/polyphony",
|
14
|
+
# "documentation_uri" => "https://www.rubydoc.info/gems/polyphony",
|
14
15
|
"documentation_uri" => "https://digital-fabric.github.io/polyphony/",
|
15
16
|
"homepage_uri" => "https://digital-fabric.github.io/polyphony/",
|
16
17
|
"changelog_uri" => "https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md"
|
@@ -21,16 +22,15 @@ Gem::Specification.new do |s|
|
|
21
22
|
s.require_paths = ["lib"]
|
22
23
|
s.required_ruby_version = '>= 3.0'
|
23
24
|
|
24
|
-
s.add_development_dependency 'rake-compiler', '1.
|
25
|
-
s.add_development_dependency 'minitest', '5.
|
26
|
-
s.add_development_dependency '
|
27
|
-
s.add_development_dependency '
|
28
|
-
s.add_development_dependency '
|
29
|
-
s.add_development_dependency 'pry', '0.13.1'
|
25
|
+
s.add_development_dependency 'rake-compiler', '1.2.1'
|
26
|
+
s.add_development_dependency 'minitest', '5.17.0'
|
27
|
+
s.add_development_dependency 'simplecov', '0.22.0'
|
28
|
+
s.add_development_dependency 'rubocop', '1.45.1'
|
29
|
+
s.add_development_dependency 'pry', '0.14.2'
|
30
30
|
|
31
|
-
s.add_development_dependency 'msgpack', '1.
|
31
|
+
s.add_development_dependency 'msgpack', '1.6.0'
|
32
32
|
s.add_development_dependency 'httparty', '0.21.0'
|
33
|
-
s.add_development_dependency 'localhost', '
|
33
|
+
s.add_development_dependency 'localhost', '1.1.10'
|
34
34
|
|
35
35
|
# s.add_development_dependency 'jekyll', '~>3.8.6'
|
36
36
|
# s.add_development_dependency 'jekyll-remote-theme', '~>0.4.1'
|
data/test/helper.rb
CHANGED
@@ -11,16 +11,11 @@ require 'fileutils'
|
|
11
11
|
require_relative './eg'
|
12
12
|
|
13
13
|
require 'minitest/autorun'
|
14
|
-
require 'minitest/reporters'
|
15
14
|
|
16
15
|
::Exception.__disable_sanitized_backtrace__ = true
|
17
16
|
|
18
17
|
IS_LINUX = RUBY_PLATFORM =~ /linux/
|
19
18
|
|
20
|
-
# Minitest::Reporters.use! [
|
21
|
-
# Minitest::Reporters::SpecReporter.new
|
22
|
-
# ]
|
23
|
-
|
24
19
|
module ::Kernel
|
25
20
|
def trace(*args)
|
26
21
|
STDOUT.orig_write(format_trace(args))
|
data/test/test_ext.rb
CHANGED
@@ -39,6 +39,69 @@ class ExceptionTest < MiniTest::Test
|
|
39
39
|
Exception.__disable_sanitized_backtrace__ = prev_disable
|
40
40
|
end
|
41
41
|
|
42
|
+
LOCATION_ONLY = ->(s) { s =~ /^(.+)\:in / && Regexp.last_match[1] }
|
43
|
+
|
44
|
+
def test_backtrace_on_main_fiber
|
45
|
+
base = caller.map(&LOCATION_ONLY)
|
46
|
+
begin
|
47
|
+
lineno = __LINE__ + 1
|
48
|
+
raise 'foo'
|
49
|
+
rescue => e
|
50
|
+
end
|
51
|
+
|
52
|
+
assert !!e
|
53
|
+
|
54
|
+
bt = e.backtrace.map(&LOCATION_ONLY)
|
55
|
+
assert_equal ["#{__FILE__}:#{lineno}"] + base, bt
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_backtrace_on_child_fiber
|
59
|
+
Exception.__disable_sanitized_backtrace__ = false
|
60
|
+
|
61
|
+
lineno = __LINE__ + 1
|
62
|
+
fiber = spin do
|
63
|
+
raise receive
|
64
|
+
end
|
65
|
+
|
66
|
+
base = caller.map(&LOCATION_ONLY)
|
67
|
+
|
68
|
+
begin
|
69
|
+
fiber << 'foo'
|
70
|
+
fiber.await
|
71
|
+
rescue => e
|
72
|
+
end
|
73
|
+
|
74
|
+
assert !!e
|
75
|
+
bt = e.backtrace.map(&LOCATION_ONLY)
|
76
|
+
assert_equal ["#{__FILE__}:#{lineno + 1}", "#{__FILE__}:#{lineno}"] + base, bt
|
77
|
+
ensure
|
78
|
+
Exception.__disable_sanitized_backtrace__ = true
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_backtrace_on_grand_child_fiber
|
82
|
+
Exception.__disable_sanitized_backtrace__ = false
|
83
|
+
|
84
|
+
lineno = __LINE__ + 1
|
85
|
+
f1 = spin do
|
86
|
+
f2 = spin do
|
87
|
+
raise 'foo'
|
88
|
+
end
|
89
|
+
f2.await
|
90
|
+
end
|
91
|
+
|
92
|
+
base = caller.map(&LOCATION_ONLY)
|
93
|
+
|
94
|
+
begin
|
95
|
+
f1.await
|
96
|
+
rescue => e
|
97
|
+
end
|
98
|
+
|
99
|
+
assert !!e
|
100
|
+
bt = e.backtrace.map(&LOCATION_ONLY)
|
101
|
+
assert_equal ["#{__FILE__}:#{lineno + 2}", "#{__FILE__}:#{lineno + 1}", "#{__FILE__}:#{lineno}"] + base, bt
|
102
|
+
ensure
|
103
|
+
Exception.__disable_sanitized_backtrace__ = true
|
104
|
+
end
|
42
105
|
end
|
43
106
|
|
44
107
|
class ProcessTest < MiniTest::Test
|
data/test/test_thread_pool.rb
CHANGED
@@ -56,7 +56,7 @@ class ThreadPoolTest < MiniTest::Test
|
|
56
56
|
t0 = Time.now
|
57
57
|
threads = []
|
58
58
|
buffer = []
|
59
|
-
|
59
|
+
20.times do |i|
|
60
60
|
@pool.cast do
|
61
61
|
sleep 0.01
|
62
62
|
threads << Thread.current
|
@@ -70,7 +70,7 @@ class ThreadPoolTest < MiniTest::Test
|
|
70
70
|
|
71
71
|
sleep 0.20 # allow time for threads to spawn
|
72
72
|
assert_equal @pool.size, threads.uniq.size
|
73
|
-
assert_equal (0..
|
73
|
+
assert_equal (0..19).to_a, buffer.sort if IS_LINUX
|
74
74
|
end
|
75
75
|
|
76
76
|
def test_busy?
|
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.96'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -16,98 +16,84 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.2.1
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.2.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 5.
|
33
|
+
version: 5.17.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 5.
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest-reporters
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - '='
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 1.4.2
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - '='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 1.4.2
|
40
|
+
version: 5.17.0
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: simplecov
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - '='
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
47
|
+
version: 0.22.0
|
62
48
|
type: :development
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - '='
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.
|
54
|
+
version: 0.22.0
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: rubocop
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - '='
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
61
|
+
version: 1.45.1
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - '='
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
68
|
+
version: 1.45.1
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: pry
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - '='
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.
|
75
|
+
version: 0.14.2
|
90
76
|
type: :development
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
80
|
- - '='
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version: 0.
|
82
|
+
version: 0.14.2
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: msgpack
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
87
|
- - '='
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version: 1.
|
89
|
+
version: 1.6.0
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
94
|
- - '='
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version: 1.
|
96
|
+
version: 1.6.0
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: httparty
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,16 +112,16 @@ dependencies:
|
|
126
112
|
name: localhost
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
128
114
|
requirements:
|
129
|
-
- -
|
115
|
+
- - '='
|
130
116
|
- !ruby/object:Gem::Version
|
131
|
-
version: 1.1.
|
117
|
+
version: 1.1.10
|
132
118
|
type: :development
|
133
119
|
prerelease: false
|
134
120
|
version_requirements: !ruby/object:Gem::Requirement
|
135
121
|
requirements:
|
136
|
-
- -
|
122
|
+
- - '='
|
137
123
|
- !ruby/object:Gem::Version
|
138
|
-
version: 1.1.
|
124
|
+
version: 1.1.10
|
139
125
|
description:
|
140
126
|
email: sharon@noteflakes.com
|
141
127
|
executables: []
|
@@ -271,6 +257,7 @@ files:
|
|
271
257
|
- examples/io/pry.rb
|
272
258
|
- examples/io/rack_server.rb
|
273
259
|
- examples/io/raw.rb
|
260
|
+
- examples/io/readline.rb
|
274
261
|
- examples/io/reline.rb
|
275
262
|
- examples/io/splice_chunks.rb
|
276
263
|
- examples/io/splice_echo_server.rb
|
@@ -364,6 +351,7 @@ files:
|
|
364
351
|
- lib/polyphony/adapters/readline.rb
|
365
352
|
- lib/polyphony/adapters/redis.rb
|
366
353
|
- lib/polyphony/adapters/sequel.rb
|
354
|
+
- lib/polyphony/core/channel.rb
|
367
355
|
- lib/polyphony/core/debug.rb
|
368
356
|
- lib/polyphony/core/exceptions.rb
|
369
357
|
- lib/polyphony/core/global_api.rb
|
@@ -374,7 +362,6 @@ files:
|
|
374
362
|
- lib/polyphony/core/timer.rb
|
375
363
|
- lib/polyphony/debugger.rb
|
376
364
|
- lib/polyphony/extensions.rb
|
377
|
-
- lib/polyphony/extensions/enumerator.rb
|
378
365
|
- lib/polyphony/extensions/exception.rb
|
379
366
|
- lib/polyphony/extensions/fiber.rb
|
380
367
|
- lib/polyphony/extensions/io.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Extensions to the Enumerator class
|
4
|
-
class ::Enumerator
|
5
|
-
alias_method :orig_next, :next
|
6
|
-
def next
|
7
|
-
Fiber.current.thread ||= Thread.current
|
8
|
-
orig_next
|
9
|
-
end
|
10
|
-
|
11
|
-
alias_method :orig_each, :each
|
12
|
-
def each(*a, &b)
|
13
|
-
Fiber.current.thread ||= Thread.current
|
14
|
-
orig_each(*a, &b)
|
15
|
-
end
|
16
|
-
end
|