polyphony 0.79 → 0.81.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/Gemfile.lock +2 -1
- data/examples/core/raw_buffer_test.rb +8 -0
- data/examples/core/zlib_stream.rb +16 -0
- data/ext/polyphony/backend_common.c +2 -1
- data/ext/polyphony/backend_common.h +7 -2
- data/ext/polyphony/backend_io_uring.c +69 -30
- data/ext/polyphony/polyphony.c +8 -0
- data/ext/polyphony/polyphony.h +11 -0
- data/lib/polyphony/adapters/fs.rb +4 -0
- data/lib/polyphony/adapters/process.rb +14 -1
- data/lib/polyphony/adapters/redis.rb +28 -0
- data/lib/polyphony/adapters/sequel.rb +19 -1
- data/lib/polyphony/core/debug.rb +129 -72
- data/lib/polyphony/core/exceptions.rb +21 -6
- data/lib/polyphony/core/global_api.rb +228 -73
- data/lib/polyphony/core/resource_pool.rb +65 -20
- data/lib/polyphony/core/sync.rb +57 -12
- data/lib/polyphony/core/thread_pool.rb +42 -5
- data/lib/polyphony/core/throttler.rb +21 -5
- data/lib/polyphony/core/timer.rb +125 -1
- data/lib/polyphony/extensions/exception.rb +36 -6
- data/lib/polyphony/extensions/fiber.rb +238 -57
- data/lib/polyphony/extensions/io.rb +4 -2
- data/lib/polyphony/extensions/kernel.rb +9 -4
- data/lib/polyphony/extensions/object.rb +8 -0
- data/lib/polyphony/extensions/openssl.rb +3 -1
- data/lib/polyphony/extensions/socket.rb +458 -39
- data/lib/polyphony/extensions/thread.rb +108 -43
- data/lib/polyphony/extensions/timeout.rb +12 -1
- data/lib/polyphony/extensions.rb +1 -0
- data/lib/polyphony/net.rb +66 -7
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +0 -2
- data/test/test_backend.rb +6 -2
- data/test/test_global_api.rb +0 -23
- data/test/test_resource_pool.rb +1 -1
- data/test/test_throttler.rb +0 -6
- data/test/test_trace.rb +87 -0
- metadata +10 -8
- data/lib/polyphony/core/channel.rb +0 -15
@@ -3,12 +3,13 @@
|
|
3
3
|
require_relative '../core/exceptions'
|
4
4
|
|
5
5
|
module Polyphony
|
6
|
-
|
6
|
+
|
7
|
+
# Fiber control methods
|
7
8
|
module FiberControl
|
8
9
|
# Returns the fiber's monitoring mailbox queue, used for receiving fiber
|
9
10
|
# monitoring messages.
|
10
11
|
#
|
11
|
-
# @return [Polyphony::Queue]
|
12
|
+
# @return [Polyphony::Queue] monitoring mailbox queue
|
12
13
|
def monitor_mailbox
|
13
14
|
@monitor_mailbox ||= Polyphony::Queue.new
|
14
15
|
end
|
@@ -16,12 +17,13 @@ module Polyphony
|
|
16
17
|
# call-seq:
|
17
18
|
# fiber.stop(value = nil) -> fiber
|
18
19
|
# Fiber.interrupt(value = nil) -> fiber
|
20
|
+
# Fiber.move_on(value = nil) -> fiber
|
19
21
|
#
|
20
|
-
# Stops the fiber by raising a Polyphony::MoveOn exception. The given
|
21
|
-
# will become the fiber's return value.
|
22
|
+
# Stops the fiber by raising a `Polyphony::MoveOn` exception. The given
|
23
|
+
# value will become the fiber's return value.
|
22
24
|
#
|
23
|
-
# @param value [any]
|
24
|
-
# @return [Fiber]
|
25
|
+
# @param value [any] fiber's eventual return value
|
26
|
+
# @return [Fiber] self
|
25
27
|
def interrupt(value = nil)
|
26
28
|
return if @running == false
|
27
29
|
|
@@ -29,6 +31,7 @@ module Polyphony
|
|
29
31
|
self
|
30
32
|
end
|
31
33
|
alias_method :stop, :interrupt
|
34
|
+
alias_method :move_on, :interrupt
|
32
35
|
|
33
36
|
# call-seq:
|
34
37
|
# fiber.reset(value = nil) -> fiber
|
@@ -56,24 +59,27 @@ module Polyphony
|
|
56
59
|
|
57
60
|
# Stops a fiber by raising a Polyphony::Cancel exception.
|
58
61
|
#
|
59
|
-
# @
|
60
|
-
|
62
|
+
# @param exception [Class, Exception] exception or exception class
|
63
|
+
# @return [Fiber] self
|
64
|
+
def cancel(exception = Polyphony::Cancel)
|
61
65
|
return if @running == false
|
62
66
|
|
63
|
-
|
67
|
+
value = (Class === exception) ? exception.new : exception
|
68
|
+
schedule value
|
64
69
|
self
|
65
70
|
end
|
66
71
|
|
67
72
|
# Sets the graceful shutdown flag for the fiber.
|
68
73
|
#
|
69
74
|
# @param graceful [bool] Whether or not to perform a graceful shutdown
|
75
|
+
# @return [bool] graceful
|
70
76
|
def graceful_shutdown=(graceful)
|
71
77
|
@graceful_shutdown = graceful
|
72
78
|
end
|
73
79
|
|
74
80
|
# Returns the graceful shutdown flag for the fiber.
|
75
81
|
#
|
76
|
-
# @return [bool]
|
82
|
+
# @return [bool] true if graceful shutdown, otherwise false
|
77
83
|
def graceful_shutdown?
|
78
84
|
@graceful_shutdown
|
79
85
|
end
|
@@ -81,7 +87,7 @@ module Polyphony
|
|
81
87
|
# Terminates the fiber, optionally setting the graceful shutdown flag.
|
82
88
|
#
|
83
89
|
# @param graceful [bool] Whether to perform a graceful shutdown
|
84
|
-
# @return [Fiber]
|
90
|
+
# @return [Fiber] self
|
85
91
|
def terminate(graceful = false)
|
86
92
|
return if @running == false
|
87
93
|
|
@@ -96,15 +102,36 @@ module Polyphony
|
|
96
102
|
# fiber.raise(exception_class, exception_message) -> fiber
|
97
103
|
# fiber.raise(exception) -> fiber
|
98
104
|
#
|
99
|
-
# Raises an exception in the context of the fiber
|
105
|
+
# Raises an exception in the context of the fiber
|
100
106
|
#
|
101
|
-
# @return [Fiber]
|
107
|
+
# @return [Fiber] self
|
102
108
|
def raise(*args)
|
103
109
|
error = error_from_raise_args(args)
|
104
110
|
schedule(error)
|
105
111
|
self
|
106
112
|
end
|
107
113
|
|
114
|
+
# Adds an interjection to the fiber. The current operation undertaken by the
|
115
|
+
# fiber will be interrupted, and the given block will be executed, and the
|
116
|
+
# operation will be resumed. This API is experimental and might be removed
|
117
|
+
# in the future.
|
118
|
+
#
|
119
|
+
# @param &block [Proc] given block
|
120
|
+
# @return [Fiber] self
|
121
|
+
def interject(&block)
|
122
|
+
raise Polyphony::Interjection.new(block)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Blocks until the fiber has terminated, returning its return value.
|
126
|
+
#
|
127
|
+
# @return [any] fiber's return value
|
128
|
+
def await
|
129
|
+
Fiber.await(self).first
|
130
|
+
end
|
131
|
+
alias_method :join, :await
|
132
|
+
|
133
|
+
private
|
134
|
+
|
108
135
|
# :no-doc:
|
109
136
|
def error_from_raise_args(args)
|
110
137
|
case (arg = args.shift)
|
@@ -114,19 +141,41 @@ module Polyphony
|
|
114
141
|
else RuntimeError.new
|
115
142
|
end
|
116
143
|
end
|
117
|
-
|
118
|
-
def interject(&block)
|
119
|
-
raise Polyphony::Interjection.new(block)
|
120
|
-
end
|
121
|
-
|
122
|
-
def await
|
123
|
-
Fiber.await(self).first
|
124
|
-
end
|
125
|
-
alias_method :join, :await
|
126
144
|
end
|
127
145
|
|
128
|
-
# Fiber supervision
|
146
|
+
# Fiber supervision methods
|
129
147
|
module FiberSupervision
|
148
|
+
|
149
|
+
# call-seq:
|
150
|
+
# fiber.supervise
|
151
|
+
# fiber.supervise(fiber_a, fiber_b)
|
152
|
+
# fiber.supervise { |f, r| handle_terminated_fiber(f, r) }
|
153
|
+
# fiber.supervise(on_done: ->(f, r) { handle_terminated_fiber(f, r) })
|
154
|
+
# fiber.supervise(on_error: ->(f, e) { handle_error(f, e) })
|
155
|
+
# fiber.supervise(*fibers, restart: always)
|
156
|
+
# fiber.supervise(*fibers, restart: on_error)
|
157
|
+
#
|
158
|
+
# Supervises the given fibers or all child fibers. The fiber is put in
|
159
|
+
# supervision mode, which means any child added after calling `#supervise`
|
160
|
+
# will automatically be supervised. Depending on the given options, fibers
|
161
|
+
# may be automatically restarted.
|
162
|
+
#
|
163
|
+
# If a block is given, the block is called whenever a supervised fiber has
|
164
|
+
# terminated. If the `:on_done` option is given, that proc will be called
|
165
|
+
# when a supervised fiber has terminated. If the `:on_error` option is
|
166
|
+
# given, that proc will be called when a supervised fiber has terminated
|
167
|
+
# with an uncaught exception. If the `:restart` option equals `:always`,
|
168
|
+
# fibers will always be restarted. If the `:restart` option equals
|
169
|
+
# `:on_error`, fibers will be restarted only when terminated with an
|
170
|
+
# uncaught exception.
|
171
|
+
#
|
172
|
+
# This method blocks indefinitely.
|
173
|
+
#
|
174
|
+
# @param *fibers [Array<Fiber>] fibers to supervise
|
175
|
+
# @param on_done: [Proc, nil] proc to call when a supervised fiber is terminated
|
176
|
+
# @param on_error: [Proc, nil] proc to call when a supervised fiber is terminated with an exception
|
177
|
+
# @param restart: [:always, :on_error, nil] whether to restart terminated fibers
|
178
|
+
# @return [void]
|
130
179
|
def supervise(*fibers, **opts, &block)
|
131
180
|
block ||= supervise_opts_to_block(opts)
|
132
181
|
|
@@ -147,6 +196,9 @@ module Polyphony
|
|
147
196
|
@supervise_mode = false
|
148
197
|
end
|
149
198
|
|
199
|
+
private
|
200
|
+
|
201
|
+
# :no-doc:
|
150
202
|
def supervise_opts_to_block(opts)
|
151
203
|
block = opts[:on_done] || opts[:on_error]
|
152
204
|
restart = opts[:restart]
|
@@ -164,8 +216,9 @@ module Polyphony
|
|
164
216
|
end
|
165
217
|
end
|
166
218
|
|
167
|
-
#
|
219
|
+
# Fiber control class methods
|
168
220
|
module FiberControlClassMethods
|
221
|
+
|
169
222
|
# call-seq:
|
170
223
|
# Fiber.await(*fibers) -> [*results]
|
171
224
|
# Fiber.join(*fibers) -> [*results]
|
@@ -247,6 +300,9 @@ module Polyphony
|
|
247
300
|
# running, it will bubble up to the main thread's main fiber, which will
|
248
301
|
# also be scheduled with priority. This method is mainly used trapping
|
249
302
|
# signals (see also the patched `Kernel#trap`)
|
303
|
+
#
|
304
|
+
# @param &block [Proc] given block
|
305
|
+
# @return [void]
|
250
306
|
def schedule_priority_oob_fiber(&block)
|
251
307
|
oob_fiber = Fiber.new do
|
252
308
|
Fiber.current.setup_raw
|
@@ -264,6 +320,9 @@ module Polyphony
|
|
264
320
|
oob_fiber.schedule_with_priority(nil)
|
265
321
|
end
|
266
322
|
|
323
|
+
private
|
324
|
+
|
325
|
+
# :no-doc:
|
267
326
|
def prepare_oob_fiber(fiber, block)
|
268
327
|
fiber.oob = true
|
269
328
|
fiber.tag = :oob
|
@@ -273,21 +332,24 @@ module Polyphony
|
|
273
332
|
end
|
274
333
|
end
|
275
334
|
|
276
|
-
#
|
335
|
+
# Child fiber control methods
|
277
336
|
module ChildFiberControl
|
337
|
+
|
338
|
+
# Returns the fiber's children.
|
339
|
+
#
|
340
|
+
# @return [Array<Fiber>] child fibers
|
278
341
|
def children
|
279
342
|
(@children ||= {}).keys
|
280
343
|
end
|
281
344
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
345
|
+
# Creates a new child fiber.
|
346
|
+
#
|
347
|
+
# child = fiber.spin { sleep 10; fiber.stop }
|
348
|
+
#
|
349
|
+
# @param tag [any] child fiber's tag
|
350
|
+
# @param orig_caller [Array<String>] caller to set for fiber
|
351
|
+
# @param &block [Proc] child fiber's block
|
352
|
+
# @return [Fiber] child fiber
|
291
353
|
def spin(tag = nil, orig_caller = Kernel.caller, &block)
|
292
354
|
f = Fiber.new { |v| f.run(v) }
|
293
355
|
f.prepare(tag, block, orig_caller, self)
|
@@ -296,24 +358,37 @@ module Polyphony
|
|
296
358
|
f
|
297
359
|
end
|
298
360
|
|
361
|
+
# Terminates all child fibers. This method will return before the fibers are
|
362
|
+
# actually terminated.
|
363
|
+
#
|
364
|
+
# @param graceful [bool] whether to perform a graceful termination
|
365
|
+
# @return [Fiber] self
|
299
366
|
def terminate_all_children(graceful = false)
|
300
|
-
return unless @children
|
367
|
+
return self unless @children
|
301
368
|
|
302
369
|
e = Polyphony::Terminate.new
|
303
370
|
@children.each_key do |c|
|
304
371
|
c.graceful_shutdown = true if graceful
|
305
372
|
c.raise e
|
306
373
|
end
|
374
|
+
self
|
307
375
|
end
|
308
376
|
|
377
|
+
# Block until all child fibers have terminated. Returns the return values
|
378
|
+
# for all child fibers.
|
379
|
+
#
|
380
|
+
# @return [Array<any>] return values of child fibers
|
309
381
|
def await_all_children
|
310
382
|
return unless @children && !@children.empty?
|
311
383
|
|
312
384
|
Fiber.await(*@children.keys.reject { |c| c.dead? })
|
313
385
|
end
|
314
386
|
|
387
|
+
# Terminates and blocks until all child fibers have terminated.
|
388
|
+
#
|
389
|
+
# @return [Fiber] self
|
315
390
|
def shutdown_all_children(graceful = false)
|
316
|
-
return unless @children
|
391
|
+
return self unless @children
|
317
392
|
|
318
393
|
@children.keys.each do |c|
|
319
394
|
next if c.dead?
|
@@ -321,12 +396,22 @@ module Polyphony
|
|
321
396
|
c.terminate(graceful)
|
322
397
|
c.await
|
323
398
|
end
|
399
|
+
self
|
324
400
|
end
|
325
401
|
|
326
|
-
|
327
|
-
|
402
|
+
# Attaches all child fibers to a new parent.
|
403
|
+
#
|
404
|
+
# @param parent [Fiber] new parent
|
405
|
+
# @return [Fiber] self
|
406
|
+
def attach_all_children_to(parent)
|
407
|
+
@children&.keys.each { |c| c.attach_to(parent) }
|
408
|
+
self
|
328
409
|
end
|
329
410
|
|
411
|
+
# Detaches the fiber from its current parent. The fiber will be made a child
|
412
|
+
# of the main fiber (for the current thread.)
|
413
|
+
#
|
414
|
+
# @return [Fiber] self
|
330
415
|
def detach
|
331
416
|
@parent.remove_child(self)
|
332
417
|
@parent = @thread.main_fiber
|
@@ -334,22 +419,58 @@ module Polyphony
|
|
334
419
|
self
|
335
420
|
end
|
336
421
|
|
337
|
-
|
422
|
+
# Attaches the fiber to a new parent.
|
423
|
+
#
|
424
|
+
# @param parent [Fiber] new parent
|
425
|
+
# @return [Fiber] self
|
426
|
+
def attach_to(parent)
|
338
427
|
@parent.remove_child(self)
|
339
|
-
@parent =
|
340
|
-
|
428
|
+
@parent = parent
|
429
|
+
parent.add_child(self)
|
430
|
+
self
|
341
431
|
end
|
342
432
|
|
343
|
-
|
433
|
+
# Attaches the fiber to the new parent and monitors the new parent.
|
434
|
+
#
|
435
|
+
# @param parent [Fiber] new parent
|
436
|
+
# @return [Fiber] self
|
437
|
+
def attach_and_monitor(parent)
|
344
438
|
@parent.remove_child(self)
|
345
|
-
@parent =
|
346
|
-
|
347
|
-
monitor(
|
439
|
+
@parent = parent
|
440
|
+
parent.add_child(self)
|
441
|
+
monitor(parent)
|
442
|
+
self
|
443
|
+
end
|
444
|
+
|
445
|
+
# Adds a child fiber reference. Used internally.
|
446
|
+
#
|
447
|
+
# @param child_fiber [Fiber] child fiber
|
448
|
+
# @return [Fiber] self
|
449
|
+
def add_child(child_fiber)
|
450
|
+
(@children ||= {})[child_fiber] = true
|
451
|
+
child_fiber.monitor(self) if @supervise_mode
|
452
|
+
self
|
453
|
+
end
|
454
|
+
|
455
|
+
# Removes a child fiber reference. Used internally.
|
456
|
+
#
|
457
|
+
# @param parent [Fiber] new parent
|
458
|
+
# @return [Fiber] self
|
459
|
+
def remove_child(child_fiber)
|
460
|
+
@children.delete(child_fiber) if @children
|
348
461
|
end
|
349
462
|
end
|
350
463
|
|
351
464
|
# Fiber life cycle methods
|
352
465
|
module FiberLifeCycle
|
466
|
+
|
467
|
+
# Prepares a fiber for running.
|
468
|
+
#
|
469
|
+
# @param tag [any] fiber's tag
|
470
|
+
# @param block [Proc] fiber's block
|
471
|
+
# @param caller [Array<String>] fiber's caller
|
472
|
+
# @param parent [Fiber] fiber's parent
|
473
|
+
# @return [void]
|
353
474
|
def prepare(tag, block, caller, parent)
|
354
475
|
@thread = Thread.current
|
355
476
|
@tag = tag
|
@@ -360,35 +481,40 @@ module Polyphony
|
|
360
481
|
schedule
|
361
482
|
end
|
362
483
|
|
484
|
+
# Runs the fiber's block and handles uncaught exceptions.
|
485
|
+
#
|
486
|
+
# @param first_value [any] value passed to fiber on first resume
|
487
|
+
# @return [void]
|
363
488
|
def run(first_value)
|
364
|
-
|
489
|
+
Kernel.raise first_value if first_value.is_a?(Exception)
|
490
|
+
@running = true
|
491
|
+
|
365
492
|
Thread.backend.trace(:unblock, self, first_value, @caller)
|
366
493
|
result = @block.(first_value)
|
367
|
-
finalize
|
494
|
+
finalize(result)
|
368
495
|
rescue Polyphony::Restart => e
|
369
496
|
restart_self(e.value)
|
370
497
|
rescue Polyphony::MoveOn, Polyphony::Terminate => e
|
371
|
-
finalize
|
498
|
+
finalize(e.value)
|
372
499
|
rescue Exception => e
|
373
500
|
e.source_fiber = self
|
374
|
-
finalize
|
375
|
-
end
|
376
|
-
|
377
|
-
def setup(first_value)
|
378
|
-
Kernel.raise first_value if first_value.is_a?(Exception)
|
379
|
-
|
380
|
-
@running = true
|
501
|
+
finalize(e, true)
|
381
502
|
end
|
382
503
|
|
383
504
|
# Performs setup for a "raw" Fiber created using Fiber.new. Note that this
|
384
505
|
# fiber is an orphan fiber (has no parent), since we cannot control how the
|
385
506
|
# fiber terminates after it has already been created. Calling #setup_raw
|
386
507
|
# allows the fiber to be scheduled and to receive messages.
|
508
|
+
#
|
509
|
+
# @return [void]
|
387
510
|
def setup_raw
|
388
511
|
@thread = Thread.current
|
389
512
|
@running = true
|
390
513
|
end
|
391
514
|
|
515
|
+
# Sets up the fiber as the main fiber for the current thread.
|
516
|
+
#
|
517
|
+
# @return [void]
|
392
518
|
def setup_main_fiber
|
393
519
|
@main = true
|
394
520
|
@tag = :main
|
@@ -397,11 +523,20 @@ module Polyphony
|
|
397
523
|
@children&.clear
|
398
524
|
end
|
399
525
|
|
526
|
+
# Resets the fiber's state and reruns the fiber.
|
527
|
+
#
|
528
|
+
# @param first_value [Fiber] first_value to pass to fiber after restarting
|
529
|
+
# @return [void]
|
400
530
|
def restart_self(first_value)
|
401
531
|
@mailbox = nil
|
402
532
|
run(first_value)
|
403
533
|
end
|
404
534
|
|
535
|
+
# Finalizes the fiber, handling its return value or any uncaught exception.
|
536
|
+
#
|
537
|
+
# @param result [any] return value
|
538
|
+
# @param uncaught_exception [Exception, nil] uncaught exception
|
539
|
+
# @return [void]
|
405
540
|
def finalize(result, uncaught_exception = false)
|
406
541
|
result, uncaught_exception = finalize_children(result, uncaught_exception)
|
407
542
|
Thread.backend.trace(:terminate, self, result)
|
@@ -419,6 +554,10 @@ module Polyphony
|
|
419
554
|
# Shuts down all children of the current fiber. If any exception occurs while
|
420
555
|
# the children are shut down, it is returned along with the uncaught_exception
|
421
556
|
# flag set. Otherwise, it returns the given arguments.
|
557
|
+
#
|
558
|
+
# @param result [any] fiber's return value
|
559
|
+
# @param uncaught_exception [Exception, nil] uncaught exception
|
560
|
+
# @return [void]
|
422
561
|
def finalize_children(result, uncaught_exception)
|
423
562
|
shutdown_all_children(graceful_shutdown?)
|
424
563
|
[result, uncaught_exception]
|
@@ -426,6 +565,11 @@ module Polyphony
|
|
426
565
|
[e, true]
|
427
566
|
end
|
428
567
|
|
568
|
+
# Informs the fiber's monitors it is terminated.
|
569
|
+
#
|
570
|
+
# @param result [any] fiber's return value
|
571
|
+
# @param uncaught_exception [Exception, nil] uncaught exception
|
572
|
+
# @return [void]
|
429
573
|
def inform_monitors(result, uncaught_exception)
|
430
574
|
if @monitors
|
431
575
|
msg = [self, result]
|
@@ -438,18 +582,35 @@ module Polyphony
|
|
438
582
|
end
|
439
583
|
end
|
440
584
|
|
585
|
+
# Adds a fiber to the list of monitoring fibers. Monitoring fibers will be
|
586
|
+
# notified on their monitor mailboxes when the fiber is terminated.
|
587
|
+
#
|
588
|
+
# @param fiber [Fiber] monitoring fiber
|
589
|
+
# @return [Fiber] self
|
441
590
|
def monitor(fiber)
|
442
591
|
(@monitors ||= {})[fiber] = true
|
592
|
+
self
|
443
593
|
end
|
444
594
|
|
595
|
+
# Removes a monitor fiber.
|
596
|
+
#
|
597
|
+
# @param fiber [Fiber] monitoring fiber
|
598
|
+
# @return [Fiber] self
|
445
599
|
def unmonitor(fiber)
|
446
600
|
(@monitors ||= []).delete(fiber)
|
601
|
+
self
|
447
602
|
end
|
448
603
|
|
604
|
+
# Returns the list of monitoring fibers.
|
605
|
+
#
|
606
|
+
# @return [Array<Fiber>] monitoring fibers
|
449
607
|
def monitors
|
450
608
|
@monitors&.keys || []
|
451
609
|
end
|
452
610
|
|
611
|
+
# Returns true if the fiber is dead.
|
612
|
+
#
|
613
|
+
# @return [bool] is fiber dead
|
453
614
|
def dead?
|
454
615
|
state == :dead
|
455
616
|
end
|
@@ -468,10 +629,16 @@ class ::Fiber
|
|
468
629
|
attr_accessor :tag, :thread, :parent, :oob
|
469
630
|
attr_reader :result
|
470
631
|
|
632
|
+
# Returns true if fiber is running.
|
633
|
+
#
|
634
|
+
# @return [bool] is fiber running
|
471
635
|
def running?
|
472
636
|
@running
|
473
637
|
end
|
474
638
|
|
639
|
+
# Returns a string representation of the fiber for debugging.
|
640
|
+
#
|
641
|
+
# @return [String] string representation
|
475
642
|
def inspect
|
476
643
|
if @tag
|
477
644
|
"#<Fiber #{tag}:#{object_id} #{location} (#{state})>"
|
@@ -481,6 +648,9 @@ class ::Fiber
|
|
481
648
|
end
|
482
649
|
alias_method :to_s, :inspect
|
483
650
|
|
651
|
+
# Returns the source location for the fiber based on its caller.
|
652
|
+
#
|
653
|
+
# @return [String] source location
|
484
654
|
def location
|
485
655
|
if @oob
|
486
656
|
"#{@caller[0]} (oob)"
|
@@ -489,6 +659,9 @@ class ::Fiber
|
|
489
659
|
end
|
490
660
|
end
|
491
661
|
|
662
|
+
# Returns the fiber's caller.
|
663
|
+
#
|
664
|
+
# @return [Array<String>] caller
|
492
665
|
def caller
|
493
666
|
spin_caller = @caller || []
|
494
667
|
if @parent
|
@@ -498,10 +671,18 @@ class ::Fiber
|
|
498
671
|
end
|
499
672
|
end
|
500
673
|
|
501
|
-
|
502
|
-
|
674
|
+
# Sets the fiber's caller.
|
675
|
+
#
|
676
|
+
# @param caller [Array<String>] new caller
|
677
|
+
# @return [Fiber] self
|
678
|
+
def set_caller(caller)
|
679
|
+
@caller = caller
|
680
|
+
self
|
503
681
|
end
|
504
682
|
|
683
|
+
# Returns true if the fiber is the main fiber for its thread.
|
684
|
+
#
|
685
|
+
# @return [bool] is main fiber
|
505
686
|
def main?
|
506
687
|
@main
|
507
688
|
end
|
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'open3'
|
4
4
|
|
5
|
-
# IO
|
5
|
+
# IO extensions
|
6
6
|
class ::IO
|
7
7
|
class << self
|
8
8
|
alias_method :orig_binread, :binread
|
9
|
+
|
10
|
+
# TODO: add docs to all methods in this file
|
9
11
|
def binread(name, length = nil, offset = nil)
|
10
12
|
File.open(name, 'rb:ASCII-8BIT') do |f|
|
11
13
|
f.seek(offset) if offset
|
@@ -76,7 +78,7 @@ end
|
|
76
78
|
|
77
79
|
# IO instance method patches
|
78
80
|
class ::IO
|
79
|
-
def
|
81
|
+
def __read_method__
|
80
82
|
:backend_read
|
81
83
|
end
|
82
84
|
|
@@ -7,6 +7,8 @@ module ::Kernel
|
|
7
7
|
alias_method :orig_sleep, :sleep
|
8
8
|
|
9
9
|
alias_method :orig_backtick, :`
|
10
|
+
|
11
|
+
# TODO: add docs to all methods in this file
|
10
12
|
def `(cmd)
|
11
13
|
Open3.popen3(cmd) do |i, o, e, _t|
|
12
14
|
i.close
|
@@ -72,10 +74,6 @@ module ::Kernel
|
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
75
|
-
def pipe_to_eof(src, dest)
|
76
|
-
src.read_loop { |data| dest << data }
|
77
|
-
end
|
78
|
-
|
79
77
|
alias_method :orig_trap, :trap
|
80
78
|
def trap(sig, command = nil, &block)
|
81
79
|
return orig_trap(sig, command) if command.is_a? String
|
@@ -92,4 +90,11 @@ module ::Kernel
|
|
92
90
|
Fiber.schedule_priority_oob_fiber(&block)
|
93
91
|
end
|
94
92
|
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# :no-doc:
|
97
|
+
def pipe_to_eof(src, dest)
|
98
|
+
src.read_loop { |data| dest << data }
|
99
|
+
end
|
95
100
|
end
|
@@ -5,11 +5,13 @@ require_relative './socket'
|
|
5
5
|
|
6
6
|
# OpenSSL socket helper methods (to make it compatible with Socket API) and overrides
|
7
7
|
class ::OpenSSL::SSL::SSLSocket
|
8
|
-
def
|
8
|
+
def __read_method__
|
9
9
|
:readpartial
|
10
10
|
end
|
11
11
|
|
12
12
|
alias_method :orig_initialize, :initialize
|
13
|
+
|
14
|
+
# TODO: add docs to all methods in this file
|
13
15
|
def initialize(socket, context = nil)
|
14
16
|
socket = socket.respond_to?(:io) ? socket.io || socket : socket
|
15
17
|
context ? orig_initialize(socket, context) : orig_initialize(socket)
|