polyphony 0.43.8

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 (221) hide show
  1. checksums.yaml +7 -0
  2. data/.gitbook.yaml +4 -0
  3. data/.github/workflows/test.yml +29 -0
  4. data/.gitignore +59 -0
  5. data/.rubocop.yml +175 -0
  6. data/CHANGELOG.md +393 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +141 -0
  9. data/LICENSE +21 -0
  10. data/README.md +51 -0
  11. data/Rakefile +26 -0
  12. data/TODO.md +201 -0
  13. data/bin/polyphony-debug +87 -0
  14. data/docs/_config.yml +64 -0
  15. data/docs/_includes/head.html +40 -0
  16. data/docs/_includes/title.html +1 -0
  17. data/docs/_sass/custom/custom.scss +10 -0
  18. data/docs/_sass/overrides.scss +0 -0
  19. data/docs/_user-guide/all-about-timers.md +126 -0
  20. data/docs/_user-guide/index.md +9 -0
  21. data/docs/_user-guide/web-server.md +136 -0
  22. data/docs/api-reference/exception.md +27 -0
  23. data/docs/api-reference/fiber.md +425 -0
  24. data/docs/api-reference/index.md +9 -0
  25. data/docs/api-reference/io.md +36 -0
  26. data/docs/api-reference/object.md +99 -0
  27. data/docs/api-reference/polyphony-baseexception.md +33 -0
  28. data/docs/api-reference/polyphony-cancel.md +26 -0
  29. data/docs/api-reference/polyphony-moveon.md +24 -0
  30. data/docs/api-reference/polyphony-net.md +20 -0
  31. data/docs/api-reference/polyphony-process.md +28 -0
  32. data/docs/api-reference/polyphony-resourcepool.md +59 -0
  33. data/docs/api-reference/polyphony-restart.md +18 -0
  34. data/docs/api-reference/polyphony-terminate.md +18 -0
  35. data/docs/api-reference/polyphony-threadpool.md +67 -0
  36. data/docs/api-reference/polyphony-throttler.md +77 -0
  37. data/docs/api-reference/polyphony.md +36 -0
  38. data/docs/api-reference/thread.md +88 -0
  39. data/docs/assets/img/echo-fibers.svg +1 -0
  40. data/docs/assets/img/sleeping-fiber.svg +1 -0
  41. data/docs/faq.md +195 -0
  42. data/docs/favicon.ico +0 -0
  43. data/docs/getting-started/index.md +10 -0
  44. data/docs/getting-started/installing.md +34 -0
  45. data/docs/getting-started/overview.md +486 -0
  46. data/docs/getting-started/tutorial.md +359 -0
  47. data/docs/index.md +94 -0
  48. data/docs/main-concepts/concurrency.md +151 -0
  49. data/docs/main-concepts/design-principles.md +161 -0
  50. data/docs/main-concepts/exception-handling.md +291 -0
  51. data/docs/main-concepts/extending.md +89 -0
  52. data/docs/main-concepts/fiber-scheduling.md +197 -0
  53. data/docs/main-concepts/index.md +9 -0
  54. data/docs/polyphony-logo.png +0 -0
  55. data/examples/adapters/concurrent-ruby.rb +9 -0
  56. data/examples/adapters/pg_client.rb +36 -0
  57. data/examples/adapters/pg_notify.rb +35 -0
  58. data/examples/adapters/pg_pool.rb +43 -0
  59. data/examples/adapters/pg_transaction.rb +31 -0
  60. data/examples/adapters/redis_blpop.rb +12 -0
  61. data/examples/adapters/redis_channels.rb +122 -0
  62. data/examples/adapters/redis_client.rb +19 -0
  63. data/examples/adapters/redis_pubsub.rb +26 -0
  64. data/examples/adapters/redis_pubsub_perf.rb +68 -0
  65. data/examples/core/01-spinning-up-fibers.rb +18 -0
  66. data/examples/core/02-awaiting-fibers.rb +20 -0
  67. data/examples/core/03-interrupting.rb +39 -0
  68. data/examples/core/04-handling-signals.rb +19 -0
  69. data/examples/core/xx-agent.rb +102 -0
  70. data/examples/core/xx-at_exit.rb +29 -0
  71. data/examples/core/xx-caller.rb +12 -0
  72. data/examples/core/xx-channels.rb +45 -0
  73. data/examples/core/xx-daemon.rb +14 -0
  74. data/examples/core/xx-deadlock.rb +8 -0
  75. data/examples/core/xx-deferring-an-operation.rb +14 -0
  76. data/examples/core/xx-erlang-style-genserver.rb +81 -0
  77. data/examples/core/xx-exception-backtrace.rb +40 -0
  78. data/examples/core/xx-fork-cleanup.rb +22 -0
  79. data/examples/core/xx-fork-spin.rb +42 -0
  80. data/examples/core/xx-fork-terminate.rb +27 -0
  81. data/examples/core/xx-forking.rb +24 -0
  82. data/examples/core/xx-move_on.rb +23 -0
  83. data/examples/core/xx-pingpong.rb +18 -0
  84. data/examples/core/xx-queue-async.rb +120 -0
  85. data/examples/core/xx-readpartial.rb +18 -0
  86. data/examples/core/xx-recurrent-timer.rb +12 -0
  87. data/examples/core/xx-resource_delegate.rb +31 -0
  88. data/examples/core/xx-signals.rb +16 -0
  89. data/examples/core/xx-sleep-forever.rb +9 -0
  90. data/examples/core/xx-sleeping.rb +25 -0
  91. data/examples/core/xx-snooze-starve.rb +16 -0
  92. data/examples/core/xx-spin-fork.rb +49 -0
  93. data/examples/core/xx-spin_error_backtrace.rb +33 -0
  94. data/examples/core/xx-state-machine.rb +51 -0
  95. data/examples/core/xx-stop.rb +20 -0
  96. data/examples/core/xx-supervise-process.rb +30 -0
  97. data/examples/core/xx-supervisors.rb +21 -0
  98. data/examples/core/xx-thread-selector-sleep.rb +51 -0
  99. data/examples/core/xx-thread-selector-snooze.rb +46 -0
  100. data/examples/core/xx-thread-sleep.rb +17 -0
  101. data/examples/core/xx-thread-snooze.rb +34 -0
  102. data/examples/core/xx-thread_pool.rb +17 -0
  103. data/examples/core/xx-throttling.rb +18 -0
  104. data/examples/core/xx-timeout.rb +10 -0
  105. data/examples/core/xx-timer-gc.rb +17 -0
  106. data/examples/core/xx-trace.rb +79 -0
  107. data/examples/core/xx-using-a-mutex.rb +21 -0
  108. data/examples/core/xx-worker-thread.rb +30 -0
  109. data/examples/io/tunnel.rb +48 -0
  110. data/examples/io/xx-backticks.rb +11 -0
  111. data/examples/io/xx-echo_client.rb +25 -0
  112. data/examples/io/xx-echo_client_from_stdin.rb +21 -0
  113. data/examples/io/xx-echo_pipe.rb +16 -0
  114. data/examples/io/xx-echo_server.rb +17 -0
  115. data/examples/io/xx-echo_server_with_timeout.rb +34 -0
  116. data/examples/io/xx-echo_stdin.rb +14 -0
  117. data/examples/io/xx-happy-eyeballs.rb +36 -0
  118. data/examples/io/xx-httparty.rb +38 -0
  119. data/examples/io/xx-irb.rb +17 -0
  120. data/examples/io/xx-net-http.rb +15 -0
  121. data/examples/io/xx-open.rb +16 -0
  122. data/examples/io/xx-switch.rb +15 -0
  123. data/examples/io/xx-system.rb +11 -0
  124. data/examples/io/xx-tcpserver.rb +15 -0
  125. data/examples/io/xx-tcpsocket.rb +18 -0
  126. data/examples/io/xx-zip.rb +19 -0
  127. data/examples/performance/fiber_transfer.rb +47 -0
  128. data/examples/performance/fs_read.rb +38 -0
  129. data/examples/performance/mem-usage.rb +56 -0
  130. data/examples/performance/messaging.rb +29 -0
  131. data/examples/performance/multi_snooze.rb +33 -0
  132. data/examples/performance/snooze.rb +39 -0
  133. data/examples/performance/snooze_raw.rb +39 -0
  134. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +74 -0
  135. data/examples/performance/thread-vs-fiber/polyphony_server.rb +45 -0
  136. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
  137. data/examples/performance/thread-vs-fiber/threaded_server.rb +27 -0
  138. data/examples/performance/thread-vs-fiber/xx-httparty_multi.rb +36 -0
  139. data/examples/performance/thread-vs-fiber/xx-httparty_threaded.rb +29 -0
  140. data/examples/performance/thread_pool_perf.rb +63 -0
  141. data/examples/performance/xx-array.rb +11 -0
  142. data/examples/performance/xx-fiber-switch.rb +9 -0
  143. data/examples/performance/xx-snooze.rb +15 -0
  144. data/examples/xx-spin.rb +32 -0
  145. data/ext/libev/Changes +548 -0
  146. data/ext/libev/LICENSE +37 -0
  147. data/ext/libev/README +59 -0
  148. data/ext/libev/README.embed +3 -0
  149. data/ext/libev/ev.c +5279 -0
  150. data/ext/libev/ev.h +856 -0
  151. data/ext/libev/ev_epoll.c +296 -0
  152. data/ext/libev/ev_kqueue.c +224 -0
  153. data/ext/libev/ev_linuxaio.c +642 -0
  154. data/ext/libev/ev_poll.c +156 -0
  155. data/ext/libev/ev_port.c +192 -0
  156. data/ext/libev/ev_select.c +316 -0
  157. data/ext/libev/ev_vars.h +215 -0
  158. data/ext/libev/ev_win32.c +162 -0
  159. data/ext/libev/ev_wrap.h +216 -0
  160. data/ext/libev/test_libev_win32.c +123 -0
  161. data/ext/polyphony/extconf.rb +20 -0
  162. data/ext/polyphony/fiber.c +109 -0
  163. data/ext/polyphony/libev.c +2 -0
  164. data/ext/polyphony/libev.h +9 -0
  165. data/ext/polyphony/libev_agent.c +882 -0
  166. data/ext/polyphony/polyphony.c +71 -0
  167. data/ext/polyphony/polyphony.h +97 -0
  168. data/ext/polyphony/polyphony_ext.c +21 -0
  169. data/ext/polyphony/queue.c +168 -0
  170. data/ext/polyphony/ring_buffer.c +96 -0
  171. data/ext/polyphony/ring_buffer.h +28 -0
  172. data/ext/polyphony/thread.c +208 -0
  173. data/ext/polyphony/tracing.c +11 -0
  174. data/lib/polyphony.rb +136 -0
  175. data/lib/polyphony/adapters/fs.rb +19 -0
  176. data/lib/polyphony/adapters/irb.rb +52 -0
  177. data/lib/polyphony/adapters/postgres.rb +110 -0
  178. data/lib/polyphony/adapters/process.rb +33 -0
  179. data/lib/polyphony/adapters/redis.rb +67 -0
  180. data/lib/polyphony/adapters/trace.rb +138 -0
  181. data/lib/polyphony/core/channel.rb +46 -0
  182. data/lib/polyphony/core/exceptions.rb +36 -0
  183. data/lib/polyphony/core/global_api.rb +124 -0
  184. data/lib/polyphony/core/resource_pool.rb +117 -0
  185. data/lib/polyphony/core/sync.rb +21 -0
  186. data/lib/polyphony/core/thread_pool.rb +64 -0
  187. data/lib/polyphony/core/throttler.rb +41 -0
  188. data/lib/polyphony/event.rb +17 -0
  189. data/lib/polyphony/extensions/core.rb +174 -0
  190. data/lib/polyphony/extensions/fiber.rb +379 -0
  191. data/lib/polyphony/extensions/io.rb +221 -0
  192. data/lib/polyphony/extensions/openssl.rb +81 -0
  193. data/lib/polyphony/extensions/socket.rb +150 -0
  194. data/lib/polyphony/extensions/thread.rb +108 -0
  195. data/lib/polyphony/net.rb +77 -0
  196. data/lib/polyphony/version.rb +5 -0
  197. data/polyphony.gemspec +40 -0
  198. data/test/coverage.rb +54 -0
  199. data/test/eg.rb +27 -0
  200. data/test/helper.rb +56 -0
  201. data/test/q.rb +24 -0
  202. data/test/run.rb +5 -0
  203. data/test/stress.rb +25 -0
  204. data/test/test_agent.rb +130 -0
  205. data/test/test_event.rb +59 -0
  206. data/test/test_ext.rb +196 -0
  207. data/test/test_fiber.rb +988 -0
  208. data/test/test_global_api.rb +352 -0
  209. data/test/test_io.rb +249 -0
  210. data/test/test_kernel.rb +57 -0
  211. data/test/test_process_supervision.rb +46 -0
  212. data/test/test_queue.rb +112 -0
  213. data/test/test_resource_pool.rb +138 -0
  214. data/test/test_signal.rb +100 -0
  215. data/test/test_socket.rb +34 -0
  216. data/test/test_supervise.rb +103 -0
  217. data/test/test_thread.rb +170 -0
  218. data/test/test_thread_pool.rb +101 -0
  219. data/test/test_throttler.rb +50 -0
  220. data/test/test_trace.rb +68 -0
  221. metadata +482 -0
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ t = Thread.new {
9
+ t0 = Time.now
10
+ puts "sleep"
11
+ sleep 0.01
12
+ puts "wake up #{Time.now - t0}"
13
+ }
14
+
15
+ t0 = Time.now
16
+ t.join
17
+ puts "elapsed: #{Time.now - t0}"
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ def work
9
+ puts "creating fibers..."
10
+ 100000.times {
11
+ spin {
12
+ loop { snooze }
13
+ }
14
+ }
15
+
16
+ puts "done"
17
+ suspend
18
+ end
19
+
20
+ def work_thread
21
+ t = Thread.new { work }
22
+ t.join
23
+ end
24
+
25
+ main = Fiber.current
26
+ p [:main, main]
27
+
28
+ # trap('SIGINT') do
29
+ # p [:SIGINT, Fiber.current]
30
+ # p caller
31
+ # exit!
32
+ # end
33
+
34
+ work
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ def lengthy_op
7
+ data = IO.orig_read(__FILE__)
8
+ data.bytesize
9
+ end
10
+
11
+ 10.times do |_i|
12
+ spin {
13
+ p [_i, 2, Polyphony::ThreadPool.process { lengthy_op }]
14
+ }
15
+ end
16
+
17
+ suspend
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ spin do
7
+ throttled_loop(3) { STDOUT << '.' }
8
+ end
9
+
10
+ spin do
11
+ throttled_loop(rate: 2) { STDOUT << '?' }
12
+ end
13
+
14
+ spin do
15
+ throttled_loop(interval: 1) { STDOUT << '*' }
16
+ end
17
+
18
+ suspend
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ puts 'going to sleep...'
7
+ Timeout.timeout(1) do
8
+ sleep 60
9
+ end
10
+ puts 'woke up'
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ timers = 10.times.map do
9
+ spin do
10
+ t = Gyro::Timer.new(1, 1)
11
+ t.await
12
+ end
13
+ end
14
+
15
+ sleep 0.1
16
+ GC.start
17
+ sleep 0.1
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+
9
+ sleep 0
10
+ $records = []
11
+
12
+ Gyro.trace(true)
13
+ trace = Polyphony::Trace.new { |r| $records << r }
14
+ trace.enable
15
+
16
+ f2 = spin(:f2) { 3.times { sleep 0.1 } }
17
+
18
+ 10.times {
19
+ spin { 3.times { sleep rand(0.05..0.15) } }
20
+ }
21
+
22
+ suspend
23
+ trace.disable
24
+ puts("record count: %d" % $records.size)
25
+
26
+ analysis = Polyphony::Trace.analyze $records
27
+
28
+ puts("fiber count: %d" % analysis[:by_fiber].size)
29
+ puts
30
+
31
+ worker_fibers = analysis[:by_fiber].keys - [Fiber.current]
32
+
33
+ analysis[:by_fiber][f2].each { |r|
34
+ case r[:event]
35
+ when /^fiber_/
36
+ STDOUT.orig_puts "#{r[:stamp]} #{r[:event]} (#{r[:value].inspect})"
37
+ else
38
+ STDOUT.orig_puts "#{r[:stamp]} #{r[:fiber]&.tag} #{r[:event]} (#{r[:value].inspect})"
39
+ end
40
+ }
41
+
42
+ state = 0
43
+ run_wait_stamp = nil
44
+ schedule_stamp = nil
45
+ run_time = 0
46
+ wait_time = 0
47
+ schedule_count = 0
48
+ schedule_acc = 0
49
+ worker_fibers.each do |f|
50
+ analysis[:by_fiber][f].each { |r|
51
+ case r[:event]
52
+ when :fiber_create
53
+ state = 0
54
+ run_wait_stamp = r[:stamp]
55
+ when :fiber_schedule
56
+ schedule_count += 1
57
+ schedule_stamp = r[:stamp]
58
+ when :fiber_run
59
+ schedule_acc += r[:stamp] - schedule_stamp
60
+ wait_time += r[:stamp] - run_wait_stamp
61
+ state = 1
62
+ schedule_stamp = run_wait_stamp = r[:stamp]
63
+ when :fiber_switchpoint, :fiber_terminate
64
+ run_time += r[:stamp] - run_wait_stamp
65
+ state = 0
66
+ run_wait_stamp = r[:stamp]
67
+ end
68
+ }
69
+ end
70
+
71
+ puts(
72
+ format(
73
+ "f2 run: %f wait: %f schedule_count: %d avg schedule latency: %f",
74
+ run_time,
75
+ wait_time,
76
+ schedule_count,
77
+ schedule_acc / schedule_count
78
+ )
79
+ )
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ def loop_it(number, lock)
7
+ loop do
8
+ sleep(rand * 0.2)
9
+ lock.synchronize do
10
+ puts "child #{number} has the lock"
11
+ sleep(rand * 0.05)
12
+ end
13
+ end
14
+ end
15
+
16
+ lock = Polyphony::Sync::Mutex.new
17
+ spin { loop_it(1, lock) }
18
+ spin { loop_it(2, lock) }
19
+ spin { loop_it(3, lock) }
20
+
21
+ suspend
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ def do_work(client)
7
+ result = yield
8
+ client.schedule(result)
9
+ rescue Exception => e
10
+ client.schedule(e)
11
+ end
12
+
13
+ $worker = Thread.new do
14
+ Fiber.current.tag = :worker
15
+ loop do
16
+ client, block = receive
17
+ do_work(client, &block)
18
+ end
19
+ rescue Exception => e
20
+ p e
21
+ end
22
+
23
+ def process(&block)
24
+ $worker.main_fiber << [Fiber.current, block]
25
+ receive
26
+ end
27
+
28
+ sleep 0.1
29
+
30
+ p process { 1 + 1 }
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Ports = ARGV[0..1]
7
+ EndPoints = []
8
+
9
+ def log(msg)
10
+ puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S.%3N')} #{msg}"
11
+ end
12
+
13
+ def endpoint_loop(idx, peer_idx)
14
+ port = Ports[idx]
15
+ server = Polyphony::Net.tcp_listen(
16
+ '0.0.0.0',
17
+ port,
18
+ reuse_addr: true
19
+ )
20
+ # server = TCPServer.open('0.0.0.0', port)
21
+ log "Listening on port #{port}"
22
+ loop do
23
+ conn = server.accept
24
+ conn.binmode
25
+ EndPoints[idx] = conn
26
+ log "Client connected on port #{port} (#{conn.remote_address.inspect})"
27
+ while data = conn.readpartial(8192)
28
+ peer = EndPoints[peer_idx]
29
+ if peer
30
+ peer << data
31
+ log "#{idx} => #{peer_idx} #{data.inspect}"
32
+ else
33
+ log "#{idx}: #{data.inspect}"
34
+ end
35
+ end
36
+ EndPoints[idx] = nil
37
+ log "Connection closed on port #{port}"
38
+ rescue => e
39
+ log "Error on port #{port}: #{e.inspect}"
40
+ end
41
+ end
42
+
43
+ spin { endpoint_loop(0, 1) }
44
+ spin { endpoint_loop(1, 0) }
45
+
46
+ log "Tunneling port #{Ports[0]} to port #{Ports[1]}..."
47
+ sleep
48
+
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ timer = spin do
7
+ throttled_loop(5) { STDOUT << '.' }
8
+ end
9
+
10
+ puts `ruby -e "sleep 1; puts :done; STDOUT.close"`
11
+ timer.stop
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ socket = Polyphony::Net.tcp_connect('127.0.0.1', 1234)
7
+
8
+ writer = spin do
9
+ throttled_loop(1) do
10
+ socket << "#{Time.now}\n"
11
+ rescue StandardError
12
+ nil
13
+ end
14
+ end
15
+
16
+ reader = spin do
17
+ puts 'received from echo server:'
18
+ while (data = socket.readpartial(8192))
19
+ STDOUT << data
20
+ end
21
+ end
22
+
23
+ sleep(5)
24
+ [reader, writer].each(&:stop)
25
+ socket.close
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ socket = Polyphony::Net.tcp_connect('127.0.0.1', 1234)
7
+
8
+ writer = spin do
9
+ while (data = gets)
10
+ socket << data
11
+ end
12
+ end
13
+
14
+ spin do
15
+ while (data = socket.readpartial(8192))
16
+ STDOUT << 'received: ' + data
17
+ end
18
+ writer.interrupt
19
+ end
20
+
21
+ suspend
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ i, o = IO.pipe
7
+
8
+ puts 'Say something:'
9
+ spin do
10
+ loop { o << STDIN.gets }
11
+ o.close
12
+ end
13
+
14
+ while (data = i.readpartial(8192))
15
+ STDOUT << "You said: #{data}"
16
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ server = TCPServer.open('127.0.0.1', 1234)
7
+ puts "Pid: #{Process.pid}"
8
+ puts 'Echoing on port 1234...'
9
+ while (client = server.accept)
10
+ spin do
11
+ while (data = client.gets)
12
+ client.write('you said: ', data.chomp, "!\n")
13
+ end
14
+ rescue Errno::ECONNRESET
15
+ 'Connection reset...'
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ begin
7
+ server = Polyphony::Net.tcp_listen(
8
+ nil, 1234, reuse_addr: true, dont_linger: true
9
+ )
10
+ puts 'listening on port 1234...'
11
+
12
+ loop do
13
+ client = server.accept
14
+ client.write "Hi there\n"
15
+ spin do
16
+ move_on_after(5) do |scope|
17
+ scope.when_cancelled do
18
+ client.write "Disconnecting due to inactivity\n"
19
+ end
20
+ while (data = client.readpartial(8192))
21
+ scope.reset_timeout
22
+ client.write "You said: #{data}"
23
+ end
24
+ end
25
+ rescue StandardError => e
26
+ puts "client error: #{e.inspect}"
27
+ ensure
28
+ client.close
29
+ end
30
+ end
31
+ rescue Exception => e
32
+ puts "uncaught exception: #{e.inspect}"
33
+ server&.close
34
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ puts 'Write something...'
7
+ move_on_after(5) do |scope|
8
+ loop do
9
+ data = STDIN.gets
10
+ scope.reset_timeout
11
+ puts "you wrote: #{data}"
12
+ end
13
+ end
14
+ puts 'quitting due to inactivity'