polyphony 0.59.1 → 0.63

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- data = readpartial(8192, +'')
155
- return nil unless data
156
- @read_buffer << data
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
- def readpartial(maxlen, buf = +'')
68
- result = sysread(maxlen, buf)
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(8192))
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.59.1'
4
+ VERSION = '0.63'
5
5
  end
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
- assert_in_delta 0.03, Time.now - t0, 0.01
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
@@ -42,7 +42,7 @@ class ExceptionTest < MiniTest::Test
42
42
  end
43
43
 
44
44
  class ProcessTest < MiniTest::Test
45
- def test_detach
45
+ def test_process_detach
46
46
  pid = Polyphony.fork { sleep 0.05; exit! 42 }
47
47
  buffer = []
48
48
  spin { 3.times { |i| buffer << i; snooze } }
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
- CMD_TERMINATE_MAIN_FIBER = <<~BASH
352
- ruby -rbundler/setup -rpolyphony -e"spin { sleep 0.1; Thread.current.main_fiber.terminate }; begin; sleep; rescue Polyphony::Terminate; STDOUT << 'terminated'; end" 2>&1
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
- CMD_TERMINATE_CHILD_FIBER = <<~BASH
356
- ruby -rbundler/setup -rpolyphony -e"f = spin { sleep }; spin { sleep 0.1; f.terminate }; f.await" 2>&1
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 test_when_done
551
- flag = nil
552
- values = []
553
- f = spin do
554
- snooze until flag
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
- assert values.empty?
560
- snooze
561
- flag = true
562
- assert values.empty?
563
- assert f.alive?
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
- assert_equal [42], values
567
- assert !f.running?
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 :dead, f2.state
1055
+ assert_equal :waiting, f2.state
968
1056
  end
969
1057
 
970
1058
  def test_select_with_interruption