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,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony/adapters/redis'
5
+ # require 'redis'
6
+
7
+ redis = Redis.new(host: ENV['REDISHOST'] || 'localhost')
8
+
9
+ redis.lpush("queue_key", "omgvalue")
10
+ puts "len: #{redis.llen("queue_key")}"
11
+ result = redis.blpop("queue_key")
12
+ puts result.inspect
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony/adapters/redis'
5
+
6
+ class RedisChannel < Polyphony::Channel
7
+ def self.publish_connection
8
+ @publish_connection ||= Redis.new
9
+ end
10
+
11
+ def self.subscribe_connection
12
+ @subscribe_connection ||= Redis.new
13
+ end
14
+
15
+ CHANNEL_MASTER_TOPIC = 'channel_master'
16
+
17
+ def self.start_monitor
18
+ @channels = {}
19
+ @monitor = spin do
20
+ subscribe_connection.subscribe(CHANNEL_MASTER_TOPIC) do |on|
21
+ on.message do |topic, message|
22
+ message = Marshal.load(message)
23
+ topic == if CHANNEL_MASTER_TOPIC
24
+ handle_master_message(message)
25
+ else
26
+ handle_channel_message(topic, message)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def self.stop_monitor
34
+ @monitor&.interrupt
35
+ end
36
+
37
+ def self.handle_master_message(message)
38
+ case message[:kind]
39
+ when :subscribe
40
+ subscribe_connection.subscribe(message[:topic])
41
+ when :unsubscribe
42
+ subscribe_connection.unsubscribe(message[:topic])
43
+ end
44
+ end
45
+
46
+ def self.handle_channel_message(topic, message)
47
+ channel = @channels[topic]
48
+ channel&.did_receive(message)
49
+ end
50
+
51
+ def self.watch(channel)
52
+ @channels[channel.topic] = channel
53
+ spin do
54
+ publish_connection.publish(CHANNEL_MASTER_TOPIC, Marshal.dump(
55
+ kind: :subscribe,
56
+ topic: channel.topic
57
+ ))
58
+ end
59
+ end
60
+
61
+ def self.unwatch(channel)
62
+ @channels.delete(channel.topic)
63
+ spin do
64
+ publish_connection.publish(CHANNEL_MASTER_TOPIC, Marshal.dump(
65
+ kind: :unsubscribe,
66
+ topic: channel.topic
67
+ ))
68
+ end
69
+ end
70
+
71
+ def self.channel_topic(channel)
72
+ "channel_#{channel.object_id}"
73
+ end
74
+
75
+ attr_reader :topic
76
+
77
+ def initialize(topic)
78
+ @topic = topic
79
+ @waiting_queue = []
80
+ RedisChannel.watch(self)
81
+ end
82
+
83
+ def close
84
+ super
85
+ RedisChannel.unwatch(self)
86
+ end
87
+
88
+ def <<(o)
89
+ RedisChannel.publish_connection.publish(@topic, Marshal.dump(o))
90
+ end
91
+
92
+ def did_receive(o)
93
+ @waiting_queue.shift&.schedule(o)
94
+ end
95
+
96
+ def receive
97
+ @waiting_queue << Fiber.current
98
+ suspend
99
+ end
100
+ end
101
+
102
+ RedisChannel.start_monitor
103
+ channel = RedisChannel.new('channel1')
104
+
105
+ spin do
106
+ loop do
107
+ message = channel.receive
108
+ puts "got message: #{message}"
109
+ end
110
+ end
111
+
112
+ spin do
113
+ move_on_after(3) do
114
+ throttled_loop(1) do
115
+ channel << Time.now
116
+ end
117
+ end
118
+ channel.close
119
+ RedisChannel.stop_monitor
120
+ end
121
+
122
+ suspend
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony/adapters/redis'
5
+
6
+ redis = Redis.new
7
+
8
+ X = 10
9
+
10
+ t0 = Time.now
11
+ X.times { redis.get('abc') }
12
+ puts "get rate: #{X / (Time.now - t0)} reqs/s"
13
+
14
+ puts "abc = #{redis.get('abc')}"
15
+
16
+ puts 'updating value...'
17
+ redis.set('abc', Time.now.to_s)
18
+
19
+ puts "abc = #{redis.get('abc')}"
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony/adapters/redis'
5
+
6
+ spin do
7
+ redis = Redis.new
8
+ redis.subscribe('redis-channel') do |on|
9
+ on.message do |channel, message|
10
+ puts "##{channel}: #{message}"
11
+ redis.unsubscribe if message == 'exit'
12
+ end
13
+ end
14
+ end
15
+
16
+ spin do
17
+ redis = Redis.new
18
+ move_on_after(3) do
19
+ throttled_loop(1) do
20
+ redis.publish('redis-channel', Time.now)
21
+ end
22
+ end
23
+ redis.publish('redis-channel', 'exit')
24
+ end
25
+
26
+ suspend
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony/adapters/redis'
5
+ require 'json'
6
+
7
+ X_SESSIONS = 1000
8
+ X_NODES = 10_000
9
+ X_SUBSCRIPTIONS_PER_SESSION = 100
10
+
11
+ $sessions = []
12
+ X_SESSIONS.times do
13
+ $sessions << {
14
+ subscriptions: X_SUBSCRIPTIONS_PER_SESSION.times.map do
15
+ "node#{rand(X_NODES)}"
16
+ end.uniq
17
+ }
18
+ end
19
+
20
+ spin do
21
+ redis = Redis.new
22
+ redis.subscribe('events') do |on|
23
+ on.message do |_, message|
24
+ distribute_event(JSON.parse(message, symbolize_names: true))
25
+ end
26
+ end
27
+ end
28
+
29
+ $update_count = 0
30
+
31
+ def distribute_event(event)
32
+ $update_count += 1
33
+ # t0 = Time.now
34
+ count = 0
35
+ $sessions.each do |s|
36
+ count += 1 if s[:subscriptions].include?(event[:path])
37
+ end
38
+ # elapsed = Time.now - t0
39
+ # rate = X_SESSIONS / elapsed
40
+ # puts "elapsed: #{elapsed} (#{rate}/s)" if $update_count % 100 == 0
41
+ end
42
+
43
+ spin do
44
+ redis = Redis.new
45
+ throttled_loop(1000) do
46
+ redis.publish('events', { path: "node#{rand(X_NODES)}" }.to_json)
47
+ end
48
+ end
49
+
50
+ spin do
51
+ last_count = 0
52
+ last_stamp = Time.now
53
+ throttled_loop(1) do
54
+ now = Time.now
55
+ elapsed = now - last_stamp
56
+ delta = $update_count - last_count
57
+ puts "update rate: #{delta.to_f / elapsed}"
58
+ last_stamp = now
59
+ last_count = $update_count
60
+ end
61
+ end
62
+
63
+ trap(:int) do
64
+ puts 'bye...'
65
+ exit!
66
+ end
67
+
68
+ suspend
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+
5
+ require 'polyphony'
6
+
7
+ def nap(tag, t)
8
+ puts "#{Time.now} #{tag} napping for #{t} seconds..."
9
+ sleep t
10
+ puts "#{Time.now} #{tag} done napping"
11
+ end
12
+
13
+ # We launch two concurrent fibers, each sleeping for the given duration.
14
+ spin { nap(:a, 1) }
15
+ spin { nap(:b, 2) }
16
+
17
+ # Calling suspend will block until all child fibers have terminated
18
+ suspend
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ sleeper = spin do
7
+ puts 'going to sleep'
8
+ sleep 1
9
+ puts 'woke up'
10
+ end
11
+
12
+ # One way to synchronize fibers is by using `Fiber#await`, which blocks
13
+ # until the fiber has finished running or has been interrupted.
14
+ waiter = spin do
15
+ puts 'waiting for fiber to terminate'
16
+ sleeper.await
17
+ puts 'done waiting'
18
+ end
19
+
20
+ waiter.await
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ # Let's see how a long-running blocking operation can be interrupted. Polyphony
7
+ # provides several APIs for interrupting an ongoing operation, and distinguishes
8
+ # between two different types of interruptions: *cancel* and *move on*. A
9
+ # *cancel* will interrupt an ongoing operation and raise an exception. A *move
10
+ # on* will interrupt an ongoing operation without raising an exception,
11
+ # optionally returning an arbitrary value as the result of that operation.
12
+
13
+ def nap(tag, t)
14
+ puts "#{Time.now} #{tag} napping for #{t} seconds..."
15
+ sleep t
16
+ ensure
17
+ puts "#{Time.now} #{tag} done napping"
18
+ end
19
+
20
+ # The Kernel#cancel_after interrupts a blocking operation by raising a
21
+ # Polyphony::Cancel exception after the given timeout. If not rescued, the
22
+ # exception is propagated up the fiber hierarchy
23
+ spin do
24
+ # cancel after 1 second
25
+ cancel_after(1) { nap(:cancel, 2) }
26
+ rescue Polyphony::Cancel => e
27
+ puts "got exception: #{e}"
28
+ end
29
+
30
+ # The Kernel#move_on_after interrupts a blocking operation by raising a
31
+ # Polyphony::MoveOn exception, which is silently swallowed by the fiber
32
+ spin do
33
+ # move on after 1 second
34
+ move_on_after(1) do
35
+ nap(:move_on, 2)
36
+ end
37
+ end
38
+
39
+ suspend
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ # trap('TERM') do
7
+ # Polyphony.emit_signal_exception(::SystemExit)
8
+ # end
9
+
10
+ # trap('INT') do
11
+ # Polyphony.emit_signal_exception(::Interrupt)
12
+ # end
13
+
14
+ puts "go to sleep"
15
+ begin
16
+ sleep
17
+ ensure
18
+ puts "done sleeping"
19
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ class Test
9
+ def test_sleep
10
+ puts "going to sleep"
11
+ sleep 1
12
+ puts "done sleeping"
13
+ end
14
+
15
+ def test_spin
16
+ spin {
17
+ 10.times {
18
+ STDOUT << '.'
19
+ sleep 0.1
20
+ }
21
+ }
22
+
23
+ puts "going to sleep\n"
24
+ sleep 1
25
+ puts 'woke up'
26
+ end
27
+
28
+ def test_file
29
+ f = File.open(__FILE__, 'r')
30
+ puts Thread.current.agent.read(f, +'', 10000, true)
31
+
32
+ Thread.current.agent.write(STDOUT, "Write something: ")
33
+ str = +''
34
+ Thread.current.agent.read(STDIN, str, 5, false)
35
+ puts str
36
+ end
37
+
38
+ def test_fork
39
+ pid = fork do
40
+ Thread.current.agent.post_fork
41
+ puts 'child going to sleep'
42
+ sleep 1
43
+ puts 'child done sleeping'
44
+ exit(42)
45
+ end
46
+
47
+ puts "Waiting for pid #{pid}"
48
+ result = Thread.current.agent.waitpid(pid)
49
+ puts "Done waiting"
50
+ p result
51
+ end
52
+
53
+ def test_async
54
+ async = Polyphony::Event.new
55
+
56
+ spin {
57
+ puts "signaller starting"
58
+ sleep 1
59
+ puts "signal"
60
+ async.signal(:foo)
61
+ }
62
+
63
+ puts "awaiting event"
64
+ p async.await
65
+ end
66
+
67
+ def test_queue
68
+ q = Gyro::Queue.new
69
+ spin {
70
+ 10.times {
71
+ q << Time.now.to_f
72
+ sleep 0.2
73
+ }
74
+ q << :STOP
75
+ }
76
+
77
+ loop do
78
+ value = q.shift
79
+ break if value == :STOP
80
+
81
+ p value
82
+ end
83
+ end
84
+
85
+ def test_thread
86
+ t = Thread.new do
87
+ puts "thread going to sleep"
88
+ sleep 0.2
89
+ puts "thread done sleeping"
90
+ end
91
+
92
+ t.await
93
+ end
94
+ end
95
+
96
+ t = Test.new
97
+
98
+ t.methods.select { |m| m =~ /^test_/ }.each do |m|
99
+ puts '*' * 40
100
+ puts m
101
+ t.send(m)
102
+ end