async 2.15.0 → 2.15.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/async/node.rb +26 -0
- data/lib/async/scheduler.rb +39 -34
- data/lib/async/task.rb +17 -9
- data/lib/async/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +3 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be0c94dc887562681bc88ba244ed1bdd85ff41cd5707b22208c44fde725459d0
|
4
|
+
data.tar.gz: d91b6f27e96fb9c892fda055cdfb7bcc6564d89e9a02da3f9cf95c248d989360
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ec8529ee1df127e0527eb7346b9b606a3767c9ca51b812616d758e0ef2f83687829f9b70d517e4e0f18dd56b169e07fa0df9339fd96393e51388c2fb837eaaf
|
7
|
+
data.tar.gz: 777d6eb933f5907504a129f3320f36bc3f9c199b5054d24c2bbdcdebb3d3f598bb064282cd7e07b8e75760cd7872119a4aa6c2d73df43b33dc42f60f1358cfd2
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/async/node.rb
CHANGED
@@ -34,6 +34,19 @@ module Async
|
|
34
34
|
empty?
|
35
35
|
end
|
36
36
|
|
37
|
+
# Adjust the number of transient children, assuming it has changed.
|
38
|
+
#
|
39
|
+
# Despite being public, this is not intended to be called directly. It is used internally by {Node#transient=}.
|
40
|
+
#
|
41
|
+
# @parameter transient [Boolean] Whether to increment or decrement the transient count.
|
42
|
+
def adjust_transient_count(transient)
|
43
|
+
if transient
|
44
|
+
@transient_count += 1
|
45
|
+
else
|
46
|
+
@transient_count -= 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
37
50
|
private
|
38
51
|
|
39
52
|
def added(node)
|
@@ -110,6 +123,19 @@ module Async
|
|
110
123
|
@transient
|
111
124
|
end
|
112
125
|
|
126
|
+
# Change the transient state of the node.
|
127
|
+
#
|
128
|
+
# A transient node is not considered when determining if a node is finished, and propagates up if the parent is consumed.
|
129
|
+
#
|
130
|
+
# @parameter value [Boolean] Whether the node is transient.
|
131
|
+
def transient=(value)
|
132
|
+
if @transient != value
|
133
|
+
@transient = value
|
134
|
+
|
135
|
+
@parent&.children&.adjust_transient_count(value)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
113
139
|
# Annotate the node with a description.
|
114
140
|
#
|
115
141
|
# @parameter annotation [String] The description to annotate the node with.
|
data/lib/async/scheduler.rb
CHANGED
@@ -75,30 +75,33 @@ module Async
|
|
75
75
|
# Invoked when the fiber scheduler is being closed.
|
76
76
|
#
|
77
77
|
# Executes the run loop until all tasks are finished, then closes the scheduler.
|
78
|
-
def scheduler_close
|
78
|
+
def scheduler_close(error = $!)
|
79
79
|
# If the execution context (thread) was handling an exception, we want to exit as quickly as possible:
|
80
|
-
unless
|
80
|
+
unless error
|
81
81
|
self.run
|
82
82
|
end
|
83
83
|
ensure
|
84
84
|
self.close
|
85
85
|
end
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
unless @children.nil?
|
93
|
-
run_once!
|
94
|
-
end
|
87
|
+
# Terminate all child tasks.
|
88
|
+
def terminate
|
89
|
+
# If that doesn't work, take more serious action:
|
90
|
+
@children&.each do |child|
|
91
|
+
child.terminate
|
95
92
|
end
|
93
|
+
|
94
|
+
return @children.nil?
|
96
95
|
end
|
97
96
|
|
98
97
|
# Terminate all child tasks and close the scheduler.
|
99
98
|
# @public Since `stable-v1`.
|
100
99
|
def close
|
101
|
-
self.
|
100
|
+
self.run_loop do
|
101
|
+
until self.terminate
|
102
|
+
self.run_once!
|
103
|
+
end
|
104
|
+
end
|
102
105
|
|
103
106
|
Kernel.raise "Closing scheduler with blocked operations!" if @blocked > 0
|
104
107
|
ensure
|
@@ -288,21 +291,6 @@ module Async
|
|
288
291
|
return @selector.process_wait(Fiber.current, pid, flags)
|
289
292
|
end
|
290
293
|
|
291
|
-
# Run one iteration of the event loop.
|
292
|
-
# Does not handle interrupts.
|
293
|
-
# @parameter timeout [Float | Nil] The maximum timeout, or if nil, indefinite.
|
294
|
-
# @returns [Boolean] Whether there is more work to do.
|
295
|
-
def run_once(timeout = nil)
|
296
|
-
Kernel.raise "Running scheduler on non-blocking fiber!" unless Fiber.blocking?
|
297
|
-
|
298
|
-
# If we are finished, we stop the task tree and exit:
|
299
|
-
if self.finished?
|
300
|
-
return false
|
301
|
-
end
|
302
|
-
|
303
|
-
return run_once!(timeout)
|
304
|
-
end
|
305
|
-
|
306
294
|
# Run one iteration of the event loop.
|
307
295
|
#
|
308
296
|
# When terminating the event loop, we already know we are finished. So we don't need to check the task tree. This is a logical requirement because `run_once` ignores transient tasks. For example, a single top level transient task is not enough to keep the reactor running, but during termination we must still process it in order to terminate child tasks.
|
@@ -346,6 +334,25 @@ module Async
|
|
346
334
|
return true
|
347
335
|
end
|
348
336
|
|
337
|
+
# Run one iteration of the event loop.
|
338
|
+
# Does not handle interrupts.
|
339
|
+
# @parameter timeout [Float | Nil] The maximum timeout, or if nil, indefinite.
|
340
|
+
# @returns [Boolean] Whether there is more work to do.
|
341
|
+
def run_once(timeout = nil)
|
342
|
+
Kernel.raise "Running scheduler on non-blocking fiber!" unless Fiber.blocking?
|
343
|
+
|
344
|
+
if self.finished?
|
345
|
+
self.stop
|
346
|
+
end
|
347
|
+
|
348
|
+
# If we are finished, we stop the task tree and exit:
|
349
|
+
if @children.nil?
|
350
|
+
return false
|
351
|
+
end
|
352
|
+
|
353
|
+
return run_once!(timeout)
|
354
|
+
end
|
355
|
+
|
349
356
|
# Checks and clears the interrupted state of the scheduler.
|
350
357
|
# @returns [Boolean] Whether the reactor has been interrupted.
|
351
358
|
private def interrupted?
|
@@ -363,10 +370,8 @@ module Async
|
|
363
370
|
|
364
371
|
# Stop all children, including transient children, ignoring any signals.
|
365
372
|
def stop
|
366
|
-
|
367
|
-
|
368
|
-
child.stop
|
369
|
-
end
|
373
|
+
@children&.each do |child|
|
374
|
+
child.stop
|
370
375
|
end
|
371
376
|
end
|
372
377
|
|
@@ -382,7 +387,9 @@ module Async
|
|
382
387
|
end
|
383
388
|
end
|
384
389
|
rescue Interrupt => interrupt
|
385
|
-
|
390
|
+
Thread.handle_interrupt(::SignalException => :never) do
|
391
|
+
self.stop
|
392
|
+
end
|
386
393
|
|
387
394
|
retry
|
388
395
|
end
|
@@ -398,9 +405,7 @@ module Async
|
|
398
405
|
initial_task = self.async(...) if block_given?
|
399
406
|
|
400
407
|
self.run_loop do
|
401
|
-
|
402
|
-
run_once!
|
403
|
-
end
|
408
|
+
run_once
|
404
409
|
end
|
405
410
|
|
406
411
|
return initial_task
|
data/lib/async/task.rb
CHANGED
@@ -176,7 +176,7 @@ module Async
|
|
176
176
|
|
177
177
|
alias complete? completed?
|
178
178
|
|
179
|
-
# @attribute [Symbol] The status of the execution of the
|
179
|
+
# @attribute [Symbol] The status of the execution of the task, one of `:initialized`, `:running`, `:complete`, `:stopped` or `:failed`.
|
180
180
|
attr :status
|
181
181
|
|
182
182
|
# Begin the execution of the task.
|
@@ -253,15 +253,18 @@ module Async
|
|
253
253
|
return stopped!
|
254
254
|
end
|
255
255
|
|
256
|
-
# If we are deferring stop...
|
257
|
-
if @defer_stop == false
|
258
|
-
# Don't stop now... but update the state so we know we need to stop later.
|
259
|
-
@defer_stop = true
|
260
|
-
return false
|
261
|
-
end
|
262
|
-
|
263
256
|
# If the fiber is alive, we need to stop it:
|
264
257
|
if @fiber&.alive?
|
258
|
+
# As the task is now exiting, we want to ensure the event loop continues to execute until the task finishes.
|
259
|
+
self.transient = false
|
260
|
+
|
261
|
+
# If we are deferring stop...
|
262
|
+
if @defer_stop == false
|
263
|
+
# Don't stop now... but update the state so we know we need to stop later.
|
264
|
+
@defer_stop = true
|
265
|
+
return false
|
266
|
+
end
|
267
|
+
|
265
268
|
if self.current?
|
266
269
|
# If the fiber is current, and later is `true`, we need to schedule the fiber to be stopped later, as it's currently invoking `stop`:
|
267
270
|
if later
|
@@ -276,7 +279,7 @@ module Async
|
|
276
279
|
begin
|
277
280
|
# There is a chance that this will stop the fiber that originally called stop. If that happens, the exception handling in `#stopped` will rescue the exception and re-raise it later.
|
278
281
|
Fiber.scheduler.raise(@fiber, Stop)
|
279
|
-
rescue FiberError
|
282
|
+
rescue FiberError => error
|
280
283
|
# In some cases, this can cause a FiberError (it might be resumed already), so we schedule it to be stopped later:
|
281
284
|
Fiber.scheduler.push(Stop::Later.new(self))
|
282
285
|
end
|
@@ -323,6 +326,11 @@ module Async
|
|
323
326
|
end
|
324
327
|
end
|
325
328
|
|
329
|
+
# @returns [Boolean] Whether stop has been deferred.
|
330
|
+
def stop_deferred?
|
331
|
+
@defer_stop
|
332
|
+
end
|
333
|
+
|
326
334
|
# Lookup the {Task} for the current fiber. Raise `RuntimeError` if none is available.
|
327
335
|
# @returns [Task]
|
328
336
|
# @raises[RuntimeError] If task was not {set!} for the current fiber.
|
data/lib/async/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.15.
|
4
|
+
version: 2.15.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -63,7 +63,7 @@ cert_chain:
|
|
63
63
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
64
64
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
65
65
|
-----END CERTIFICATE-----
|
66
|
-
date: 2024-08-
|
66
|
+
date: 2024-08-07 00:00:00.000000000 Z
|
67
67
|
dependencies:
|
68
68
|
- !ruby/object:Gem::Dependency
|
69
69
|
name: console
|
@@ -167,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
167
|
- !ruby/object:Gem::Version
|
168
168
|
version: '0'
|
169
169
|
requirements: []
|
170
|
-
rubygems_version: 3.5.
|
170
|
+
rubygems_version: 3.5.11
|
171
171
|
signing_key:
|
172
172
|
specification_version: 4
|
173
173
|
summary: A concurrency framework for Ruby.
|
metadata.gz.sig
CHANGED
Binary file
|