polyphony 0.59 → 0.62
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 +24 -0
- data/Gemfile.lock +15 -29
- data/examples/core/message_based_supervision.rb +51 -0
- data/examples/io/echo_server.rb +16 -7
- data/ext/polyphony/backend_common.c +83 -16
- data/ext/polyphony/backend_common.h +15 -3
- data/ext/polyphony/backend_io_uring.c +58 -25
- data/ext/polyphony/backend_io_uring_context.c +10 -1
- data/ext/polyphony/backend_io_uring_context.h +5 -3
- data/ext/polyphony/backend_libev.c +52 -20
- data/ext/polyphony/extconf.rb +2 -2
- data/ext/polyphony/fiber.c +1 -32
- data/ext/polyphony/polyphony.c +12 -12
- data/ext/polyphony/polyphony.h +4 -5
- data/ext/polyphony/queue.c +12 -12
- data/ext/polyphony/runqueue.c +11 -19
- data/ext/polyphony/runqueue.h +2 -2
- data/ext/polyphony/thread.c +0 -18
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/extensions/fiber.rb +100 -80
- data/lib/polyphony/extensions/io.rb +10 -9
- data/lib/polyphony/extensions/openssl.rb +14 -4
- data/lib/polyphony/extensions/socket.rb +15 -15
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +0 -7
- data/test/test_backend.rb +43 -6
- data/test/test_ext.rb +1 -1
- data/test/test_fiber.rb +106 -18
- data/test/test_global_api.rb +1 -1
- data/test/test_io.rb +29 -0
- data/test/test_supervise.rb +100 -100
- data/test/test_thread_pool.rb +1 -1
- data/test/test_trace.rb +5 -4
- metadata +4 -107
@@ -101,7 +101,7 @@ class ::IO
|
|
101
101
|
return @read_buffer.slice!(0) if @read_buffer && !@read_buffer.empty?
|
102
102
|
|
103
103
|
@read_buffer ||= +''
|
104
|
-
Polyphony.backend_read(self, @read_buffer, 8192, false)
|
104
|
+
Polyphony.backend_read(self, @read_buffer, 8192, false, -1)
|
105
105
|
return @read_buffer.slice!(0) if !@read_buffer.empty?
|
106
106
|
|
107
107
|
nil
|
@@ -110,7 +110,7 @@ class ::IO
|
|
110
110
|
alias_method :orig_read, :read
|
111
111
|
def read(len = nil)
|
112
112
|
@read_buffer ||= +''
|
113
|
-
result = Polyphony.backend_read(self, @read_buffer, len, true)
|
113
|
+
result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
|
114
114
|
return nil unless result
|
115
115
|
|
116
116
|
already_read = @read_buffer
|
@@ -119,8 +119,8 @@ class ::IO
|
|
119
119
|
end
|
120
120
|
|
121
121
|
alias_method :orig_readpartial, :read
|
122
|
-
def readpartial(len, str = +'')
|
123
|
-
result = Polyphony.backend_read(self, str, len, false)
|
122
|
+
def readpartial(len, str = +'', buffer_pos = 0)
|
123
|
+
result = Polyphony.backend_read(self, str, len, false, buffer_pos)
|
124
124
|
raise EOFError unless result
|
125
125
|
|
126
126
|
result
|
@@ -151,9 +151,10 @@ class ::IO
|
|
151
151
|
idx = @read_buffer.index(sep)
|
152
152
|
return @read_buffer.slice!(0, idx + sep_size) if idx
|
153
153
|
|
154
|
-
|
155
|
-
|
156
|
-
@read_buffer
|
154
|
+
result = readpartial(8192, @read_buffer, -1)
|
155
|
+
|
156
|
+
#Polyphony.backend_read(self, @read_buffer, 8192, false, -1)
|
157
|
+
return nil unless result
|
157
158
|
end
|
158
159
|
rescue EOFError
|
159
160
|
return nil
|
@@ -216,8 +217,8 @@ class ::IO
|
|
216
217
|
buf ? readpartial(maxlen, buf) : readpartial(maxlen)
|
217
218
|
end
|
218
219
|
|
219
|
-
def read_loop(&block)
|
220
|
-
Polyphony.backend_read_loop(self, &block)
|
220
|
+
def read_loop(maxlen = 8192, &block)
|
221
|
+
Polyphony.backend_read_loop(self, maxlen, &block)
|
221
222
|
end
|
222
223
|
|
223
224
|
def feed_loop(receiver, method = :call, &block)
|
@@ -64,13 +64,23 @@ class ::OpenSSL::SSL::SSLSocket
|
|
64
64
|
# @sync = osync
|
65
65
|
end
|
66
66
|
|
67
|
-
def readpartial(maxlen, buf = +'')
|
68
|
-
|
67
|
+
def readpartial(maxlen, buf = +'', buffer_pos = 0)
|
68
|
+
if buffer_pos != 0
|
69
|
+
if (result = sysread(maxlen, +''))
|
70
|
+
if buffer_pos == -1
|
71
|
+
result = buf + result
|
72
|
+
else
|
73
|
+
result = buf[0...buffer_pos] + result
|
74
|
+
end
|
75
|
+
end
|
76
|
+
else
|
77
|
+
result = sysread(maxlen, buf)
|
78
|
+
end
|
69
79
|
result || (raise EOFError)
|
70
80
|
end
|
71
81
|
|
72
|
-
def read_loop
|
73
|
-
while (data = sysread(
|
82
|
+
def read_loop(maxlen = 8192)
|
83
|
+
while (data = sysread(maxlen))
|
74
84
|
yield data
|
75
85
|
end
|
76
86
|
end
|
@@ -23,11 +23,11 @@ class ::Socket
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def recv(maxlen, flags = 0, outbuf = nil)
|
26
|
-
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
26
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
|
27
27
|
end
|
28
28
|
|
29
|
-
def recv_loop(&block)
|
30
|
-
Polyphony.backend_recv_loop(self, &block)
|
29
|
+
def recv_loop(maxlen = 8192, &block)
|
30
|
+
Polyphony.backend_recv_loop(self, maxlen, &block)
|
31
31
|
end
|
32
32
|
alias_method :read_loop, :recv_loop
|
33
33
|
|
@@ -60,8 +60,8 @@ class ::Socket
|
|
60
60
|
# Polyphony.backend_send(self, mesg, 0)
|
61
61
|
# end
|
62
62
|
|
63
|
-
def readpartial(maxlen, str = +'')
|
64
|
-
Polyphony.backend_recv(self, str, maxlen)
|
63
|
+
def readpartial(maxlen, str = +'', buffer_pos = 0)
|
64
|
+
Polyphony.backend_recv(self, str, maxlen, buffer_pos)
|
65
65
|
end
|
66
66
|
|
67
67
|
ZERO_LINGER = [0, 0].pack('ii').freeze
|
@@ -141,11 +141,11 @@ class ::TCPSocket
|
|
141
141
|
end
|
142
142
|
|
143
143
|
def recv(maxlen, flags = 0, outbuf = nil)
|
144
|
-
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
144
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
|
145
145
|
end
|
146
146
|
|
147
|
-
def recv_loop(&block)
|
148
|
-
Polyphony.backend_recv_loop(self, &block)
|
147
|
+
def recv_loop(maxlen = 8192, &block)
|
148
|
+
Polyphony.backend_recv_loop(self, maxlen, &block)
|
149
149
|
end
|
150
150
|
alias_method :read_loop, :recv_loop
|
151
151
|
|
@@ -165,8 +165,8 @@ class ::TCPSocket
|
|
165
165
|
# Polyphony.backend_send(self, mesg, 0)
|
166
166
|
# end
|
167
167
|
|
168
|
-
def readpartial(maxlen, str = +'')
|
169
|
-
result = Polyphony.backend_recv(self, str, maxlen)
|
168
|
+
def readpartial(maxlen, str = +'', buffer_pos = 0)
|
169
|
+
result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
|
170
170
|
raise EOFError unless result
|
171
171
|
|
172
172
|
str
|
@@ -218,11 +218,11 @@ end
|
|
218
218
|
|
219
219
|
class ::UNIXSocket
|
220
220
|
def recv(maxlen, flags = 0, outbuf = nil)
|
221
|
-
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
221
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
|
222
222
|
end
|
223
223
|
|
224
|
-
def recv_loop(&block)
|
225
|
-
Polyphony.backend_recv_loop(self, &block)
|
224
|
+
def recv_loop(maxlen = 8192, &block)
|
225
|
+
Polyphony.backend_recv_loop(self, maxlen, &block)
|
226
226
|
end
|
227
227
|
alias_method :read_loop, :recv_loop
|
228
228
|
|
@@ -242,8 +242,8 @@ class ::UNIXSocket
|
|
242
242
|
Polyphony.backend_send(self, mesg, 0)
|
243
243
|
end
|
244
244
|
|
245
|
-
def readpartial(maxlen, str = +'')
|
246
|
-
result = Polyphony.backend_recv(self, str, maxlen)
|
245
|
+
def readpartial(maxlen, str = +'', buffer_pos = 0)
|
246
|
+
result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
|
247
247
|
raise EOFError unless result
|
248
248
|
|
249
249
|
str
|
data/lib/polyphony/version.rb
CHANGED
data/polyphony.gemspec
CHANGED
@@ -29,13 +29,6 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.add_development_dependency 'pry', '0.13.1'
|
30
30
|
|
31
31
|
s.add_development_dependency 'msgpack', '1.4.2'
|
32
|
-
s.add_development_dependency 'pg', '1.1.4'
|
33
|
-
s.add_development_dependency 'redis', '4.1.0'
|
34
|
-
s.add_development_dependency 'hiredis', '0.6.3'
|
35
|
-
s.add_development_dependency 'http_parser.rb', '~>0.6.0'
|
36
|
-
s.add_development_dependency 'rack', '>=2.0.8', '<2.3.0'
|
37
|
-
s.add_development_dependency 'mysql2', '0.5.3'
|
38
|
-
s.add_development_dependency 'sequel', '5.34.0'
|
39
32
|
s.add_development_dependency 'httparty', '0.17.1'
|
40
33
|
s.add_development_dependency 'localhost', '~>1.1.4'
|
41
34
|
|
data/test/test_backend.rb
CHANGED
@@ -26,14 +26,14 @@ class BackendTest < MiniTest::Test
|
|
26
26
|
@backend.sleep 0.01
|
27
27
|
count += 1
|
28
28
|
}.await
|
29
|
-
|
29
|
+
assert_in_range 0.02..0.04, Time.now - t0
|
30
30
|
assert_equal 3, count
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_write_read_partial
|
34
34
|
i, o = IO.pipe
|
35
35
|
buf = +''
|
36
|
-
f = spin { @backend.read(i, buf, 5, false) }
|
36
|
+
f = spin { @backend.read(i, buf, 5, false, 0) }
|
37
37
|
@backend.write(o, 'Hello world')
|
38
38
|
return_value = f.await
|
39
39
|
|
@@ -44,7 +44,7 @@ class BackendTest < MiniTest::Test
|
|
44
44
|
def test_write_read_to_eof_limited_buffer
|
45
45
|
i, o = IO.pipe
|
46
46
|
buf = +''
|
47
|
-
f = spin { @backend.read(i, buf, 5, true) }
|
47
|
+
f = spin { @backend.read(i, buf, 5, true, 0) }
|
48
48
|
@backend.write(o, 'Hello')
|
49
49
|
snooze
|
50
50
|
@backend.write(o, ' world')
|
@@ -59,7 +59,7 @@ class BackendTest < MiniTest::Test
|
|
59
59
|
def test_write_read_to_eof
|
60
60
|
i, o = IO.pipe
|
61
61
|
buf = +''
|
62
|
-
f = spin { @backend.read(i, buf, 10**6, true) }
|
62
|
+
f = spin { @backend.read(i, buf, 10**6, true, 0) }
|
63
63
|
@backend.write(o, 'Hello')
|
64
64
|
snooze
|
65
65
|
@backend.write(o, ' world')
|
@@ -71,6 +71,33 @@ class BackendTest < MiniTest::Test
|
|
71
71
|
assert_equal return_value, buf
|
72
72
|
end
|
73
73
|
|
74
|
+
def test_write_read_with_buffer_position
|
75
|
+
i, o = IO.pipe
|
76
|
+
buf = +'abcdefghij'
|
77
|
+
f = spin { @backend.read(i, buf, 20, false, 0) }
|
78
|
+
@backend.write(o, 'blah')
|
79
|
+
return_value = f.await
|
80
|
+
|
81
|
+
assert_equal 'blah', buf
|
82
|
+
assert_equal return_value, buf
|
83
|
+
|
84
|
+
buf = +'abcdefghij'
|
85
|
+
f = spin { @backend.read(i, buf, 20, false, -1) }
|
86
|
+
@backend.write(o, 'klmn')
|
87
|
+
return_value = f.await
|
88
|
+
|
89
|
+
assert_equal 'abcdefghijklmn', buf
|
90
|
+
assert_equal return_value, buf
|
91
|
+
|
92
|
+
buf = +'abcdefghij'
|
93
|
+
f = spin { @backend.read(i, buf, 20, false, 3) }
|
94
|
+
@backend.write(o, 'DEF')
|
95
|
+
return_value = f.await
|
96
|
+
|
97
|
+
assert_equal 'abcDEF', buf
|
98
|
+
assert_equal return_value, buf
|
99
|
+
end
|
100
|
+
|
74
101
|
def test_waitpid
|
75
102
|
pid = fork do
|
76
103
|
@backend.post_fork
|
@@ -87,7 +114,7 @@ class BackendTest < MiniTest::Test
|
|
87
114
|
buf = []
|
88
115
|
f = spin do
|
89
116
|
buf << :ready
|
90
|
-
@backend.read_loop(i) { |d| buf << d }
|
117
|
+
@backend.read_loop(i, 8192) { |d| buf << d }
|
91
118
|
buf << :done
|
92
119
|
end
|
93
120
|
|
@@ -107,7 +134,7 @@ class BackendTest < MiniTest::Test
|
|
107
134
|
parent = spin do
|
108
135
|
f = spin do
|
109
136
|
buf << :ready
|
110
|
-
@backend.read_loop(i) { |d| buf << d }
|
137
|
+
@backend.read_loop(i, 8192) { |d| buf << d }
|
111
138
|
buf << :done
|
112
139
|
end
|
113
140
|
suspend
|
@@ -125,6 +152,16 @@ class BackendTest < MiniTest::Test
|
|
125
152
|
assert_equal [:ready, 'foo', 'bar'], buf
|
126
153
|
end
|
127
154
|
|
155
|
+
def test_read_loop_with_max_len
|
156
|
+
r, w = IO.pipe
|
157
|
+
|
158
|
+
w << 'foobar'
|
159
|
+
w.close
|
160
|
+
buf = []
|
161
|
+
@backend.read_loop(r, 3) { |data| buf << data }
|
162
|
+
assert_equal ['foo', 'bar'], buf
|
163
|
+
end
|
164
|
+
|
128
165
|
Net = Polyphony::Net
|
129
166
|
|
130
167
|
def test_accept
|
data/test/test_ext.rb
CHANGED
data/test/test_fiber.rb
CHANGED
@@ -43,6 +43,14 @@ class FiberTest < MiniTest::Test
|
|
43
43
|
f&.stop
|
44
44
|
end
|
45
45
|
|
46
|
+
def test_await_dead_children
|
47
|
+
f1 = spin { :foo }
|
48
|
+
f2 = spin { :bar }
|
49
|
+
2.times { snooze }
|
50
|
+
|
51
|
+
assert_equal [:foo, :bar], Fiber.await(f1, f2)
|
52
|
+
end
|
53
|
+
|
46
54
|
def test_await_from_multiple_fibers
|
47
55
|
buffer = []
|
48
56
|
f1 = spin {
|
@@ -348,12 +356,12 @@ class FiberTest < MiniTest::Test
|
|
348
356
|
assert_equal [:foo, :terminate], buffer
|
349
357
|
end
|
350
358
|
|
351
|
-
|
352
|
-
ruby -rbundler/setup -rpolyphony -e
|
359
|
+
CMD_TERMINATE_CHILD_FIBER = <<~BASH
|
360
|
+
ruby -rbundler/setup -rpolyphony -e'f = spin { sleep }; spin { sleep 0.1; f.terminate }; f.await' 2>&1
|
353
361
|
BASH
|
354
362
|
|
355
|
-
|
356
|
-
ruby -rbundler/setup -rpolyphony -e"
|
363
|
+
CMD_TERMINATE_MAIN_FIBER = <<~BASH
|
364
|
+
ruby -rbundler/setup -rpolyphony -e"spin { sleep 0.1; Thread.current.main_fiber.terminate }; begin; sleep; rescue Polyphony::Terminate; STDOUT << 'terminated'; end" 2>&1
|
357
365
|
BASH
|
358
366
|
|
359
367
|
def test_terminate_main_fiber
|
@@ -547,24 +555,38 @@ class FiberTest < MiniTest::Test
|
|
547
555
|
assert f.location =~ location
|
548
556
|
end
|
549
557
|
|
550
|
-
def
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
558
|
+
def test_monitor
|
559
|
+
child = nil
|
560
|
+
parent = spin do
|
561
|
+
child = spin { receive }
|
562
|
+
child.await
|
555
563
|
end
|
556
|
-
f.when_done { values << 42 }
|
557
564
|
|
558
565
|
snooze
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
566
|
+
child.monitor
|
567
|
+
spin { child << :foo }
|
568
|
+
|
569
|
+
msg = receive
|
570
|
+
assert_equal [child, :foo], msg
|
571
|
+
end
|
564
572
|
|
573
|
+
def test_unmonitor
|
574
|
+
child = nil
|
575
|
+
parent = spin(:parent) do
|
576
|
+
child = spin(:child) { receive }
|
577
|
+
child.await
|
578
|
+
end
|
579
|
+
|
580
|
+
snooze
|
581
|
+
child.monitor
|
582
|
+
spin { child << :foo }
|
565
583
|
snooze
|
566
|
-
|
567
|
-
|
584
|
+
|
585
|
+
child.unmonitor
|
586
|
+
|
587
|
+
Fiber.current << :bar
|
588
|
+
msg = receive
|
589
|
+
assert_equal :bar, msg
|
568
590
|
end
|
569
591
|
|
570
592
|
def test_children
|
@@ -732,6 +754,72 @@ class FiberTest < MiniTest::Test
|
|
732
754
|
assert_equal ['bar'], buffer
|
733
755
|
snooze
|
734
756
|
end
|
757
|
+
|
758
|
+
def test_detach
|
759
|
+
buf = []
|
760
|
+
child = nil
|
761
|
+
parent = spin(:parent) do
|
762
|
+
buf << :hi_from_parent
|
763
|
+
child = spin(:child) do
|
764
|
+
buf << :hi_from_child
|
765
|
+
# wait for message (from main fiber)
|
766
|
+
buf << receive
|
767
|
+
end
|
768
|
+
snooze
|
769
|
+
buf << :bye_from_parent
|
770
|
+
end
|
771
|
+
|
772
|
+
snooze
|
773
|
+
assert_equal parent, child.parent
|
774
|
+
child.detach
|
775
|
+
assert_equal Fiber.current, child.parent
|
776
|
+
parent.await
|
777
|
+
|
778
|
+
child << :bye
|
779
|
+
child.await
|
780
|
+
|
781
|
+
assert_equal [
|
782
|
+
:hi_from_parent,
|
783
|
+
:hi_from_child,
|
784
|
+
:bye_from_parent,
|
785
|
+
:bye
|
786
|
+
], buf
|
787
|
+
end
|
788
|
+
|
789
|
+
def test_attach
|
790
|
+
buf = []
|
791
|
+
child = nil
|
792
|
+
parent = spin(:parent) do
|
793
|
+
buf << :hi_from_parent
|
794
|
+
child = spin(:child) do
|
795
|
+
buf << :hi_from_child
|
796
|
+
# wait for message (from main fiber)
|
797
|
+
buf << receive
|
798
|
+
end
|
799
|
+
snooze
|
800
|
+
buf << :bye_from_parent
|
801
|
+
end
|
802
|
+
|
803
|
+
new_parent = spin(:new_parent) { buf << receive }
|
804
|
+
|
805
|
+
snooze
|
806
|
+
assert_equal parent, child.parent
|
807
|
+
child.attach(new_parent)
|
808
|
+
assert_equal new_parent, child.parent
|
809
|
+
parent.await
|
810
|
+
|
811
|
+
child << :bye
|
812
|
+
new_parent << :bye_new_parent
|
813
|
+
snooze
|
814
|
+
|
815
|
+
assert_equal [
|
816
|
+
:hi_from_parent,
|
817
|
+
:hi_from_child,
|
818
|
+
:bye_from_parent,
|
819
|
+
:bye,
|
820
|
+
:bye_new_parent
|
821
|
+
], buf
|
822
|
+
end
|
735
823
|
end
|
736
824
|
|
737
825
|
class MailboxTest < MiniTest::Test
|
@@ -964,7 +1052,7 @@ class FiberControlTest < MiniTest::Test
|
|
964
1052
|
assert_equal 'foo', result.message
|
965
1053
|
assert_equal f1, result.source_fiber
|
966
1054
|
assert_equal :dead, f1.state
|
967
|
-
assert_equal :
|
1055
|
+
assert_equal :waiting, f2.state
|
968
1056
|
end
|
969
1057
|
|
970
1058
|
def test_select_with_interruption
|