polyphony 0.43.11 → 0.45.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -1
  3. data/CHANGELOG.md +40 -0
  4. data/Gemfile.lock +18 -8
  5. data/Rakefile +1 -1
  6. data/TODO.md +22 -9
  7. data/docs/_posts/2020-07-26-polyphony-0.44.md +77 -0
  8. data/docs/api-reference/thread.md +1 -1
  9. data/docs/getting-started/overview.md +14 -14
  10. data/docs/getting-started/tutorial.md +1 -1
  11. data/examples/adapters/redis_client.rb +3 -1
  12. data/examples/adapters/redis_pubsub_perf.rb +11 -8
  13. data/examples/adapters/sequel_mysql.rb +23 -0
  14. data/examples/adapters/sequel_mysql_pool.rb +33 -0
  15. data/examples/adapters/sequel_pg.rb +24 -0
  16. data/examples/core/{02-awaiting-fibers.rb → await.rb} +0 -0
  17. data/examples/core/{xx-channels.rb → channels.rb} +0 -0
  18. data/examples/core/deferring-an-operation.rb +16 -0
  19. data/examples/core/{xx-erlang-style-genserver.rb → erlang-style-genserver.rb} +16 -9
  20. data/examples/core/{xx-forking.rb → forking.rb} +1 -1
  21. data/examples/core/handling-signals.rb +11 -0
  22. data/examples/core/{03-interrupting.rb → interrupt.rb} +0 -0
  23. data/examples/core/{xx-pingpong.rb → pingpong.rb} +7 -5
  24. data/examples/core/{xx-recurrent-timer.rb → recurrent-timer.rb} +1 -1
  25. data/examples/core/{xx-resource_delegate.rb → resource_delegate.rb} +3 -4
  26. data/examples/core/{01-spinning-up-fibers.rb → spin.rb} +1 -1
  27. data/examples/core/{xx-spin_error_backtrace.rb → spin_error_backtrace.rb} +1 -1
  28. data/examples/core/{xx-supervise-process.rb → supervise-process.rb} +8 -5
  29. data/examples/core/supervisor.rb +20 -0
  30. data/examples/core/{xx-thread-sleep.rb → thread-sleep.rb} +0 -0
  31. data/examples/core/{xx-thread_pool.rb → thread_pool.rb} +0 -0
  32. data/examples/core/{xx-throttling.rb → throttling.rb} +0 -0
  33. data/examples/core/{xx-timeout.rb → timeout.rb} +0 -0
  34. data/examples/core/{xx-using-a-mutex.rb → using-a-mutex.rb} +0 -0
  35. data/examples/core/{xx-worker-thread.rb → worker-thread.rb} +2 -2
  36. data/examples/io/{xx-backticks.rb → backticks.rb} +0 -0
  37. data/examples/io/{xx-echo_client.rb → echo_client.rb} +1 -1
  38. data/examples/io/{xx-echo_client_from_stdin.rb → echo_client_from_stdin.rb} +2 -2
  39. data/examples/io/{xx-echo_pipe.rb → echo_pipe.rb} +1 -1
  40. data/examples/io/{xx-echo_server.rb → echo_server.rb} +0 -0
  41. data/examples/io/{xx-echo_server_with_timeout.rb → echo_server_with_timeout.rb} +1 -1
  42. data/examples/io/{xx-echo_stdin.rb → echo_stdin.rb} +0 -0
  43. data/examples/io/{xx-happy-eyeballs.rb → happy-eyeballs.rb} +0 -0
  44. data/examples/io/{xx-httparty.rb → httparty.rb} +4 -13
  45. data/examples/io/{xx-irb.rb → irb.rb} +0 -0
  46. data/examples/io/{xx-net-http.rb → net-http.rb} +0 -0
  47. data/examples/io/{xx-open.rb → open.rb} +0 -0
  48. data/examples/io/pry.rb +18 -0
  49. data/examples/io/rack_server.rb +71 -0
  50. data/examples/io/raw.rb +14 -0
  51. data/examples/io/reline.rb +18 -0
  52. data/examples/io/{xx-system.rb → system.rb} +1 -1
  53. data/examples/io/{xx-tcpserver.rb → tcpserver.rb} +0 -0
  54. data/examples/io/{xx-tcpsocket.rb → tcpsocket.rb} +0 -0
  55. data/examples/io/tunnel.rb +6 -1
  56. data/examples/io/{xx-zip.rb → zip.rb} +0 -0
  57. data/examples/performance/fiber_transfer.rb +2 -1
  58. data/examples/performance/fs_read.rb +5 -6
  59. data/examples/{io/xx-switch.rb → performance/switch.rb} +2 -1
  60. data/examples/performance/thread-vs-fiber/{xx-httparty_multi.rb → httparty_multi.rb} +3 -4
  61. data/examples/performance/thread-vs-fiber/{xx-httparty_threaded.rb → httparty_threaded.rb} +0 -0
  62. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +1 -1
  63. data/examples/performance/thread-vs-fiber/polyphony_server.rb +1 -1
  64. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +1 -1
  65. data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -5
  66. data/examples/performance/thread_pool_perf.rb +6 -7
  67. data/ext/polyphony/backend.h +40 -0
  68. data/ext/polyphony/event.c +3 -3
  69. data/ext/polyphony/extconf.rb +1 -1
  70. data/ext/polyphony/fiber.c +66 -6
  71. data/ext/polyphony/{libev_agent.c → libev_backend.c} +237 -238
  72. data/ext/polyphony/polyphony.c +3 -3
  73. data/ext/polyphony/polyphony.h +15 -20
  74. data/ext/polyphony/polyphony_ext.c +3 -4
  75. data/ext/polyphony/queue.c +5 -6
  76. data/ext/polyphony/ring_buffer.c +0 -1
  77. data/ext/polyphony/thread.c +36 -33
  78. data/lib/polyphony.rb +26 -39
  79. data/lib/polyphony/adapters/fs.rb +1 -1
  80. data/lib/polyphony/adapters/irb.rb +2 -17
  81. data/lib/polyphony/adapters/mysql2.rb +19 -0
  82. data/lib/polyphony/adapters/postgres.rb +5 -5
  83. data/lib/polyphony/adapters/process.rb +2 -5
  84. data/lib/polyphony/adapters/readline.rb +17 -0
  85. data/lib/polyphony/adapters/redis.rb +1 -1
  86. data/lib/polyphony/adapters/sequel.rb +45 -0
  87. data/lib/polyphony/core/exceptions.rb +11 -0
  88. data/lib/polyphony/core/global_api.rb +17 -12
  89. data/lib/polyphony/core/resource_pool.rb +20 -7
  90. data/lib/polyphony/core/sync.rb +46 -8
  91. data/lib/polyphony/core/throttler.rb +1 -1
  92. data/lib/polyphony/extensions/core.rb +30 -30
  93. data/lib/polyphony/extensions/fiber.rb +30 -49
  94. data/lib/polyphony/extensions/io.rb +60 -16
  95. data/lib/polyphony/extensions/openssl.rb +6 -6
  96. data/lib/polyphony/extensions/socket.rb +14 -15
  97. data/lib/polyphony/extensions/thread.rb +6 -5
  98. data/lib/polyphony/version.rb +1 -1
  99. data/polyphony.gemspec +7 -3
  100. data/test/helper.rb +1 -1
  101. data/test/{test_agent.rb → test_backend.rb} +22 -22
  102. data/test/test_fiber.rb +29 -12
  103. data/test/test_io.rb +59 -1
  104. data/test/test_kernel.rb +5 -0
  105. data/test/test_resource_pool.rb +29 -4
  106. data/test/test_signal.rb +16 -37
  107. data/test/test_socket.rb +17 -0
  108. data/test/test_sync.rb +52 -0
  109. metadata +127 -97
  110. data/.gitbook.yaml +0 -4
  111. data/examples/adapters/concurrent-ruby.rb +0 -9
  112. data/examples/core/04-handling-signals.rb +0 -19
  113. data/examples/core/xx-agent.rb +0 -102
  114. data/examples/core/xx-at_exit.rb +0 -29
  115. data/examples/core/xx-caller.rb +0 -12
  116. data/examples/core/xx-daemon.rb +0 -14
  117. data/examples/core/xx-deadlock.rb +0 -8
  118. data/examples/core/xx-deferring-an-operation.rb +0 -14
  119. data/examples/core/xx-exception-backtrace.rb +0 -40
  120. data/examples/core/xx-fork-cleanup.rb +0 -22
  121. data/examples/core/xx-fork-spin.rb +0 -42
  122. data/examples/core/xx-fork-terminate.rb +0 -27
  123. data/examples/core/xx-move_on.rb +0 -23
  124. data/examples/core/xx-queue-async.rb +0 -120
  125. data/examples/core/xx-readpartial.rb +0 -18
  126. data/examples/core/xx-signals.rb +0 -16
  127. data/examples/core/xx-sleep-forever.rb +0 -9
  128. data/examples/core/xx-sleeping.rb +0 -25
  129. data/examples/core/xx-snooze-starve.rb +0 -16
  130. data/examples/core/xx-spin-fork.rb +0 -49
  131. data/examples/core/xx-state-machine.rb +0 -51
  132. data/examples/core/xx-stop.rb +0 -20
  133. data/examples/core/xx-supervisors.rb +0 -21
  134. data/examples/core/xx-thread-selector-sleep.rb +0 -51
  135. data/examples/core/xx-thread-selector-snooze.rb +0 -46
  136. data/examples/core/xx-thread-snooze.rb +0 -34
  137. data/examples/core/xx-timer-gc.rb +0 -17
  138. data/examples/core/xx-trace.rb +0 -79
  139. data/examples/performance/xx-array.rb +0 -11
  140. data/examples/performance/xx-fiber-switch.rb +0 -9
  141. data/examples/performance/xx-snooze.rb +0 -15
  142. data/examples/xx-spin.rb +0 -32
  143. data/ext/polyphony/agent.h +0 -41
@@ -7,20 +7,6 @@ require_relative '../core/exceptions'
7
7
  module Polyphony
8
8
  # Fiber control API
9
9
  module FiberControl
10
- def await
11
- if @running == false
12
- return @result.is_a?(Exception) ? (Kernel.raise @result) : @result
13
- end
14
-
15
- fiber = Fiber.current
16
- @waiting_fibers ||= {}
17
- @waiting_fibers[fiber] = true
18
- suspend
19
- ensure
20
- @waiting_fibers&.delete(fiber)
21
- end
22
- alias_method :join, :await
23
-
24
10
  def interrupt(value = nil)
25
11
  return if @running == false
26
12
 
@@ -67,6 +53,10 @@ module Polyphony
67
53
  else RuntimeError.new
68
54
  end
69
55
  end
56
+
57
+ def interject(&block)
58
+ raise Polyphony::Interjection.new(block)
59
+ end
70
60
  end
71
61
 
72
62
  # Fiber supervision
@@ -113,7 +103,7 @@ module Polyphony
113
103
  suspend
114
104
  fibers.map(&:result)
115
105
  ensure
116
- await_select_cleanup(state)
106
+ await_select_cleanup(state) if state
117
107
  end
118
108
  alias_method :join, :await
119
109
 
@@ -175,21 +165,19 @@ module Polyphony
175
165
  state[:selected] = true
176
166
  end
177
167
  end
178
- end
179
-
180
- # Messaging functionality
181
- module FiberMessaging
182
- def <<(value)
183
- @mailbox << value
184
- end
185
- alias_method :send, :<<
186
-
187
- def receive
188
- @mailbox.shift
189
- end
190
168
 
191
- def receive_pending
192
- @mailbox.shift_all
169
+ # Creates and schedules with priority an out-of-band fiber that runs the
170
+ # supplied block. If any uncaught exception is raised while the fiber is
171
+ # running, it will bubble up to the main thread's main fiber, which will
172
+ # also be scheduled with priority. This method is mainly used trapping
173
+ # signals (see also the patched `Kernel#trap`)
174
+ def schedule_priority_oob_fiber(&block)
175
+ f = Fiber.new do
176
+ block.call
177
+ rescue Exception => e
178
+ Thread.current.break_out_of_ev_loop(Thread.main.main_fiber, e)
179
+ end
180
+ Thread.current.break_out_of_ev_loop(f, nil)
193
181
  end
194
182
  end
195
183
 
@@ -199,9 +187,9 @@ module Polyphony
199
187
  (@children ||= {}).keys
200
188
  end
201
189
 
202
- def spin(tag = nil, orig_caller = Kernel.caller, &block)
190
+ def spin(tag = nil, orig_caller = Kernel.caller, do_schedule: true, &block)
203
191
  f = Fiber.new { |v| f.run(v) }
204
- f.prepare(tag, block, orig_caller, self)
192
+ f.prepare(tag, block, orig_caller, self, do_schedule: do_schedule)
205
193
  (@children ||= {})[f] = true
206
194
  f
207
195
  end
@@ -221,14 +209,14 @@ module Polyphony
221
209
  def await_all_children
222
210
  return unless @children && !@children.empty?
223
211
 
224
- @results = @children.dup
212
+ results = @children.dup
225
213
  @on_child_done = proc do |c, r|
226
- @results[c] = r
227
- self.schedule if @children.empty?
214
+ results[c] = r
215
+ schedule if @children.empty?
228
216
  end
229
217
  suspend
230
218
  @on_child_done = nil
231
- @results.values
219
+ results.values
232
220
  end
233
221
 
234
222
  def shutdown_all_children
@@ -239,15 +227,14 @@ module Polyphony
239
227
 
240
228
  # Fiber life cycle methods
241
229
  module FiberLifeCycle
242
- def prepare(tag, block, caller, parent)
230
+ def prepare(tag, block, caller, parent, do_schedule: true)
243
231
  @thread = Thread.current
244
232
  @tag = tag
245
233
  @parent = parent
246
234
  @caller = caller
247
235
  @block = block
248
- @mailbox = Polyphony::Queue.new
249
236
  __fiber_trace__(:fiber_create, self)
250
- schedule
237
+ schedule if do_schedule
251
238
  end
252
239
 
253
240
  def run(first_value)
@@ -275,7 +262,6 @@ module Polyphony
275
262
  # allows the fiber to be scheduled and to receive messages.
276
263
  def setup_raw
277
264
  @thread = Thread.current
278
- @mailbox = Polyphony::Queue.new
279
265
  end
280
266
 
281
267
  def setup_main_fiber
@@ -284,11 +270,10 @@ module Polyphony
284
270
  @thread = Thread.current
285
271
  @running = true
286
272
  @children&.clear
287
- @mailbox = Polyphony::Queue.new
288
273
  end
289
274
 
290
275
  def restart_self(first_value)
291
- @mailbox = Polyphony::Queue.new
276
+ @mailbox = nil
292
277
  @when_done_procs = nil
293
278
  @waiting_fibers = nil
294
279
  run(first_value)
@@ -320,13 +305,10 @@ module Polyphony
320
305
  def inform_dependants(result, uncaught_exception)
321
306
  @parent&.child_done(self, result)
322
307
  @when_done_procs&.each { |p| p.(result) }
323
- @waiting_fibers&.each_key do |f|
324
- f.schedule(result)
325
- end
326
- return unless uncaught_exception && !@waiting_fibers
327
-
308
+ @waiting_fibers&.each_key { |f| f.schedule(result) }
309
+
328
310
  # propagate unaught exception to parent
329
- @parent&.schedule(result)
311
+ @parent&.schedule(result) if uncaught_exception && !@waiting_fibers
330
312
  end
331
313
 
332
314
  def when_done(&block)
@@ -340,14 +322,13 @@ end
340
322
  class ::Fiber
341
323
  prepend Polyphony::FiberControl
342
324
  include Polyphony::FiberSupervision
343
- include Polyphony::FiberMessaging
344
325
  include Polyphony::ChildFiberControl
345
326
  include Polyphony::FiberLifeCycle
346
327
 
347
328
  extend Polyphony::FiberControlClassMethods
348
329
 
349
330
  attr_accessor :tag, :thread, :parent
350
- attr_reader :result
331
+ attr_reader :result, :mailbox
351
332
 
352
333
  def running?
353
334
  @running
@@ -90,16 +90,27 @@ class ::IO
90
90
  # def each_codepoint
91
91
  # end
92
92
 
93
- # def getbyte
94
- # end
93
+ alias_method :orig_getbyte, :getbyte
94
+ def getbyte
95
+ char = getc
96
+ char ? char.getbyte(0) : nil
97
+ end
95
98
 
96
- # def getc
97
- # end
99
+ alias_method :orig_getc, :getc
100
+ def getc
101
+ return @read_buffer.slice!(0) if @read_buffer && !@read_buffer.empty?
102
+
103
+ @read_buffer ||= +''
104
+ Thread.current.backend.read(self, @read_buffer, 8192, false)
105
+ return @read_buffer.slice!(0) if !@read_buffer.empty?
106
+
107
+ nil
108
+ end
98
109
 
99
110
  alias_method :orig_read, :read
100
111
  def read(len = nil)
101
112
  @read_buffer ||= +''
102
- result = Thread.current.agent.read(self, @read_buffer, len, true)
113
+ result = Thread.current.backend.read(self, @read_buffer, len, true)
103
114
  return nil unless result
104
115
 
105
116
  already_read = @read_buffer
@@ -110,7 +121,7 @@ class ::IO
110
121
  alias_method :orig_readpartial, :read
111
122
  def readpartial(len, str = nil)
112
123
  @read_buffer ||= +''
113
- result = Thread.current.agent.read(self, @read_buffer, len, false)
124
+ result = Thread.current.backend.read(self, @read_buffer, len, false)
114
125
  raise EOFError unless result
115
126
 
116
127
  if str
@@ -124,12 +135,12 @@ class ::IO
124
135
 
125
136
  alias_method :orig_write, :write
126
137
  def write(str, *args)
127
- Thread.current.agent.write(self, str, *args)
138
+ Thread.current.backend.write(self, str, *args)
128
139
  end
129
140
 
130
141
  alias_method :orig_write_chevron, :<<
131
142
  def <<(str)
132
- Thread.current.agent.write(self, str)
143
+ Thread.current.backend.write(self, str)
133
144
  self
134
145
  end
135
146
 
@@ -163,20 +174,29 @@ class ::IO
163
174
  # def putc(obj)
164
175
  # end
165
176
 
177
+ LINEFEED = "\n"
178
+ LINEFEED_RE = /\n$/.freeze
179
+
166
180
  alias_method :orig_puts, :puts
167
181
  def puts(*args)
168
182
  if args.empty?
169
- write "\n"
183
+ write LINEFEED
170
184
  return
171
185
  end
172
186
 
173
- strs = args.inject([]) do |m, a|
174
- a = a.to_s
175
- m << a
176
- m << "\n" unless a =~ /\n$/
177
- m
187
+ idx = 0
188
+ while idx < args.size
189
+ arg = args[idx]
190
+ args[idx] = arg = arg.to_s unless arg.is_a?(String)
191
+ if arg =~ LINEFEED_RE
192
+ idx += 1
193
+ else
194
+ args.insert(idx + 1, LINEFEED)
195
+ idx += 2
196
+ end
178
197
  end
179
- write *strs
198
+
199
+ write(*args)
180
200
  nil
181
201
  end
182
202
 
@@ -203,7 +223,7 @@ class ::IO
203
223
  end
204
224
 
205
225
  def read_loop(&block)
206
- Thread.current.agent.read_loop(self, &block)
226
+ Thread.current.backend.read_loop(self, &block)
207
227
  end
208
228
 
209
229
  # alias_method :orig_read, :read
@@ -218,4 +238,28 @@ class ::IO
218
238
  # end
219
239
  # outbuf
220
240
  # end
241
+
242
+ def wait_readable(timeout = nil)
243
+ if timeout
244
+ move_on_after(timeout) do
245
+ Thread.current.backend.wait_io(self, false)
246
+ self
247
+ end
248
+ else
249
+ Thread.current.backend.wait_io(self, false)
250
+ self
251
+ end
252
+ end
253
+
254
+ def wait_writable(timeout = nil)
255
+ if timeout
256
+ move_on_after(timeout) do
257
+ Thread.current.backend.wait_io(self, true)
258
+ self
259
+ end
260
+ else
261
+ Thread.current.backend.wait_io(self, true)
262
+ self
263
+ end
264
+ end
221
265
  end
@@ -28,8 +28,8 @@ class ::OpenSSL::SSL::SSLSocket
28
28
  loop do
29
29
  result = accept_nonblock(exception: false)
30
30
  case result
31
- when :wait_readable then Thread.current.agent.wait_io(io, false)
32
- when :wait_writable then Thread.current.agent.wait_io(io, true)
31
+ when :wait_readable then Thread.current.backend.wait_io(io, false)
32
+ when :wait_writable then Thread.current.backend.wait_io(io, true)
33
33
  else
34
34
  return result
35
35
  end
@@ -40,8 +40,8 @@ class ::OpenSSL::SSL::SSLSocket
40
40
  def sysread(maxlen, buf = +'')
41
41
  loop do
42
42
  case (result = read_nonblock(maxlen, buf, exception: false))
43
- when :wait_readable then Thread.current.agent.wait_io(io, false)
44
- when :wait_writable then Thread.current.agent.wait_io(io, true)
43
+ when :wait_readable then Thread.current.backend.wait_io(io, false)
44
+ when :wait_writable then Thread.current.backend.wait_io(io, true)
45
45
  else return result
46
46
  end
47
47
  end
@@ -51,8 +51,8 @@ class ::OpenSSL::SSL::SSLSocket
51
51
  def syswrite(buf)
52
52
  loop do
53
53
  case (result = write_nonblock(buf, exception: false))
54
- when :wait_readable then Thread.current.agent.wait_io(io, false)
55
- when :wait_writable then Thread.current.agent.wait_io(io, true)
54
+ when :wait_readable then Thread.current.backend.wait_io(io, false)
55
+ when :wait_writable then Thread.current.backend.wait_io(io, true)
56
56
  else
57
57
  return result
58
58
  end
@@ -5,26 +5,17 @@ require 'socket'
5
5
  require_relative './io'
6
6
  require_relative '../core/thread_pool'
7
7
 
8
- class ::BasicSocket
9
- def write_nonblock(string, _options = {})
10
- write(string)
11
- end
12
-
13
- def read_nonblock(maxlen, str = nil, _options = {})
14
- readpartial(maxlen, str)
15
- end
16
- end
17
-
18
8
  # Socket overrides (eventually rewritten in C)
19
9
  class ::Socket
20
10
  def accept
21
- Thread.current.agent.accept(self)
11
+ Thread.current.backend.accept(self)
22
12
  end
23
13
 
24
14
  NO_EXCEPTION = { exception: false }.freeze
25
15
 
26
- def connect(remotesockaddr)
27
- Thread.current.agent.connect(self, remotesockaddr.ip_address, remotesockaddr.ip_port)
16
+ def connect(addr)
17
+ addr = Addrinfo.new(addr) if addr.is_a?(String)
18
+ Thread.current.backend.connect(self, addr.ip_address, addr.ip_port)
28
19
  end
29
20
 
30
21
  def recv(maxlen, flags = 0, outbuf = nil)
@@ -33,7 +24,7 @@ class ::Socket
33
24
  result = recv_nonblock(maxlen, flags, outbuf, **NO_EXCEPTION)
34
25
  case result
35
26
  when nil then raise IOError
36
- when :wait_readable then Thread.current.agent.wait_io(self, false)
27
+ when :wait_readable then Thread.current.backend.wait_io(self, false)
37
28
  else
38
29
  return result
39
30
  end
@@ -46,7 +37,7 @@ class ::Socket
46
37
  result = recvfrom_nonblock(maxlen, flags, @read_buffer, **NO_EXCEPTION)
47
38
  case result
48
39
  when nil then raise IOError
49
- when :wait_readable then Thread.current.agent.wait_io(self, false)
40
+ when :wait_readable then Thread.current.backend.wait_io(self, false)
50
41
  else
51
42
  return result
52
43
  end
@@ -128,6 +119,14 @@ class ::TCPSocket
128
119
  def reuse_port
129
120
  setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, 1)
130
121
  end
122
+
123
+ def read_nonblock(len, str = nil, exception: true)
124
+ @io.read_nonblock(len, str, exception: exception)
125
+ end
126
+
127
+ def write_nonblock(buf, exception: true)
128
+ @io.write_nonblock(buf, exception: exception)
129
+ end
131
130
  end
132
131
 
133
132
  # Override stock TCPServer code by encapsulating a Socket instance.
@@ -16,21 +16,22 @@ class ::Thread
16
16
  end
17
17
 
18
18
  def execute
19
- # agent must be created in the context of the new thread, therefore it
19
+ # backend must be created in the context of the new thread, therefore it
20
20
  # cannot be created in Thread#initialize
21
- @agent = Polyphony::Agent.new
21
+ @backend = Polyphony::Backend.new
22
22
  setup
23
23
  @ready = true
24
24
  result = @block.(*@args)
25
25
  rescue Polyphony::MoveOn, Polyphony::Terminate => e
26
26
  result = e.value
27
- rescue Exception => result
27
+ rescue Exception => e
28
+ result = e
28
29
  ensure
29
30
  @ready = true
30
31
  finalize(result)
31
32
  end
32
33
 
33
- attr_accessor :agent
34
+ attr_accessor :backend
34
35
 
35
36
  def setup
36
37
  @main_fiber = Fiber.current
@@ -48,7 +49,7 @@ class ::Thread
48
49
  @result = result
49
50
  signal_waiters(result)
50
51
  end
51
- @agent.finalize
52
+ @backend.finalize
52
53
  end
53
54
 
54
55
  def signal_waiters(result)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.43.11'
4
+ VERSION = '0.45.4'
5
5
  end
@@ -21,17 +21,21 @@ Gem::Specification.new do |s|
21
21
  s.require_paths = ["lib"]
22
22
  s.required_ruby_version = '>= 2.6'
23
23
 
24
- s.add_development_dependency 'httparty', '0.17.0'
25
- s.add_development_dependency 'localhost', '1.1.4'
24
+ s.add_development_dependency 'rake-compiler', '1.1.1'
26
25
  s.add_development_dependency 'minitest', '5.13.0'
27
26
  s.add_development_dependency 'minitest-reporters', '1.4.2'
28
27
  s.add_development_dependency 'simplecov', '0.17.1'
29
28
  s.add_development_dependency 'rubocop', '0.85.1'
29
+ s.add_development_dependency 'pry', '0.13.1'
30
+
30
31
  s.add_development_dependency 'pg', '1.1.4'
31
- s.add_development_dependency 'rake-compiler', '1.0.5'
32
32
  s.add_development_dependency 'redis', '4.1.0'
33
33
  s.add_development_dependency 'hiredis', '0.6.3'
34
34
  s.add_development_dependency 'http_parser.rb', '~>0.6.0'
35
+ s.add_development_dependency 'rack', '>=2.0.8', '<2.3.0'
36
+ s.add_development_dependency 'mysql2', '0.5.3'
37
+ s.add_development_dependency 'sequel', '5.34.0'
38
+ s.add_development_dependency 'httparty', '0.17.1'
35
39
 
36
40
  s.add_development_dependency 'jekyll', '~>3.8.6'
37
41
  s.add_development_dependency 'jekyll-remote-theme', '~>0.4.1'