polyphony 0.43.11 → 0.45.4
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -1
- data/CHANGELOG.md +40 -0
- data/Gemfile.lock +18 -8
- data/Rakefile +1 -1
- data/TODO.md +22 -9
- data/docs/_posts/2020-07-26-polyphony-0.44.md +77 -0
- data/docs/api-reference/thread.md +1 -1
- data/docs/getting-started/overview.md +14 -14
- data/docs/getting-started/tutorial.md +1 -1
- data/examples/adapters/redis_client.rb +3 -1
- data/examples/adapters/redis_pubsub_perf.rb +11 -8
- data/examples/adapters/sequel_mysql.rb +23 -0
- data/examples/adapters/sequel_mysql_pool.rb +33 -0
- data/examples/adapters/sequel_pg.rb +24 -0
- data/examples/core/{02-awaiting-fibers.rb → await.rb} +0 -0
- data/examples/core/{xx-channels.rb → channels.rb} +0 -0
- data/examples/core/deferring-an-operation.rb +16 -0
- data/examples/core/{xx-erlang-style-genserver.rb → erlang-style-genserver.rb} +16 -9
- data/examples/core/{xx-forking.rb → forking.rb} +1 -1
- data/examples/core/handling-signals.rb +11 -0
- data/examples/core/{03-interrupting.rb → interrupt.rb} +0 -0
- data/examples/core/{xx-pingpong.rb → pingpong.rb} +7 -5
- data/examples/core/{xx-recurrent-timer.rb → recurrent-timer.rb} +1 -1
- data/examples/core/{xx-resource_delegate.rb → resource_delegate.rb} +3 -4
- data/examples/core/{01-spinning-up-fibers.rb → spin.rb} +1 -1
- data/examples/core/{xx-spin_error_backtrace.rb → spin_error_backtrace.rb} +1 -1
- data/examples/core/{xx-supervise-process.rb → supervise-process.rb} +8 -5
- data/examples/core/supervisor.rb +20 -0
- data/examples/core/{xx-thread-sleep.rb → thread-sleep.rb} +0 -0
- data/examples/core/{xx-thread_pool.rb → thread_pool.rb} +0 -0
- data/examples/core/{xx-throttling.rb → throttling.rb} +0 -0
- data/examples/core/{xx-timeout.rb → timeout.rb} +0 -0
- data/examples/core/{xx-using-a-mutex.rb → using-a-mutex.rb} +0 -0
- data/examples/core/{xx-worker-thread.rb → worker-thread.rb} +2 -2
- data/examples/io/{xx-backticks.rb → backticks.rb} +0 -0
- data/examples/io/{xx-echo_client.rb → echo_client.rb} +1 -1
- data/examples/io/{xx-echo_client_from_stdin.rb → echo_client_from_stdin.rb} +2 -2
- data/examples/io/{xx-echo_pipe.rb → echo_pipe.rb} +1 -1
- data/examples/io/{xx-echo_server.rb → echo_server.rb} +0 -0
- data/examples/io/{xx-echo_server_with_timeout.rb → echo_server_with_timeout.rb} +1 -1
- data/examples/io/{xx-echo_stdin.rb → echo_stdin.rb} +0 -0
- data/examples/io/{xx-happy-eyeballs.rb → happy-eyeballs.rb} +0 -0
- data/examples/io/{xx-httparty.rb → httparty.rb} +4 -13
- data/examples/io/{xx-irb.rb → irb.rb} +0 -0
- data/examples/io/{xx-net-http.rb → net-http.rb} +0 -0
- data/examples/io/{xx-open.rb → open.rb} +0 -0
- data/examples/io/pry.rb +18 -0
- data/examples/io/rack_server.rb +71 -0
- data/examples/io/raw.rb +14 -0
- data/examples/io/reline.rb +18 -0
- data/examples/io/{xx-system.rb → system.rb} +1 -1
- data/examples/io/{xx-tcpserver.rb → tcpserver.rb} +0 -0
- data/examples/io/{xx-tcpsocket.rb → tcpsocket.rb} +0 -0
- data/examples/io/tunnel.rb +6 -1
- data/examples/io/{xx-zip.rb → zip.rb} +0 -0
- data/examples/performance/fiber_transfer.rb +2 -1
- data/examples/performance/fs_read.rb +5 -6
- data/examples/{io/xx-switch.rb → performance/switch.rb} +2 -1
- data/examples/performance/thread-vs-fiber/{xx-httparty_multi.rb → httparty_multi.rb} +3 -4
- data/examples/performance/thread-vs-fiber/{xx-httparty_threaded.rb → httparty_threaded.rb} +0 -0
- data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +1 -1
- data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -5
- data/examples/performance/thread_pool_perf.rb +6 -7
- data/ext/polyphony/backend.h +40 -0
- data/ext/polyphony/event.c +3 -3
- data/ext/polyphony/extconf.rb +1 -1
- data/ext/polyphony/fiber.c +66 -6
- data/ext/polyphony/{libev_agent.c → libev_backend.c} +237 -238
- data/ext/polyphony/polyphony.c +3 -3
- data/ext/polyphony/polyphony.h +15 -20
- data/ext/polyphony/polyphony_ext.c +3 -4
- data/ext/polyphony/queue.c +5 -6
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/thread.c +36 -33
- data/lib/polyphony.rb +26 -39
- data/lib/polyphony/adapters/fs.rb +1 -1
- data/lib/polyphony/adapters/irb.rb +2 -17
- data/lib/polyphony/adapters/mysql2.rb +19 -0
- data/lib/polyphony/adapters/postgres.rb +5 -5
- data/lib/polyphony/adapters/process.rb +2 -5
- data/lib/polyphony/adapters/readline.rb +17 -0
- data/lib/polyphony/adapters/redis.rb +1 -1
- data/lib/polyphony/adapters/sequel.rb +45 -0
- data/lib/polyphony/core/exceptions.rb +11 -0
- data/lib/polyphony/core/global_api.rb +17 -12
- data/lib/polyphony/core/resource_pool.rb +20 -7
- data/lib/polyphony/core/sync.rb +46 -8
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/extensions/core.rb +30 -30
- data/lib/polyphony/extensions/fiber.rb +30 -49
- data/lib/polyphony/extensions/io.rb +60 -16
- data/lib/polyphony/extensions/openssl.rb +6 -6
- data/lib/polyphony/extensions/socket.rb +14 -15
- data/lib/polyphony/extensions/thread.rb +6 -5
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +7 -3
- data/test/helper.rb +1 -1
- data/test/{test_agent.rb → test_backend.rb} +22 -22
- data/test/test_fiber.rb +29 -12
- data/test/test_io.rb +59 -1
- data/test/test_kernel.rb +5 -0
- data/test/test_resource_pool.rb +29 -4
- data/test/test_signal.rb +16 -37
- data/test/test_socket.rb +17 -0
- data/test/test_sync.rb +52 -0
- metadata +127 -97
- data/.gitbook.yaml +0 -4
- data/examples/adapters/concurrent-ruby.rb +0 -9
- data/examples/core/04-handling-signals.rb +0 -19
- data/examples/core/xx-agent.rb +0 -102
- data/examples/core/xx-at_exit.rb +0 -29
- data/examples/core/xx-caller.rb +0 -12
- data/examples/core/xx-daemon.rb +0 -14
- data/examples/core/xx-deadlock.rb +0 -8
- data/examples/core/xx-deferring-an-operation.rb +0 -14
- data/examples/core/xx-exception-backtrace.rb +0 -40
- data/examples/core/xx-fork-cleanup.rb +0 -22
- data/examples/core/xx-fork-spin.rb +0 -42
- data/examples/core/xx-fork-terminate.rb +0 -27
- data/examples/core/xx-move_on.rb +0 -23
- data/examples/core/xx-queue-async.rb +0 -120
- data/examples/core/xx-readpartial.rb +0 -18
- data/examples/core/xx-signals.rb +0 -16
- data/examples/core/xx-sleep-forever.rb +0 -9
- data/examples/core/xx-sleeping.rb +0 -25
- data/examples/core/xx-snooze-starve.rb +0 -16
- data/examples/core/xx-spin-fork.rb +0 -49
- data/examples/core/xx-state-machine.rb +0 -51
- data/examples/core/xx-stop.rb +0 -20
- data/examples/core/xx-supervisors.rb +0 -21
- data/examples/core/xx-thread-selector-sleep.rb +0 -51
- data/examples/core/xx-thread-selector-snooze.rb +0 -46
- data/examples/core/xx-thread-snooze.rb +0 -34
- data/examples/core/xx-timer-gc.rb +0 -17
- data/examples/core/xx-trace.rb +0 -79
- data/examples/performance/xx-array.rb +0 -11
- data/examples/performance/xx-fiber-switch.rb +0 -9
- data/examples/performance/xx-snooze.rb +0 -15
- data/examples/xx-spin.rb +0 -32
- 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
|
-
|
|
192
|
-
|
|
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
|
-
|
|
212
|
+
results = @children.dup
|
|
225
213
|
@on_child_done = proc do |c, r|
|
|
226
|
-
|
|
227
|
-
|
|
214
|
+
results[c] = r
|
|
215
|
+
schedule if @children.empty?
|
|
228
216
|
end
|
|
229
217
|
suspend
|
|
230
218
|
@on_child_done = nil
|
|
231
|
-
|
|
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 =
|
|
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
|
|
324
|
-
|
|
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
|
-
|
|
94
|
-
|
|
93
|
+
alias_method :orig_getbyte, :getbyte
|
|
94
|
+
def getbyte
|
|
95
|
+
char = getc
|
|
96
|
+
char ? char.getbyte(0) : nil
|
|
97
|
+
end
|
|
95
98
|
|
|
96
|
-
|
|
97
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
183
|
+
write LINEFEED
|
|
170
184
|
return
|
|
171
185
|
end
|
|
172
186
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
32
|
-
when :wait_writable then Thread.current.
|
|
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.
|
|
44
|
-
when :wait_writable then Thread.current.
|
|
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.
|
|
55
|
-
when :wait_writable then Thread.current.
|
|
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.
|
|
11
|
+
Thread.current.backend.accept(self)
|
|
22
12
|
end
|
|
23
13
|
|
|
24
14
|
NO_EXCEPTION = { exception: false }.freeze
|
|
25
15
|
|
|
26
|
-
def connect(
|
|
27
|
-
|
|
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.
|
|
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.
|
|
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
|
-
#
|
|
19
|
+
# backend must be created in the context of the new thread, therefore it
|
|
20
20
|
# cannot be created in Thread#initialize
|
|
21
|
-
@
|
|
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 =>
|
|
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 :
|
|
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
|
-
@
|
|
52
|
+
@backend.finalize
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
def signal_waiters(result)
|
data/lib/polyphony/version.rb
CHANGED
data/polyphony.gemspec
CHANGED
|
@@ -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 '
|
|
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'
|