async 1.28.8 → 1.29.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/async/debug/monitor.rb +8 -10
- data/lib/async/debug/selector.rb +8 -15
- data/lib/async/node.rb +25 -2
- data/lib/async/reactor.rb +10 -24
- data/lib/async/scheduler.rb +3 -1
- data/lib/async/task.rb +8 -13
- data/lib/async/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3613e4f3c3948bdf49fba954cca2f5df7934c52773dc533c424485aebaf800d6
|
4
|
+
data.tar.gz: ef790cb3bf5bb3bd248cbae57917f8a1598ffb94acef79a024e3d786e663f3ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99f619c7c76e7767b49ba8ff67e243a015b7a9f981df347ed4271c4bfafa1a465822293d177d42fd7e2ea184a628579853c233e060522e4a4f388c201a26ae12
|
7
|
+
data.tar.gz: 28046633dc2f14dae25828666cf611b9bd8d96fdaa140fc66126b4a3b48030d8811fd1081e4c9ecc46288eaa7b5d962a0845e54a81873b47bc9d3407c9f3b0a1
|
data/lib/async/debug/monitor.rb
CHANGED
@@ -20,25 +20,23 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
+
require 'delegate'
|
24
|
+
|
23
25
|
module Async
|
24
26
|
module Debug
|
25
|
-
class Monitor
|
27
|
+
class Monitor < Delegator
|
26
28
|
def initialize(monitor, selector)
|
27
29
|
@monitor = monitor
|
28
30
|
@selector = selector
|
29
31
|
end
|
30
32
|
|
31
|
-
def
|
32
|
-
@
|
33
|
-
@monitor.close
|
33
|
+
def __getobj__
|
34
|
+
@monitor
|
34
35
|
end
|
35
36
|
|
36
|
-
def
|
37
|
-
@
|
38
|
-
|
39
|
-
|
40
|
-
def respond_to?(*arguments)
|
41
|
-
@monitor.respond_to?(*arguments)
|
37
|
+
def close
|
38
|
+
@selector.deregister(self)
|
39
|
+
@monitor.close
|
42
40
|
end
|
43
41
|
|
44
42
|
def inspect
|
data/lib/async/debug/selector.rb
CHANGED
@@ -24,6 +24,7 @@ require_relative 'monitor'
|
|
24
24
|
require_relative '../logger'
|
25
25
|
|
26
26
|
require 'nio'
|
27
|
+
require 'set'
|
27
28
|
|
28
29
|
module Async
|
29
30
|
module Debug
|
@@ -36,7 +37,7 @@ module Async
|
|
36
37
|
class Selector
|
37
38
|
def initialize(selector = NIO::Selector.new)
|
38
39
|
@selector = selector
|
39
|
-
@monitors =
|
40
|
+
@monitors = Set.new
|
40
41
|
end
|
41
42
|
|
42
43
|
def register(object, interests)
|
@@ -46,26 +47,18 @@ module Async
|
|
46
47
|
raise RuntimeError, "Could not convert #{io} into IO!"
|
47
48
|
end
|
48
49
|
|
49
|
-
if monitor = @monitors[io.fileno]
|
50
|
-
raise RuntimeError, "Trying to register monitor for #{object.inspect} but it was already registered: #{monitor.inspect}!"
|
51
|
-
end
|
52
|
-
|
53
50
|
monitor = Monitor.new(@selector.register(object, interests), self)
|
54
51
|
|
55
|
-
@monitors
|
52
|
+
@monitors.add(monitor)
|
56
53
|
|
57
54
|
return monitor
|
58
55
|
end
|
59
56
|
|
60
|
-
def deregister(
|
61
|
-
Async.logger.debug(self) {"Deregistering #{
|
62
|
-
|
63
|
-
unless io = ::IO.try_convert(object)
|
64
|
-
raise RuntimeError, "Could not convert #{io} into IO!"
|
65
|
-
end
|
57
|
+
def deregister(monitor)
|
58
|
+
Async.logger.debug(self) {"Deregistering #{monitor.inspect}."}
|
66
59
|
|
67
|
-
unless @monitors.delete(
|
68
|
-
raise RuntimeError, "Trying to remove monitor for #{
|
60
|
+
unless @monitors.delete?(monitor)
|
61
|
+
raise RuntimeError, "Trying to remove monitor for #{monitor.inspect} but it was not registered!"
|
69
62
|
end
|
70
63
|
end
|
71
64
|
|
@@ -75,7 +68,7 @@ module Async
|
|
75
68
|
|
76
69
|
def close
|
77
70
|
if @monitors.any?
|
78
|
-
raise LeakError, @monitors
|
71
|
+
raise LeakError, @monitors
|
79
72
|
end
|
80
73
|
ensure
|
81
74
|
@selector.close
|
data/lib/async/node.rb
CHANGED
@@ -302,8 +302,31 @@ module Async
|
|
302
302
|
end
|
303
303
|
end
|
304
304
|
|
305
|
-
|
306
|
-
|
305
|
+
# Immediately terminate all children tasks, including transient tasks.
|
306
|
+
# Internally invokes `stop(false)` on all children.
|
307
|
+
def terminate
|
308
|
+
# Attempt to stop the current task immediately, and all children:
|
309
|
+
stop(false)
|
310
|
+
|
311
|
+
# If that doesn't work, take more serious action:
|
312
|
+
@children&.each do |child|
|
313
|
+
child.terminate
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# Attempt to stop the current node immediately, including all non-transient children.
|
318
|
+
# Invokes {#stop_children} to stop all children.
|
319
|
+
# @parameter later [Boolean] Whether to defer stopping until some point in the future.
|
320
|
+
def stop(later = false)
|
321
|
+
# The implementation of this method may defer calling `stop_children`.
|
322
|
+
stop_children(later)
|
323
|
+
end
|
324
|
+
|
325
|
+
# Attempt to stop all non-transient children.
|
326
|
+
private def stop_children(later = false)
|
327
|
+
@children&.each do |child|
|
328
|
+
child.stop(later) unless child.transient?
|
329
|
+
end
|
307
330
|
end
|
308
331
|
|
309
332
|
def print_hierarchy(out = $stdout, backtrace: true)
|
data/lib/async/reactor.rb
CHANGED
@@ -47,9 +47,7 @@ module Async
|
|
47
47
|
# running.
|
48
48
|
def self.run(*arguments, **options, &block)
|
49
49
|
if current = Task.current?
|
50
|
-
|
51
|
-
|
52
|
-
return reactor.async(*arguments, **options, &block)
|
50
|
+
return current.async(*arguments, **options, &block)
|
53
51
|
else
|
54
52
|
reactor = self.new
|
55
53
|
|
@@ -96,6 +94,7 @@ module Async
|
|
96
94
|
end
|
97
95
|
|
98
96
|
attr :scheduler
|
97
|
+
attr :logger
|
99
98
|
|
100
99
|
# @reentrant Not thread safe.
|
101
100
|
def block(blocker, timeout)
|
@@ -135,10 +134,6 @@ module Async
|
|
135
134
|
end
|
136
135
|
end
|
137
136
|
|
138
|
-
def logger
|
139
|
-
@logger || Console.logger
|
140
|
-
end
|
141
|
-
|
142
137
|
def to_s
|
143
138
|
"\#<#{self.description} #{@children&.size || 0} children (#{stopped? ? 'stopped' : 'running'})>"
|
144
139
|
end
|
@@ -167,7 +162,7 @@ module Async
|
|
167
162
|
# - Avoid scheduler overhead if no blocking operation is performed.
|
168
163
|
task.run(*arguments)
|
169
164
|
|
170
|
-
# logger.debug "Initial execution of task #{fiber} complete (#{result} -> #{fiber.alive?})..."
|
165
|
+
# Console.logger.debug "Initial execution of task #{fiber} complete (#{result} -> #{fiber.alive?})..."
|
171
166
|
return task
|
172
167
|
end
|
173
168
|
|
@@ -210,7 +205,7 @@ module Async
|
|
210
205
|
# @param timeout [Float | nil] the maximum timeout, or if nil, indefinite.
|
211
206
|
# @return [Boolean] whether there is more work to do.
|
212
207
|
def run_once(timeout = nil)
|
213
|
-
# logger.debug(self) {"@ready = #{@ready} @running = #{@running}"}
|
208
|
+
# Console.logger.debug(self) {"@ready = #{@ready} @running = #{@running}"}
|
214
209
|
|
215
210
|
if @ready.any?
|
216
211
|
# running used to correctly answer on `finished?`, and to reuse Array object.
|
@@ -258,7 +253,7 @@ module Async
|
|
258
253
|
interval = timeout
|
259
254
|
end
|
260
255
|
|
261
|
-
# logger.info(self) {"Selecting with #{@children&.size} children with interval = #{interval ? interval.round(2) : 'infinite'}..."}
|
256
|
+
# Console.logger.info(self) {"Selecting with #{@children&.size} children with interval = #{interval ? interval.round(2) : 'infinite'}..."}
|
262
257
|
if monitors = @selector.select(interval)
|
263
258
|
monitors.each do |monitor|
|
264
259
|
monitor.value.resume
|
@@ -295,35 +290,26 @@ module Async
|
|
295
290
|
return initial_task
|
296
291
|
ensure
|
297
292
|
@scheduler&.clear!
|
298
|
-
logger.debug(self) {"Exiting run-loop because #{$! ? $! : 'finished'}."}
|
299
|
-
end
|
300
|
-
|
301
|
-
def stop(later = true)
|
302
|
-
@children&.each do |child|
|
303
|
-
# We don't want this process to propagate `Async::Stop` exceptions, so we schedule tasks to stop later.
|
304
|
-
child.stop(later)
|
305
|
-
end
|
293
|
+
Console.logger.debug(self) {"Exiting run-loop because #{$! ? $! : 'finished'}."}
|
306
294
|
end
|
307
295
|
|
308
296
|
# Stop each of the children tasks and close the selector.
|
309
|
-
#
|
310
|
-
# @return [void]
|
311
297
|
def close
|
312
|
-
# This is a critical step. Because tasks could be stored as instance variables, and since the reactor is (probably) going out of scope, we need to ensure they are stopped. Otherwise, the tasks will belong to a reactor that will never run again and are not stopped
|
313
|
-
self.
|
298
|
+
# This is a critical step. Because tasks could be stored as instance variables, and since the reactor is (probably) going out of scope, we need to ensure they are stopped. Otherwise, the tasks will belong to a reactor that will never run again and are not stopped:
|
299
|
+
self.terminate
|
314
300
|
|
315
301
|
@selector.close
|
316
302
|
@selector = nil
|
317
303
|
end
|
318
304
|
|
319
305
|
# Check if the selector has been closed.
|
320
|
-
# @
|
306
|
+
# @returns [Boolean]
|
321
307
|
def closed?
|
322
308
|
@selector.nil?
|
323
309
|
end
|
324
310
|
|
325
311
|
# Put the calling fiber to sleep for a given ammount of time.
|
326
|
-
# @
|
312
|
+
# @parameter duration [Numeric] The time in seconds, to sleep for.
|
327
313
|
def sleep(duration)
|
328
314
|
fiber = Fiber.current
|
329
315
|
|
data/lib/async/scheduler.rb
CHANGED
data/lib/async/task.rb
CHANGED
@@ -81,11 +81,13 @@ module Async
|
|
81
81
|
@result = nil
|
82
82
|
@finished = finished
|
83
83
|
|
84
|
-
@logger = logger
|
84
|
+
@logger = logger || @parent.logger
|
85
85
|
|
86
86
|
@fiber = make_fiber(&block)
|
87
87
|
end
|
88
88
|
|
89
|
+
attr :logger
|
90
|
+
|
89
91
|
if Fiber.current.respond_to?(:backtrace)
|
90
92
|
def backtrace(*arguments)
|
91
93
|
@fiber&.backtrace(*arguments)
|
@@ -96,10 +98,6 @@ module Async
|
|
96
98
|
"\#<#{self.description} (#{@status})>"
|
97
99
|
end
|
98
100
|
|
99
|
-
def logger
|
100
|
-
@logger || Console.logger
|
101
|
-
end
|
102
|
-
|
103
101
|
# @attr ios [Reactor] The reactor the task was created within.
|
104
102
|
attr :reactor
|
105
103
|
|
@@ -158,7 +156,6 @@ module Async
|
|
158
156
|
# Soon to become attr :result
|
159
157
|
|
160
158
|
# Stop the task and all of its children.
|
161
|
-
# @return [void]
|
162
159
|
def stop(later = false)
|
163
160
|
if self.stopped?
|
164
161
|
# If we already stopped this task... don't try to stop it again:
|
@@ -242,9 +239,9 @@ module Async
|
|
242
239
|
raise
|
243
240
|
elsif @finished.nil?
|
244
241
|
# If no one has called wait, we log this as an error:
|
245
|
-
logger.error(self) {$!}
|
242
|
+
Console.logger.error(self) {$!}
|
246
243
|
else
|
247
|
-
logger.debug(self) {$!}
|
244
|
+
Console.logger.debug(self) {$!}
|
248
245
|
end
|
249
246
|
end
|
250
247
|
|
@@ -252,9 +249,7 @@ module Async
|
|
252
249
|
# logger.debug(self) {"Task was stopped with #{@children&.size.inspect} children!"}
|
253
250
|
@status = :stopped
|
254
251
|
|
255
|
-
|
256
|
-
child.stop(true)
|
257
|
-
end
|
252
|
+
stop_children(true)
|
258
253
|
end
|
259
254
|
|
260
255
|
def make_fiber(&block)
|
@@ -264,7 +259,7 @@ module Async
|
|
264
259
|
begin
|
265
260
|
@result = yield(self, *arguments)
|
266
261
|
@status = :complete
|
267
|
-
# logger.debug(self) {"Task was completed with #{@children.size} children!"}
|
262
|
+
# Console.logger.debug(self) {"Task was completed with #{@children.size} children!"}
|
268
263
|
rescue Stop
|
269
264
|
stop!
|
270
265
|
rescue StandardError => error
|
@@ -272,7 +267,7 @@ module Async
|
|
272
267
|
rescue Exception => exception
|
273
268
|
fail!(exception, true)
|
274
269
|
ensure
|
275
|
-
# logger.debug(self) {"Task ensure $!=#{$!} with #{@children.size} children!"}
|
270
|
+
# Console.logger.debug(self) {"Task ensure $!=#{$!} with #{@children.size} children!"}
|
276
271
|
finish!
|
277
272
|
end
|
278
273
|
end
|
data/lib/async/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.29.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: console
|
@@ -179,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
181
|
requirements: []
|
182
|
-
rubygems_version: 3.2.
|
182
|
+
rubygems_version: 3.2.22
|
183
183
|
signing_key:
|
184
184
|
specification_version: 4
|
185
185
|
summary: A concurrency framework for Ruby.
|