polyphony 0.59.1 → 0.63
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 +25 -0
- data/Gemfile.lock +15 -29
- data/Rakefile +1 -1
- 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/extensions/fiber.rb +100 -80
- data/lib/polyphony/extensions/io.rb +15 -10
- data/lib/polyphony/extensions/openssl.rb +28 -4
- data/lib/polyphony/extensions/socket.rb +66 -15
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +0 -7
- data/test/test_backend.rb +69 -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 +49 -0
- data/test/test_socket.rb +39 -1
- 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,16 +101,20 @@ 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
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
alias_method :orig_read, :read
|
|
111
|
-
def read(len = nil)
|
|
111
|
+
def read(len = nil, buf = nil, buf_pos = 0)
|
|
112
|
+
if buf
|
|
113
|
+
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
|
114
|
+
end
|
|
115
|
+
|
|
112
116
|
@read_buffer ||= +''
|
|
113
|
-
result = Polyphony.backend_read(self, @read_buffer, len, true)
|
|
117
|
+
result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
|
|
114
118
|
return nil unless result
|
|
115
119
|
|
|
116
120
|
already_read = @read_buffer
|
|
@@ -119,8 +123,8 @@ class ::IO
|
|
|
119
123
|
end
|
|
120
124
|
|
|
121
125
|
alias_method :orig_readpartial, :read
|
|
122
|
-
def readpartial(len, str = +'')
|
|
123
|
-
result = Polyphony.backend_read(self, str, len, false)
|
|
126
|
+
def readpartial(len, str = +'', buffer_pos = 0)
|
|
127
|
+
result = Polyphony.backend_read(self, str, len, false, buffer_pos)
|
|
124
128
|
raise EOFError unless result
|
|
125
129
|
|
|
126
130
|
result
|
|
@@ -151,9 +155,10 @@ class ::IO
|
|
|
151
155
|
idx = @read_buffer.index(sep)
|
|
152
156
|
return @read_buffer.slice!(0, idx + sep_size) if idx
|
|
153
157
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
@read_buffer
|
|
158
|
+
result = readpartial(8192, @read_buffer, -1)
|
|
159
|
+
|
|
160
|
+
#Polyphony.backend_read(self, @read_buffer, 8192, false, -1)
|
|
161
|
+
return nil unless result
|
|
157
162
|
end
|
|
158
163
|
rescue EOFError
|
|
159
164
|
return nil
|
|
@@ -216,8 +221,8 @@ class ::IO
|
|
|
216
221
|
buf ? readpartial(maxlen, buf) : readpartial(maxlen)
|
|
217
222
|
end
|
|
218
223
|
|
|
219
|
-
def read_loop(&block)
|
|
220
|
-
Polyphony.backend_read_loop(self, &block)
|
|
224
|
+
def read_loop(maxlen = 8192, &block)
|
|
225
|
+
Polyphony.backend_read_loop(self, maxlen, &block)
|
|
221
226
|
end
|
|
222
227
|
|
|
223
228
|
def feed_loop(receiver, method = :call, &block)
|
|
@@ -64,13 +64,37 @@ class ::OpenSSL::SSL::SSLSocket
|
|
|
64
64
|
# @sync = osync
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
alias_method :orig_read, :read
|
|
68
|
+
def read(maxlen = nil, buf = nil, buf_pos = 0)
|
|
69
|
+
return readpartial(maxlen, buf, buf_pos) if buf
|
|
70
|
+
|
|
71
|
+
buf = +''
|
|
72
|
+
return readpartial(maxlen, buf) if maxlen
|
|
73
|
+
|
|
74
|
+
while true
|
|
75
|
+
readpartial(4096, buf, -1)
|
|
76
|
+
end
|
|
77
|
+
rescue EOFError
|
|
78
|
+
buf
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def readpartial(maxlen, buf = +'', buffer_pos = 0)
|
|
82
|
+
if buffer_pos != 0
|
|
83
|
+
if (result = sysread(maxlen, +''))
|
|
84
|
+
if buffer_pos == -1
|
|
85
|
+
result = buf + result
|
|
86
|
+
else
|
|
87
|
+
result = buf[0...buffer_pos] + result
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
else
|
|
91
|
+
result = sysread(maxlen, buf)
|
|
92
|
+
end
|
|
69
93
|
result || (raise EOFError)
|
|
70
94
|
end
|
|
71
95
|
|
|
72
|
-
def read_loop
|
|
73
|
-
while (data = sysread(
|
|
96
|
+
def read_loop(maxlen = 8192)
|
|
97
|
+
while (data = sysread(maxlen))
|
|
74
98
|
yield data
|
|
75
99
|
end
|
|
76
100
|
end
|
|
@@ -22,12 +22,29 @@ class ::Socket
|
|
|
22
22
|
Polyphony.backend_connect(self, addr.ip_address, addr.ip_port)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
alias_method :orig_read, :read
|
|
26
|
+
def read(maxlen = nil, buf = nil, buf_pos = 0)
|
|
27
|
+
return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
|
|
28
|
+
return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
|
|
29
|
+
|
|
30
|
+
buf = +''
|
|
31
|
+
len = buf.bytesize
|
|
32
|
+
while true
|
|
33
|
+
Polyphony.backend_recv(self, buf, maxlen || 4096, -1)
|
|
34
|
+
new_len = buf.bytesize
|
|
35
|
+
break if new_len == len
|
|
36
|
+
|
|
37
|
+
len = new_len
|
|
38
|
+
end
|
|
39
|
+
buf
|
|
40
|
+
end
|
|
41
|
+
|
|
25
42
|
def recv(maxlen, flags = 0, outbuf = nil)
|
|
26
|
-
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
|
43
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
|
|
27
44
|
end
|
|
28
45
|
|
|
29
|
-
def recv_loop(&block)
|
|
30
|
-
Polyphony.backend_recv_loop(self, &block)
|
|
46
|
+
def recv_loop(maxlen = 8192, &block)
|
|
47
|
+
Polyphony.backend_recv_loop(self, maxlen, &block)
|
|
31
48
|
end
|
|
32
49
|
alias_method :read_loop, :recv_loop
|
|
33
50
|
|
|
@@ -60,8 +77,8 @@ class ::Socket
|
|
|
60
77
|
# Polyphony.backend_send(self, mesg, 0)
|
|
61
78
|
# end
|
|
62
79
|
|
|
63
|
-
def readpartial(maxlen, str = +'')
|
|
64
|
-
Polyphony.backend_recv(self, str, maxlen)
|
|
80
|
+
def readpartial(maxlen, str = +'', buffer_pos = 0)
|
|
81
|
+
Polyphony.backend_recv(self, str, maxlen, buffer_pos)
|
|
65
82
|
end
|
|
66
83
|
|
|
67
84
|
ZERO_LINGER = [0, 0].pack('ii').freeze
|
|
@@ -140,12 +157,29 @@ class ::TCPSocket
|
|
|
140
157
|
setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, 1)
|
|
141
158
|
end
|
|
142
159
|
|
|
160
|
+
alias_method :orig_read, :read
|
|
161
|
+
def read(maxlen = nil, buf = nil, buf_pos = 0)
|
|
162
|
+
return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
|
|
163
|
+
return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
|
|
164
|
+
|
|
165
|
+
buf = +''
|
|
166
|
+
len = buf.bytesize
|
|
167
|
+
while true
|
|
168
|
+
Polyphony.backend_recv(self, buf, maxlen || 4096, -1)
|
|
169
|
+
new_len = buf.bytesize
|
|
170
|
+
break if new_len == len
|
|
171
|
+
|
|
172
|
+
len = new_len
|
|
173
|
+
end
|
|
174
|
+
buf
|
|
175
|
+
end
|
|
176
|
+
|
|
143
177
|
def recv(maxlen, flags = 0, outbuf = nil)
|
|
144
|
-
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
|
178
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
|
|
145
179
|
end
|
|
146
180
|
|
|
147
|
-
def recv_loop(&block)
|
|
148
|
-
Polyphony.backend_recv_loop(self, &block)
|
|
181
|
+
def recv_loop(maxlen = 8192, &block)
|
|
182
|
+
Polyphony.backend_recv_loop(self, maxlen, &block)
|
|
149
183
|
end
|
|
150
184
|
alias_method :read_loop, :recv_loop
|
|
151
185
|
|
|
@@ -165,8 +199,8 @@ class ::TCPSocket
|
|
|
165
199
|
# Polyphony.backend_send(self, mesg, 0)
|
|
166
200
|
# end
|
|
167
201
|
|
|
168
|
-
def readpartial(maxlen, str = +'')
|
|
169
|
-
result = Polyphony.backend_recv(self, str, maxlen)
|
|
202
|
+
def readpartial(maxlen, str = +'', buffer_pos = 0)
|
|
203
|
+
result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
|
|
170
204
|
raise EOFError unless result
|
|
171
205
|
|
|
172
206
|
str
|
|
@@ -217,12 +251,29 @@ class ::UNIXServer
|
|
|
217
251
|
end
|
|
218
252
|
|
|
219
253
|
class ::UNIXSocket
|
|
254
|
+
alias_method :orig_read, :read
|
|
255
|
+
def read(maxlen = nil, buf = nil, buf_pos = 0)
|
|
256
|
+
return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
|
|
257
|
+
return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
|
|
258
|
+
|
|
259
|
+
buf = +''
|
|
260
|
+
len = buf.bytesize
|
|
261
|
+
while true
|
|
262
|
+
Polyphony.backend_recv(self, buf, maxlen || 4096, -1)
|
|
263
|
+
new_len = buf.bytesize
|
|
264
|
+
break if new_len == len
|
|
265
|
+
|
|
266
|
+
len = new_len
|
|
267
|
+
end
|
|
268
|
+
buf
|
|
269
|
+
end
|
|
270
|
+
|
|
220
271
|
def recv(maxlen, flags = 0, outbuf = nil)
|
|
221
|
-
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
|
272
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
|
|
222
273
|
end
|
|
223
274
|
|
|
224
|
-
def recv_loop(&block)
|
|
225
|
-
Polyphony.backend_recv_loop(self, &block)
|
|
275
|
+
def recv_loop(maxlen = 8192, &block)
|
|
276
|
+
Polyphony.backend_recv_loop(self, maxlen, &block)
|
|
226
277
|
end
|
|
227
278
|
alias_method :read_loop, :recv_loop
|
|
228
279
|
|
|
@@ -242,8 +293,8 @@ class ::UNIXSocket
|
|
|
242
293
|
Polyphony.backend_send(self, mesg, 0)
|
|
243
294
|
end
|
|
244
295
|
|
|
245
|
-
def readpartial(maxlen, str = +'')
|
|
246
|
-
result = Polyphony.backend_recv(self, str, maxlen)
|
|
296
|
+
def readpartial(maxlen, str = +'', buffer_pos = 0)
|
|
297
|
+
result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
|
|
247
298
|
raise EOFError unless result
|
|
248
299
|
|
|
249
300
|
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,59 @@ 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
|
+
|
|
101
|
+
def test_read_concat_big
|
|
102
|
+
i, o = IO.pipe
|
|
103
|
+
|
|
104
|
+
body = " " * 4000
|
|
105
|
+
|
|
106
|
+
data = "post /?q=time&blah=blah HTTP/1\r\nHost: dev.realiteq.net\r\n\r\n" +
|
|
107
|
+
"get /?q=time HTTP/1.1\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}" +
|
|
108
|
+
"get /?q=time HTTP/1.1\r\nCookie: foo\r\nCookie: bar\r\n\r\n"
|
|
109
|
+
|
|
110
|
+
o << data
|
|
111
|
+
o.close
|
|
112
|
+
|
|
113
|
+
buf = +''
|
|
114
|
+
|
|
115
|
+
@backend.read(i, buf, 4096, false, -1)
|
|
116
|
+
assert_equal 4096, buf.bytesize
|
|
117
|
+
|
|
118
|
+
@backend.read(i, buf, 1, false, -1)
|
|
119
|
+
assert_equal 4097, buf.bytesize
|
|
120
|
+
|
|
121
|
+
@backend.read(i, buf, 4096, false, -1)
|
|
122
|
+
|
|
123
|
+
assert_equal data.bytesize, buf.bytesize
|
|
124
|
+
assert_equal data, buf
|
|
125
|
+
end
|
|
126
|
+
|
|
74
127
|
def test_waitpid
|
|
75
128
|
pid = fork do
|
|
76
129
|
@backend.post_fork
|
|
@@ -87,7 +140,7 @@ class BackendTest < MiniTest::Test
|
|
|
87
140
|
buf = []
|
|
88
141
|
f = spin do
|
|
89
142
|
buf << :ready
|
|
90
|
-
@backend.read_loop(i) { |d| buf << d }
|
|
143
|
+
@backend.read_loop(i, 8192) { |d| buf << d }
|
|
91
144
|
buf << :done
|
|
92
145
|
end
|
|
93
146
|
|
|
@@ -107,7 +160,7 @@ class BackendTest < MiniTest::Test
|
|
|
107
160
|
parent = spin do
|
|
108
161
|
f = spin do
|
|
109
162
|
buf << :ready
|
|
110
|
-
@backend.read_loop(i) { |d| buf << d }
|
|
163
|
+
@backend.read_loop(i, 8192) { |d| buf << d }
|
|
111
164
|
buf << :done
|
|
112
165
|
end
|
|
113
166
|
suspend
|
|
@@ -125,6 +178,16 @@ class BackendTest < MiniTest::Test
|
|
|
125
178
|
assert_equal [:ready, 'foo', 'bar'], buf
|
|
126
179
|
end
|
|
127
180
|
|
|
181
|
+
def test_read_loop_with_max_len
|
|
182
|
+
r, w = IO.pipe
|
|
183
|
+
|
|
184
|
+
w << 'foobar'
|
|
185
|
+
w.close
|
|
186
|
+
buf = []
|
|
187
|
+
@backend.read_loop(r, 3) { |data| buf << data }
|
|
188
|
+
assert_equal ['foo', 'bar'], buf
|
|
189
|
+
end
|
|
190
|
+
|
|
128
191
|
Net = Polyphony::Net
|
|
129
192
|
|
|
130
193
|
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
|