polyphony 0.58 → 0.61

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/Gemfile.lock +15 -29
  4. data/examples/core/message_based_supervision.rb +51 -0
  5. data/examples/io/echo_server.rb +16 -7
  6. data/ext/polyphony/backend_common.c +160 -7
  7. data/ext/polyphony/backend_common.h +34 -2
  8. data/ext/polyphony/backend_io_uring.c +119 -40
  9. data/ext/polyphony/backend_io_uring_context.c +10 -1
  10. data/ext/polyphony/backend_io_uring_context.h +5 -3
  11. data/ext/polyphony/backend_libev.c +109 -31
  12. data/ext/polyphony/extconf.rb +2 -2
  13. data/ext/polyphony/fiber.c +1 -34
  14. data/ext/polyphony/polyphony.c +12 -19
  15. data/ext/polyphony/polyphony.h +9 -20
  16. data/ext/polyphony/polyphony_ext.c +0 -4
  17. data/ext/polyphony/queue.c +12 -12
  18. data/ext/polyphony/runqueue.c +21 -98
  19. data/ext/polyphony/runqueue.h +26 -0
  20. data/ext/polyphony/thread.c +6 -113
  21. data/lib/polyphony/core/timer.rb +2 -2
  22. data/lib/polyphony/extensions/fiber.rb +102 -82
  23. data/lib/polyphony/extensions/io.rb +10 -9
  24. data/lib/polyphony/extensions/openssl.rb +14 -4
  25. data/lib/polyphony/extensions/socket.rb +15 -15
  26. data/lib/polyphony/extensions/thread.rb +1 -1
  27. data/lib/polyphony/version.rb +1 -1
  28. data/polyphony.gemspec +0 -7
  29. data/test/test_backend.rb +46 -9
  30. data/test/test_ext.rb +1 -1
  31. data/test/test_fiber.rb +106 -18
  32. data/test/test_global_api.rb +1 -1
  33. data/test/test_io.rb +29 -0
  34. data/test/test_supervise.rb +100 -100
  35. data/test/test_thread.rb +5 -11
  36. data/test/test_thread_pool.rb +1 -1
  37. data/test/test_trace.rb +28 -49
  38. metadata +5 -109
  39. data/ext/polyphony/tracing.c +0 -11
  40. data/lib/polyphony/adapters/trace.rb +0 -138
@@ -372,7 +372,7 @@ class SpinScopeTest < MiniTest::Test
372
372
  rescue => e
373
373
  buffer << e.message
374
374
  end
375
- 6.times { snooze }
375
+ 10.times { snooze }
376
376
  assert_equal 0, Fiber.current.children.size
377
377
  assert_equal ['foobar'], buffer
378
378
  end
data/test/test_io.rb CHANGED
@@ -416,4 +416,33 @@ class IOClassMethodsTest < MiniTest::Test
416
416
  assert_equal "foo\nbar\n", pipe_read { |f| f.puts 'foo', 'bar' }
417
417
  assert_equal "foo\nbar\n", pipe_read { |f| f.puts 'foo', "bar\n" }
418
418
  end
419
+
420
+ def test_read_loop
421
+ i, o = IO.pipe
422
+
423
+ buf = []
424
+ f = spin do
425
+ buf << :ready
426
+ i.read_loop { |d| buf << d }
427
+ buf << :done
428
+ end
429
+
430
+ # writing always causes snoozing
431
+ o << 'foo'
432
+ o << 'bar'
433
+ o.close
434
+
435
+ f.await
436
+ assert_equal [:ready, 'foo', 'bar', :done], buf
437
+ end
438
+
439
+ def test_read_loop_with_max_len
440
+ r, w = IO.pipe
441
+
442
+ w << 'foobar'
443
+ w.close
444
+ buf = []
445
+ r.read_loop(3) { |data| buf << data }
446
+ assert_equal ['foo', 'bar'], buf
447
+ end
419
448
  end
@@ -2,103 +2,103 @@
2
2
 
3
3
  require_relative 'helper'
4
4
 
5
- class SuperviseTest < MiniTest::Test
6
- def test_supervise
7
- p = spin { supervise }
8
- snooze
9
- f1 = p.spin { receive }
10
- f2 = p.spin { receive }
11
-
12
- snooze
13
- assert_equal p.state, :waiting
14
- f1 << 'foo'
15
- f1.await
16
- snooze
17
-
18
- assert_equal :waiting, p.state
19
- assert_equal :waiting, f2.state
20
-
21
- f2 << 'bar'
22
- f2.await
23
- assert_equal :runnable, p.state
24
- snooze
25
-
26
- assert_equal :dead, p.state
27
- end
28
-
29
- def test_supervise_with_restart
30
- watcher = spin { receive }
31
- parent = spin { supervise(restart: true, watcher: watcher) }
32
- snooze
33
-
34
- buffer = []
35
- f1 = parent.spin do
36
- buffer << 'f1'
37
- end
38
-
39
- f1.await
40
- assert_equal ['f1'], buffer
41
- watcher.await
42
- assert_equal ['f1', 'f1'], buffer
43
- end
44
-
45
- def test_supervise_with_restart_on_error
46
- parent = spin { supervise(restart: true) }
47
- snooze
48
-
49
- buffer = []
50
- f1 = parent.spin do
51
- buffer << 'f1'
52
- buffer << receive
53
- end
54
-
55
- snooze
56
- assert_equal ['f1'], buffer
57
-
58
- f1.raise 'foo'
59
-
60
- 3.times { snooze }
61
-
62
- assert_equal ['f1', 'f1'], buffer
63
- assert_equal :dead, f1.state
64
-
65
- # f1 should have been restarted by supervisor
66
- f1 = parent.children.first
67
- assert_kind_of Fiber, f1
68
-
69
- f1 << 'foo'
70
- f1.await
71
-
72
- assert_equal ['f1', 'f1', 'foo'], buffer
73
- end
74
-
75
- def test_supervisor_termination
76
- f = nil
77
- p = spin do
78
- f = spin { sleep 1 }
79
- supervise
80
- end
81
- sleep 0.01
82
-
83
- p.terminate
84
- p.await
85
-
86
- assert :dead, f.state
87
- assert :dead, p.state
88
- end
89
-
90
- def test_supervisor_termination_with_restart
91
- f = nil
92
- p = spin do
93
- f = spin { sleep 1 }
94
- supervise(restart: true)
95
- end
96
- sleep 0.01
97
-
98
- p.terminate
99
- p.await
100
-
101
- assert :dead, f.state
102
- assert :dead, p.state
103
- end
104
- end
5
+ # class SuperviseTest < MiniTest::Test
6
+ # def test_supervise
7
+ # p = spin { supervise }
8
+ # snooze
9
+ # f1 = p.spin { receive }
10
+ # f2 = p.spin { receive }
11
+
12
+ # snooze
13
+ # assert_equal p.state, :waiting
14
+ # f1 << 'foo'
15
+ # f1.await
16
+ # snooze
17
+
18
+ # assert_equal :waiting, p.state
19
+ # assert_equal :waiting, f2.state
20
+
21
+ # f2 << 'bar'
22
+ # f2.await
23
+ # assert_equal :runnable, p.state
24
+
25
+ # 3.times { snooze }
26
+ # assert_equal :dead, p.state
27
+ # end
28
+
29
+ # def test_supervise_with_restart
30
+ # watcher = spin { receive }
31
+ # parent = spin { supervise(restart: true, watcher: watcher) }
32
+ # snooze
33
+
34
+ # buffer = []
35
+ # f1 = parent.spin do
36
+ # buffer << 'f1'
37
+ # end
38
+
39
+ # f1.await
40
+ # assert_equal ['f1'], buffer
41
+ # watcher.await
42
+ # assert_equal ['f1', 'f1'], buffer
43
+ # end
44
+
45
+ # def test_supervise_with_restart_on_error
46
+ # parent = spin { supervise(restart: true) }
47
+ # snooze
48
+
49
+ # buffer = []
50
+ # f1 = parent.spin do
51
+ # buffer << 'f1'
52
+ # buffer << receive
53
+ # end
54
+
55
+ # snooze
56
+ # assert_equal ['f1'], buffer
57
+
58
+ # f1.raise 'foo'
59
+
60
+ # 3.times { snooze }
61
+
62
+ # assert_equal ['f1', 'f1'], buffer
63
+ # assert_equal :dead, f1.state
64
+
65
+ # # f1 should have been restarted by supervisor
66
+ # f1 = parent.children.first
67
+ # assert_kind_of Fiber, f1
68
+
69
+ # f1 << 'foo'
70
+ # f1.await
71
+
72
+ # assert_equal ['f1', 'f1', 'foo'], buffer
73
+ # end
74
+
75
+ # def test_supervisor_termination
76
+ # f = nil
77
+ # p = spin do
78
+ # f = spin { sleep 1 }
79
+ # supervise
80
+ # end
81
+ # sleep 0.01
82
+
83
+ # p.terminate
84
+ # p.await
85
+
86
+ # assert :dead, f.state
87
+ # assert :dead, p.state
88
+ # end
89
+
90
+ # def test_supervisor_termination_with_restart
91
+ # f = nil
92
+ # p = spin do
93
+ # f = spin { sleep 1 }
94
+ # supervise(restart: true)
95
+ # end
96
+ # sleep 0.01
97
+
98
+ # p.terminate
99
+ # p.await
100
+
101
+ # assert :dead, f.state
102
+ # assert :dead, p.state
103
+ # end
104
+ # end
data/test/test_thread.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
- require 'polyphony/adapters/trace'
5
4
 
6
5
  class ThreadTest < MiniTest::Test
7
6
  def test_thread_spin
@@ -130,18 +129,13 @@ class ThreadTest < MiniTest::Test
130
129
 
131
130
  def test_that_suspend_returns_immediately_if_no_watchers
132
131
  records = []
133
- t = Polyphony::Trace.new(:fiber_all) do |r|
134
- records << r if r[:event] =~ /^fiber_/
135
- end
136
- t.enable
137
- Polyphony.trace(true)
138
-
132
+ Thread.backend.trace_proc = proc {|*r| records << r }
139
133
  suspend
140
- t.disable
141
- assert_equal [:fiber_switchpoint], records.map { |r| r[:event] }
134
+ assert_equal [
135
+ [:fiber_switchpoint, Fiber.current]
136
+ ], records
142
137
  ensure
143
- t&.disable
144
- Polyphony.trace(false)
138
+ Thread.backend.trace_proc = nil
145
139
  end
146
140
 
147
141
  def test_thread_child_fiber_termination
@@ -68,7 +68,7 @@ class ThreadPoolTest < MiniTest::Test
68
68
  assert_in_range 0.0..0.009, elapsed
69
69
  assert buffer.size < 2
70
70
 
71
- sleep 0.1 # allow time for threads to spawn
71
+ sleep 0.15 # allow time for threads to spawn
72
72
  assert_equal @pool.size, threads.uniq.size
73
73
  assert_equal (0..9).to_a, buffer.sort
74
74
  end
data/test/test_trace.rb CHANGED
@@ -1,70 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
- require 'polyphony/adapters/trace'
5
4
 
6
5
  class TraceTest < MiniTest::Test
7
- def test_tracing_disabled
8
- records = []
9
- t = Polyphony::Trace.new { |r| records << r if r[:event] =~ /^fiber_/ }
10
- t.enable
11
- snooze
12
- assert_equal 0, records.size
13
- ensure
14
- t&.disable
15
- Polyphony.trace(nil)
16
- end
17
-
18
6
  def test_tracing_enabled
19
- records = []
20
- t = Polyphony::Trace.new(:fiber_all) { |r| records << r if r[:event] =~ /^fiber_/ }
21
- Polyphony.trace(true)
22
- t.enable
7
+ events = []
8
+ Thread.backend.trace_proc = proc { |*e| events << e }
23
9
  snooze
24
- t.disable
25
10
 
26
- assert_equal 3, records.size
27
- events = records.map { |r| r[:event] }
28
- assert_equal [:fiber_schedule, :fiber_switchpoint, :fiber_run], events
29
- assert_equal [Fiber.current], records.map { |r| r[:fiber] }.uniq
11
+ assert_equal [
12
+ [:fiber_schedule, Fiber.current, nil, false],
13
+ [:fiber_switchpoint, Fiber.current],
14
+ [:fiber_run, Fiber.current, nil]
15
+ ], events
30
16
  ensure
31
- t&.disable
32
- Polyphony.trace(nil)
17
+ Thread.backend.trace_proc = nil
33
18
  end
34
19
 
35
20
  def test_2_fiber_trace
36
- records = []
37
- thread = Thread.current
38
- t = Polyphony::Trace.new(:fiber_all) do |r|
39
- records << r if Thread.current == thread && r[:event] =~ /^fiber_/
40
- end
41
- t.enable
42
- Polyphony.trace(true)
21
+ events = []
22
+ Thread.backend.trace_proc = proc { |*e| events << e }
43
23
 
44
- f = spin { sleep 0 }
24
+ f = spin { sleep 0; :byebye }
45
25
  suspend
46
26
  sleep 0
47
27
 
48
- events = records.map { |r| [r[:fiber] == f ? :f : :current, r[:event]] }
49
28
  assert_equal [
50
- [:f, :fiber_create],
51
- [:f, :fiber_schedule],
52
- [:current, :fiber_switchpoint],
53
- [:f, :fiber_run],
54
- [:f, :fiber_switchpoint],
55
- [:f, :fiber_event_poll_enter],
56
- [:f, :fiber_schedule],
57
- [:f, :fiber_event_poll_leave],
58
- [:f, :fiber_run],
59
- [:f, :fiber_terminate],
60
- [:current, :fiber_switchpoint],
61
- [:current, :fiber_event_poll_enter],
62
- [:current, :fiber_schedule],
63
- [:current, :fiber_event_poll_leave],
64
- [:current, :fiber_run]
29
+ [:fiber_create, f],
30
+ [:fiber_schedule, f, nil, false],
31
+ [:fiber_switchpoint, Fiber.current],
32
+ [:fiber_run, f, nil],
33
+ [:fiber_switchpoint, f],
34
+ [:fiber_event_poll_enter, f],
35
+ [:fiber_schedule, f, nil, false],
36
+ [:fiber_event_poll_leave, f],
37
+ [:fiber_run, f, nil],
38
+ [:fiber_terminate, f, :byebye],
39
+ [:fiber_switchpoint, f],
40
+ [:fiber_switchpoint, Fiber.current],
41
+ [:fiber_event_poll_enter, Fiber.current],
42
+ [:fiber_schedule, Fiber.current, nil, false],
43
+ [:fiber_event_poll_leave, Fiber.current],
44
+ [:fiber_run, Fiber.current, nil]
65
45
  ], events
66
46
  ensure
67
- t&.disable
68
- Polyphony.trace(nil)
47
+ Thread.backend.trace_proc = nil
69
48
  end
70
49
  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.58'
4
+ version: '0.61'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-25 00:00:00.000000000 Z
11
+ date: 2021-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -108,110 +108,6 @@ dependencies:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
110
  version: 1.4.2
111
- - !ruby/object:Gem::Dependency
112
- name: pg
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - '='
116
- - !ruby/object:Gem::Version
117
- version: 1.1.4
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - '='
123
- - !ruby/object:Gem::Version
124
- version: 1.1.4
125
- - !ruby/object:Gem::Dependency
126
- name: redis
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - '='
130
- - !ruby/object:Gem::Version
131
- version: 4.1.0
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - '='
137
- - !ruby/object:Gem::Version
138
- version: 4.1.0
139
- - !ruby/object:Gem::Dependency
140
- name: hiredis
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - '='
144
- - !ruby/object:Gem::Version
145
- version: 0.6.3
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - '='
151
- - !ruby/object:Gem::Version
152
- version: 0.6.3
153
- - !ruby/object:Gem::Dependency
154
- name: http_parser.rb
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: 0.6.0
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: 0.6.0
167
- - !ruby/object:Gem::Dependency
168
- name: rack
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- version: 2.0.8
174
- - - "<"
175
- - !ruby/object:Gem::Version
176
- version: 2.3.0
177
- type: :development
178
- prerelease: false
179
- version_requirements: !ruby/object:Gem::Requirement
180
- requirements:
181
- - - ">="
182
- - !ruby/object:Gem::Version
183
- version: 2.0.8
184
- - - "<"
185
- - !ruby/object:Gem::Version
186
- version: 2.3.0
187
- - !ruby/object:Gem::Dependency
188
- name: mysql2
189
- requirement: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - '='
192
- - !ruby/object:Gem::Version
193
- version: 0.5.3
194
- type: :development
195
- prerelease: false
196
- version_requirements: !ruby/object:Gem::Requirement
197
- requirements:
198
- - - '='
199
- - !ruby/object:Gem::Version
200
- version: 0.5.3
201
- - !ruby/object:Gem::Dependency
202
- name: sequel
203
- requirement: !ruby/object:Gem::Requirement
204
- requirements:
205
- - - '='
206
- - !ruby/object:Gem::Version
207
- version: 5.34.0
208
- type: :development
209
- prerelease: false
210
- version_requirements: !ruby/object:Gem::Requirement
211
- requirements:
212
- - - '='
213
- - !ruby/object:Gem::Version
214
- version: 5.34.0
215
111
  - !ruby/object:Gem::Dependency
216
112
  name: httparty
217
113
  requirement: !ruby/object:Gem::Requirement
@@ -326,6 +222,7 @@ files:
326
222
  - examples/core/handling-signals.rb
327
223
  - examples/core/idle_gc.rb
328
224
  - examples/core/interrupt.rb
225
+ - examples/core/message_based_supervision.rb
329
226
  - examples/core/nested.rb
330
227
  - examples/core/pingpong.rb
331
228
  - examples/core/queue.rb
@@ -437,11 +334,11 @@ files:
437
334
  - ext/polyphony/ring_buffer.c
438
335
  - ext/polyphony/ring_buffer.h
439
336
  - ext/polyphony/runqueue.c
337
+ - ext/polyphony/runqueue.h
440
338
  - ext/polyphony/runqueue_ring_buffer.c
441
339
  - ext/polyphony/runqueue_ring_buffer.h
442
340
  - ext/polyphony/socket_extensions.c
443
341
  - ext/polyphony/thread.c
444
- - ext/polyphony/tracing.c
445
342
  - lib/polyphony.rb
446
343
  - lib/polyphony/adapters/fs.rb
447
344
  - lib/polyphony/adapters/irb.rb
@@ -451,7 +348,6 @@ files:
451
348
  - lib/polyphony/adapters/readline.rb
452
349
  - lib/polyphony/adapters/redis.rb
453
350
  - lib/polyphony/adapters/sequel.rb
454
- - lib/polyphony/adapters/trace.rb
455
351
  - lib/polyphony/core/channel.rb
456
352
  - lib/polyphony/core/exceptions.rb
457
353
  - lib/polyphony/core/global_api.rb
@@ -523,7 +419,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
523
419
  - !ruby/object:Gem::Version
524
420
  version: '0'
525
421
  requirements: []
526
- rubygems_version: 3.1.4
422
+ rubygems_version: 3.1.6
527
423
  signing_key:
528
424
  specification_version: 4
529
425
  summary: Fine grained concurrency for Ruby