polyphony 0.45.1 → 0.46.1

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -0
  3. data/.gitmodules +0 -0
  4. data/CHANGELOG.md +35 -0
  5. data/Gemfile.lock +3 -3
  6. data/README.md +3 -3
  7. data/Rakefile +1 -1
  8. data/TODO.md +20 -14
  9. data/bin/test +4 -0
  10. data/examples/io/raw.rb +14 -0
  11. data/examples/io/reline.rb +18 -0
  12. data/examples/performance/fiber_transfer.rb +13 -4
  13. data/examples/performance/multi_snooze.rb +0 -1
  14. data/examples/performance/thread-vs-fiber/polyphony_server.rb +8 -20
  15. data/ext/liburing/liburing.h +585 -0
  16. data/ext/liburing/liburing/README.md +4 -0
  17. data/ext/liburing/liburing/barrier.h +73 -0
  18. data/ext/liburing/liburing/compat.h +15 -0
  19. data/ext/liburing/liburing/io_uring.h +343 -0
  20. data/ext/liburing/queue.c +333 -0
  21. data/ext/liburing/register.c +187 -0
  22. data/ext/liburing/setup.c +210 -0
  23. data/ext/liburing/syscall.c +54 -0
  24. data/ext/liburing/syscall.h +18 -0
  25. data/ext/polyphony/backend.h +1 -15
  26. data/ext/polyphony/backend_common.h +120 -0
  27. data/ext/polyphony/backend_io_uring.c +919 -0
  28. data/ext/polyphony/backend_io_uring_context.c +73 -0
  29. data/ext/polyphony/backend_io_uring_context.h +52 -0
  30. data/ext/polyphony/{libev_backend.c → backend_libev.c} +241 -297
  31. data/ext/polyphony/event.c +1 -1
  32. data/ext/polyphony/extconf.rb +31 -13
  33. data/ext/polyphony/fiber.c +107 -28
  34. data/ext/polyphony/libev.c +4 -0
  35. data/ext/polyphony/libev.h +8 -2
  36. data/ext/polyphony/liburing.c +8 -0
  37. data/ext/polyphony/playground.c +51 -0
  38. data/ext/polyphony/polyphony.c +6 -6
  39. data/ext/polyphony/polyphony.h +34 -14
  40. data/ext/polyphony/polyphony_ext.c +12 -4
  41. data/ext/polyphony/queue.c +1 -1
  42. data/ext/polyphony/runqueue.c +102 -0
  43. data/ext/polyphony/runqueue_ring_buffer.c +85 -0
  44. data/ext/polyphony/runqueue_ring_buffer.h +31 -0
  45. data/ext/polyphony/thread.c +42 -90
  46. data/lib/polyphony.rb +2 -2
  47. data/lib/polyphony/adapters/process.rb +0 -3
  48. data/lib/polyphony/adapters/trace.rb +2 -2
  49. data/lib/polyphony/core/exceptions.rb +0 -4
  50. data/lib/polyphony/core/global_api.rb +13 -11
  51. data/lib/polyphony/core/sync.rb +7 -5
  52. data/lib/polyphony/extensions/core.rb +14 -33
  53. data/lib/polyphony/extensions/debug.rb +13 -0
  54. data/lib/polyphony/extensions/fiber.rb +21 -44
  55. data/lib/polyphony/extensions/io.rb +15 -4
  56. data/lib/polyphony/extensions/openssl.rb +6 -0
  57. data/lib/polyphony/extensions/socket.rb +63 -10
  58. data/lib/polyphony/version.rb +1 -1
  59. data/polyphony.gemspec +1 -1
  60. data/test/helper.rb +36 -4
  61. data/test/io_uring_test.rb +55 -0
  62. data/test/stress.rb +4 -1
  63. data/test/test_backend.rb +15 -6
  64. data/test/test_ext.rb +1 -2
  65. data/test/test_fiber.rb +31 -24
  66. data/test/test_global_api.rb +71 -31
  67. data/test/test_io.rb +42 -0
  68. data/test/test_queue.rb +1 -1
  69. data/test/test_signal.rb +11 -8
  70. data/test/test_socket.rb +2 -2
  71. data/test/test_sync.rb +21 -0
  72. data/test/test_throttler.rb +3 -7
  73. data/test/test_trace.rb +7 -5
  74. metadata +31 -6
@@ -92,6 +92,48 @@ class IOTest < MiniTest::Test
92
92
  assert_raises(EOFError) { i.readpartial(1) }
93
93
  end
94
94
 
95
+ def test_getc
96
+ i, o = IO.pipe
97
+
98
+ buf = []
99
+ f = spin do
100
+ while (c = i.getc)
101
+ buf << c
102
+ end
103
+ end
104
+
105
+ snooze
106
+ assert_equal [], buf
107
+
108
+ o << 'f'
109
+ snooze
110
+ o << 'g'
111
+ o.close
112
+ f.await
113
+ assert_equal ['f', 'g'], buf
114
+ end
115
+
116
+ def test_getbyte
117
+ i, o = IO.pipe
118
+
119
+ buf = []
120
+ f = spin do
121
+ while (b = i.getbyte)
122
+ buf << b
123
+ end
124
+ end
125
+
126
+ snooze
127
+ assert_equal [], buf
128
+
129
+ o << 'f'
130
+ snooze
131
+ o << 'g'
132
+ o.close
133
+ f.await
134
+ assert_equal [102, 103], buf
135
+ end
136
+
95
137
  # see https://github.com/digital-fabric/polyphony/issues/30
96
138
  def test_reopened_tempfile
97
139
  file = Tempfile.new
@@ -129,4 +129,4 @@ class QueueTest < MiniTest::Test
129
129
 
130
130
  assert_equal 0, @queue.size
131
131
  end
132
- end
132
+ end
@@ -3,18 +3,21 @@
3
3
  require_relative 'helper'
4
4
 
5
5
  class SignalTrapTest < Minitest::Test
6
+ def test_int_signal
7
+ Thread.new { sleep 0.001; Process.kill('INT', Process.pid) }
8
+ assert_raises(Interrupt) { sleep 5 }
9
+ end
10
+
11
+ def test_term_signal
12
+ Thread.new { sleep 0.001; Process.kill('TERM', Process.pid) }
13
+ assert_raises(SystemExit) { sleep 5 }
14
+ end
15
+
6
16
  def test_signal_exception_handling
7
17
  i, o = IO.pipe
8
18
  pid = Polyphony.fork do
9
19
  i.close
10
- spin do
11
- spin do
12
- sleep 5
13
- rescue ::Interrupt => e
14
- # the signal should be raised only in the main fiber
15
- o.puts "1-interrupt"
16
- end.await
17
- end.await
20
+ sleep 5
18
21
  rescue ::Interrupt => e
19
22
  o.puts "3-interrupt"
20
23
  ensure
@@ -40,12 +40,12 @@ class HTTPClientTest < MiniTest::Test
40
40
  def test_http
41
41
  res = HTTParty.get('http://worldtimeapi.org/api/timezone/Europe/Paris')
42
42
  response = JSON.load(res.body)
43
- assert_equal "CEST", response['abbreviation']
43
+ assert_equal "CET", response['abbreviation']
44
44
  end
45
45
 
46
46
  def test_https
47
47
  res = HTTParty.get('https://worldtimeapi.org/api/timezone/Europe/Paris')
48
48
  response = JSON.load(res.body)
49
- assert_equal "CEST", response['abbreviation']
49
+ assert_equal "CET", response['abbreviation']
50
50
  end
51
51
  end
@@ -20,6 +20,27 @@ class MutexTest < MiniTest::Test
20
20
  assert_equal ['>> 1', '<< 1', '>> 2', '<< 2', '>> 3', '<< 3'], buf
21
21
  end
22
22
 
23
+ def test_mutex_race_condition
24
+ lock = Polyphony::Mutex.new
25
+ buf = []
26
+ f1 = spin do
27
+ lock.synchronize { buf << 1; snooze; lock.synchronize { buf << 1.1 }; snooze }
28
+ end
29
+ f2 = spin do
30
+ lock.synchronize { buf << 2 }
31
+ end
32
+ f3 = spin do
33
+ lock.synchronize { buf << 3 }
34
+ end
35
+
36
+ snooze
37
+ f2.terminate
38
+
39
+ f3.await
40
+
41
+ assert_equal [1, 1.1, 3], buf
42
+ end
43
+
23
44
  def test_condition_variable
24
45
  buf = []
25
46
  lock1 = Polyphony::Mutex.new
@@ -10,10 +10,7 @@ class ThrottlerTest < MiniTest::Test
10
10
  f = spin { loop { t.process { buffer << 1 } } }
11
11
  sleep 0.2
12
12
  f.stop
13
- elapsed = Time.now - t0
14
- expected = (elapsed * 10).to_i
15
- STDOUT.orig_write "xxxxxxxx #{[elapsed, expected].inspect}\n"
16
- assert buffer.size >= expected - 1 && buffer.size <= expected + 1
13
+ assert_in_range 1..3, buffer.size
17
14
  ensure
18
15
  t.stop
19
16
  end
@@ -26,7 +23,7 @@ class ThrottlerTest < MiniTest::Test
26
23
  end
27
24
  sleep 0.25
28
25
  f.stop
29
- assert (2..6).include?(buffer.size)
26
+ assert_in_range 2..6, buffer.size
30
27
  ensure
31
28
  t.stop
32
29
  end
@@ -37,8 +34,7 @@ class ThrottlerTest < MiniTest::Test
37
34
  f = spin { loop { t.process { buffer << 1 } } }
38
35
  sleep 0.02
39
36
  f.stop
40
- assert buffer.size >= 2
41
- assert buffer.size <= 3
37
+ assert_in_range 2..3, buffer.size
42
38
  ensure
43
39
  t.stop
44
40
  end
@@ -35,7 +35,9 @@ class TraceTest < MiniTest::Test
35
35
  def test_2_fiber_trace
36
36
  records = []
37
37
  thread = Thread.current
38
- t = Polyphony::Trace.new(:fiber_all) { |r| records << r if Thread.current == thread && r[:event] =~ /^fiber_/ }
38
+ t = Polyphony::Trace.new(:fiber_all) do |r|
39
+ records << r if Thread.current == thread && r[:event] =~ /^fiber_/
40
+ end
39
41
  t.enable
40
42
  Polyphony.trace(true)
41
43
 
@@ -50,15 +52,15 @@ class TraceTest < MiniTest::Test
50
52
  [:current, :fiber_switchpoint],
51
53
  [:f, :fiber_run],
52
54
  [:f, :fiber_switchpoint],
53
- [:f, :fiber_ev_loop_enter],
55
+ [:f, :fiber_event_poll_enter],
54
56
  [:f, :fiber_schedule],
55
- [:f, :fiber_ev_loop_leave],
57
+ [:f, :fiber_event_poll_leave],
56
58
  [:f, :fiber_run],
57
59
  [:f, :fiber_terminate],
58
60
  [:current, :fiber_switchpoint],
59
- [:current, :fiber_ev_loop_enter],
61
+ [:current, :fiber_event_poll_enter],
60
62
  [:current, :fiber_schedule],
61
- [:current, :fiber_ev_loop_leave],
63
+ [:current, :fiber_event_poll_leave],
62
64
  [:current, :fiber_run]
63
65
  ], events
64
66
  ensure
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.45.1
4
+ version: 0.46.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-01 00:00:00.000000000 Z
11
+ date: 2020-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.5
19
+ version: 1.1.1
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 1.0.5
26
+ version: 1.1.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -278,6 +278,7 @@ extra_rdoc_files:
278
278
  files:
279
279
  - ".github/workflows/test.yml"
280
280
  - ".gitignore"
281
+ - ".gitmodules"
281
282
  - ".rubocop.yml"
282
283
  - ".vscode/launch.json"
283
284
  - CHANGELOG.md
@@ -289,6 +290,7 @@ files:
289
290
  - TODO.md
290
291
  - bin/polyphony-debug
291
292
  - bin/stress.rb
293
+ - bin/test
292
294
  - docs/_config.yml
293
295
  - docs/_includes/head.html
294
296
  - docs/_includes/title.html
@@ -377,6 +379,8 @@ files:
377
379
  - examples/io/open.rb
378
380
  - examples/io/pry.rb
379
381
  - examples/io/rack_server.rb
382
+ - examples/io/raw.rb
383
+ - examples/io/reline.rb
380
384
  - examples/io/system.rb
381
385
  - examples/io/tcpserver.rb
382
386
  - examples/io/tcpsocket.rb
@@ -413,19 +417,38 @@ files:
413
417
  - ext/libev/ev_win32.c
414
418
  - ext/libev/ev_wrap.h
415
419
  - ext/libev/test_libev_win32.c
420
+ - ext/liburing/liburing.h
421
+ - ext/liburing/liburing/README.md
422
+ - ext/liburing/liburing/barrier.h
423
+ - ext/liburing/liburing/compat.h
424
+ - ext/liburing/liburing/io_uring.h
425
+ - ext/liburing/queue.c
426
+ - ext/liburing/register.c
427
+ - ext/liburing/setup.c
428
+ - ext/liburing/syscall.c
429
+ - ext/liburing/syscall.h
416
430
  - ext/polyphony/backend.h
431
+ - ext/polyphony/backend_common.h
432
+ - ext/polyphony/backend_io_uring.c
433
+ - ext/polyphony/backend_io_uring_context.c
434
+ - ext/polyphony/backend_io_uring_context.h
435
+ - ext/polyphony/backend_libev.c
417
436
  - ext/polyphony/event.c
418
437
  - ext/polyphony/extconf.rb
419
438
  - ext/polyphony/fiber.c
420
439
  - ext/polyphony/libev.c
421
440
  - ext/polyphony/libev.h
422
- - ext/polyphony/libev_backend.c
441
+ - ext/polyphony/liburing.c
442
+ - ext/polyphony/playground.c
423
443
  - ext/polyphony/polyphony.c
424
444
  - ext/polyphony/polyphony.h
425
445
  - ext/polyphony/polyphony_ext.c
426
446
  - ext/polyphony/queue.c
427
447
  - ext/polyphony/ring_buffer.c
428
448
  - ext/polyphony/ring_buffer.h
449
+ - ext/polyphony/runqueue.c
450
+ - ext/polyphony/runqueue_ring_buffer.c
451
+ - ext/polyphony/runqueue_ring_buffer.h
429
452
  - ext/polyphony/thread.c
430
453
  - ext/polyphony/tracing.c
431
454
  - lib/polyphony.rb
@@ -446,6 +469,7 @@ files:
446
469
  - lib/polyphony/core/thread_pool.rb
447
470
  - lib/polyphony/core/throttler.rb
448
471
  - lib/polyphony/extensions/core.rb
472
+ - lib/polyphony/extensions/debug.rb
449
473
  - lib/polyphony/extensions/fiber.rb
450
474
  - lib/polyphony/extensions/io.rb
451
475
  - lib/polyphony/extensions/openssl.rb
@@ -457,6 +481,7 @@ files:
457
481
  - test/coverage.rb
458
482
  - test/eg.rb
459
483
  - test/helper.rb
484
+ - test/io_uring_test.rb
460
485
  - test/q.rb
461
486
  - test/run.rb
462
487
  - test/stress.rb
@@ -505,7 +530,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
505
530
  - !ruby/object:Gem::Version
506
531
  version: '0'
507
532
  requirements: []
508
- rubygems_version: 3.1.2
533
+ rubygems_version: 3.1.4
509
534
  signing_key:
510
535
  specification_version: 4
511
536
  summary: Fine grained concurrency for Ruby