polyphony 0.79 → 0.80
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +2 -1
- data/examples/core/zlib_stream.rb +15 -0
- data/ext/polyphony/backend_common.c +2 -1
- data/ext/polyphony/backend_common.h +7 -2
- 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 +59 -0
- 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 +9 -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)
|