polyphony 0.58 → 0.61
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -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 +160 -7
- data/ext/polyphony/backend_common.h +34 -2
- data/ext/polyphony/backend_io_uring.c +119 -40
- 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 +109 -31
- data/ext/polyphony/extconf.rb +2 -2
- data/ext/polyphony/fiber.c +1 -34
- data/ext/polyphony/polyphony.c +12 -19
- data/ext/polyphony/polyphony.h +9 -20
- data/ext/polyphony/polyphony_ext.c +0 -4
- data/ext/polyphony/queue.c +12 -12
- data/ext/polyphony/runqueue.c +21 -98
- data/ext/polyphony/runqueue.h +26 -0
- data/ext/polyphony/thread.c +6 -113
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/extensions/fiber.rb +102 -82
- 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/extensions/thread.rb +1 -1
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +0 -7
- data/test/test_backend.rb +46 -9
- 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.rb +5 -11
- data/test/test_thread_pool.rb +1 -1
- data/test/test_trace.rb +28 -49
- metadata +5 -109
- data/ext/polyphony/tracing.c +0 -11
- data/lib/polyphony/adapters/trace.rb +0 -138
@@ -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
|
@@ -351,10 +388,10 @@ class BackendTest < MiniTest::Test
|
|
351
388
|
GC.enable
|
352
389
|
end
|
353
390
|
|
354
|
-
def
|
391
|
+
def test_idle_proc
|
355
392
|
counter = 0
|
356
393
|
|
357
|
-
@backend.
|
394
|
+
@backend.idle_proc = proc { counter += 1 }
|
358
395
|
|
359
396
|
3.times { snooze }
|
360
397
|
assert_equal 0, counter
|
@@ -368,7 +405,7 @@ class BackendTest < MiniTest::Test
|
|
368
405
|
3.times { snooze }
|
369
406
|
assert_equal 2, counter
|
370
407
|
|
371
|
-
@backend.
|
408
|
+
@backend.idle_proc = nil
|
372
409
|
sleep 0.01
|
373
410
|
assert_equal 2, counter
|
374
411
|
end
|
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
|