polyphony 0.77 → 0.80
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/CHANGELOG.md +18 -0
- data/Gemfile.lock +2 -1
- data/examples/core/pingpong.rb +7 -4
- data/examples/core/zlib_stream.rb +15 -0
- data/ext/polyphony/backend_common.c +16 -8
- data/ext/polyphony/backend_common.h +8 -3
- data/ext/polyphony/backend_io_uring.c +19 -3
- data/ext/polyphony/backend_libev.c +33 -17
- data/ext/polyphony/fiber.c +28 -28
- data/ext/polyphony/polyphony.c +1 -8
- data/ext/polyphony/polyphony.h +11 -8
- data/ext/polyphony/queue.c +82 -6
- data/ext/polyphony/thread.c +6 -2
- data/lib/polyphony/adapters/fs.rb +4 -0
- data/lib/polyphony/adapters/process.rb +14 -1
- data/lib/polyphony/adapters/redis.rb +28 -0
- data/lib/polyphony/adapters/sequel.rb +19 -1
- data/lib/polyphony/core/debug.rb +203 -0
- data/lib/polyphony/core/exceptions.rb +21 -6
- data/lib/polyphony/core/global_api.rb +228 -73
- data/lib/polyphony/core/resource_pool.rb +65 -20
- data/lib/polyphony/core/sync.rb +57 -12
- data/lib/polyphony/core/thread_pool.rb +42 -5
- data/lib/polyphony/core/throttler.rb +21 -5
- data/lib/polyphony/core/timer.rb +125 -1
- data/lib/polyphony/extensions/exception.rb +36 -6
- data/lib/polyphony/extensions/fiber.rb +244 -61
- data/lib/polyphony/extensions/io.rb +4 -2
- data/lib/polyphony/extensions/kernel.rb +9 -4
- data/lib/polyphony/extensions/object.rb +8 -0
- data/lib/polyphony/extensions/openssl.rb +3 -1
- data/lib/polyphony/extensions/socket.rb +458 -39
- data/lib/polyphony/extensions/thread.rb +108 -43
- data/lib/polyphony/extensions/timeout.rb +12 -1
- data/lib/polyphony/extensions.rb +1 -0
- data/lib/polyphony/net.rb +59 -0
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +0 -2
- data/test/test_backend.rb +6 -2
- data/test/test_global_api.rb +0 -23
- data/test/test_io.rb +7 -7
- data/test/test_queue.rb +103 -1
- data/test/test_resource_pool.rb +1 -1
- data/test/test_signal.rb +15 -15
- data/test/test_supervise.rb +27 -0
- data/test/test_thread.rb +1 -1
- data/test/test_throttler.rb +0 -6
- data/test/test_trace.rb +189 -24
- metadata +9 -8
- data/lib/polyphony/core/channel.rb +0 -15
data/test/test_throttler.rb
CHANGED
@@ -11,8 +11,6 @@ class ThrottlerTest < MiniTest::Test
|
|
11
11
|
sleep 0.2
|
12
12
|
f.stop
|
13
13
|
assert_in_range 1..4, buffer.size if IS_LINUX
|
14
|
-
ensure
|
15
|
-
t.stop
|
16
14
|
end
|
17
15
|
|
18
16
|
def test_throttler_with_hash_of_rate
|
@@ -24,8 +22,6 @@ class ThrottlerTest < MiniTest::Test
|
|
24
22
|
sleep 0.25
|
25
23
|
f.stop
|
26
24
|
assert_in_range 4..6, buffer.size if IS_LINUX
|
27
|
-
ensure
|
28
|
-
t.stop
|
29
25
|
end
|
30
26
|
|
31
27
|
def test_throttler_with_hash_of_interval
|
@@ -35,8 +31,6 @@ class ThrottlerTest < MiniTest::Test
|
|
35
31
|
sleep 0.02
|
36
32
|
f.stop
|
37
33
|
assert_in_range 2..4, buffer.size if IS_LINUX
|
38
|
-
ensure
|
39
|
-
t.stop
|
40
34
|
end
|
41
35
|
|
42
36
|
def test_throttler_with_invalid_argument
|
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,171 @@ 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
|
133
|
+
|
134
|
+
def test_event_firehose_with_threaded_receiver
|
135
|
+
buffer = []
|
136
|
+
this = Fiber.current
|
137
|
+
receiver = Thread.new {
|
138
|
+
this << :ok
|
139
|
+
loop {
|
140
|
+
e = receive
|
141
|
+
break if e == :stop
|
142
|
+
buffer << e
|
143
|
+
}
|
144
|
+
}
|
145
|
+
receive
|
146
|
+
|
147
|
+
Polyphony::Trace.start_event_firehose { |e| receiver << e }
|
148
|
+
|
149
|
+
f1 = spin(:f1) do
|
150
|
+
receive
|
151
|
+
end
|
152
|
+
|
153
|
+
f1 << :foo
|
154
|
+
f1.await
|
155
|
+
|
156
|
+
Thread.backend.trace_proc = nil
|
157
|
+
receiver << :stop
|
158
|
+
receiver.await
|
159
|
+
|
160
|
+
buffer.each { |e| e.delete(:stamp); e.delete(:caller) }
|
161
|
+
|
162
|
+
main = Fiber.current
|
163
|
+
assert_equal(
|
164
|
+
[
|
165
|
+
{ event: :spin, fiber: f1, source_fiber: main },
|
166
|
+
{ event: :schedule, fiber: f1, value: nil, source_fiber: main },
|
167
|
+
{ event: :block, fiber: main },
|
168
|
+
{ event: :unblock, fiber: f1, value: nil },
|
169
|
+
{ event: :schedule, fiber: f1, value: nil, source_fiber: f1 },
|
170
|
+
{ event: :block, fiber: f1, },
|
171
|
+
{ event: :enter_poll },
|
172
|
+
{ event: :leave_poll },
|
173
|
+
{ event: :unblock, fiber: f1, value: nil },
|
174
|
+
{ event: :terminate, fiber: f1, value: :foo },
|
175
|
+
{ event: :schedule, fiber: main, value: nil, source_fiber: f1 },
|
176
|
+
{ event: :block, fiber: f1 },
|
177
|
+
{ event: :unblock, fiber: main, value: nil }
|
178
|
+
], buffer
|
179
|
+
)
|
180
|
+
ensure
|
181
|
+
Thread.backend.trace_proc = nil
|
182
|
+
end
|
183
|
+
|
184
|
+
# def test_event_firehose_with_reentrancy
|
185
|
+
# buffer = []
|
186
|
+
# Polyphony::Trace.start_event_firehose { |e| buffer << e }
|
187
|
+
|
188
|
+
# f1 = spin(:f1) do
|
189
|
+
# receive
|
190
|
+
# end
|
191
|
+
|
192
|
+
# f1 << :foo
|
193
|
+
# f1.await
|
194
|
+
|
195
|
+
# Thread.backend.trace_proc = nil
|
196
|
+
# buffer.each { |e| e.delete(:stamp); e.delete(:caller) }
|
197
|
+
|
198
|
+
# main = Fiber.current
|
199
|
+
# assert_equal(
|
200
|
+
# [
|
201
|
+
# { event: :spin, fiber: f1, source_fiber: main },
|
202
|
+
# { event: :schedule, fiber: f1, value: nil, source_fiber: main },
|
203
|
+
# { event: :block, fiber: main },
|
204
|
+
# { event: :unblock, fiber: f1, value: nil },
|
205
|
+
# { event: :schedule, fiber: f1, value: nil, source_fiber: f1 },
|
206
|
+
# { event: :block, fiber: f1, },
|
207
|
+
# { event: :enter_poll },
|
208
|
+
# { event: :leave_poll },
|
209
|
+
# { event: :unblock, fiber: f1, value: nil },
|
210
|
+
# { event: :terminate, fiber: f1, value: :foo },
|
211
|
+
# { event: :schedule, fiber: main, value: nil, source_fiber: f1 },
|
212
|
+
# { event: :block, fiber: f1 },
|
213
|
+
# { event: :unblock, fiber: main, value: nil }
|
214
|
+
# ], buffer
|
215
|
+
# )
|
216
|
+
# ensure
|
217
|
+
# Thread.backend.trace_proc = nil
|
218
|
+
# end
|
219
|
+
|
55
220
|
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.80'
|
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: 2022-02-
|
11
|
+
date: 2022-02-28 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:
|
@@ -249,6 +249,7 @@ files:
|
|
249
249
|
- examples/core/trap2.rb
|
250
250
|
- examples/core/using-a-mutex.rb
|
251
251
|
- examples/core/worker-thread.rb
|
252
|
+
- examples/core/zlib_stream.rb
|
252
253
|
- examples/io/backticks.rb
|
253
254
|
- examples/io/echo_client.rb
|
254
255
|
- examples/io/echo_client_from_stdin.rb
|
@@ -358,7 +359,6 @@ files:
|
|
358
359
|
- lib/polyphony/adapters/readline.rb
|
359
360
|
- lib/polyphony/adapters/redis.rb
|
360
361
|
- lib/polyphony/adapters/sequel.rb
|
361
|
-
- lib/polyphony/core/channel.rb
|
362
362
|
- lib/polyphony/core/debug.rb
|
363
363
|
- lib/polyphony/core/exceptions.rb
|
364
364
|
- lib/polyphony/core/global_api.rb
|
@@ -373,6 +373,7 @@ files:
|
|
373
373
|
- lib/polyphony/extensions/fiber.rb
|
374
374
|
- lib/polyphony/extensions/io.rb
|
375
375
|
- lib/polyphony/extensions/kernel.rb
|
376
|
+
- lib/polyphony/extensions/object.rb
|
376
377
|
- lib/polyphony/extensions/openssl.rb
|
377
378
|
- lib/polyphony/extensions/process.rb
|
378
379
|
- lib/polyphony/extensions/socket.rb
|
@@ -415,7 +416,7 @@ metadata:
|
|
415
416
|
documentation_uri: https://digital-fabric.github.io/polyphony/
|
416
417
|
homepage_uri: https://digital-fabric.github.io/polyphony/
|
417
418
|
changelog_uri: https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md
|
418
|
-
post_install_message:
|
419
|
+
post_install_message:
|
419
420
|
rdoc_options:
|
420
421
|
- "--title"
|
421
422
|
- polyphony
|
@@ -434,8 +435,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
434
435
|
- !ruby/object:Gem::Version
|
435
436
|
version: '0'
|
436
437
|
requirements: []
|
437
|
-
rubygems_version: 3.
|
438
|
-
signing_key:
|
438
|
+
rubygems_version: 3.1.6
|
439
|
+
signing_key:
|
439
440
|
specification_version: 4
|
440
441
|
summary: Fine grained concurrency for Ruby
|
441
442
|
test_files: []
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './exceptions'
|
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
|