async 2.8.2 → 2.9.0
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
- checksums.yaml.gz.sig +0 -0
- data/lib/async/idler.rb +39 -0
- data/lib/async/scheduler.rb +35 -0
- data/lib/async/task.rb +1 -1
- data/lib/async/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +11 -4
- 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: e93ed3ea9094d074f430f9518bf0087f57abf732bf196bed5cf8249315aac33d
|
4
|
+
data.tar.gz: 233dffa50c8bb88cd514545280e3bef088b998a1ddb58e6db68d1a7c8a268c32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bede7ace58ac0e5f6bbefd05a89855a3f80ddf3d02a441aaa73b0a64adeb82b83d02d064121ae267b719519a6fc03f86b7b586f8af3901ae12fcfc6db2d5612c
|
7
|
+
data.tar.gz: a093ddf356f924089fc8500bee1570cac0e7a4a2e131127eeae0b65813905ae853f44e448f18ecda3d55e39d33f2c7e96c41a34f53cc02259ac8b5bef02e857a
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/async/idler.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
module Async
|
7
|
+
class Idler
|
8
|
+
def initialize(maximum_load = 0.8, backoff: 0.01, parent: nil)
|
9
|
+
@maximum_load = maximum_load
|
10
|
+
@backoff = backoff
|
11
|
+
@parent = parent
|
12
|
+
end
|
13
|
+
|
14
|
+
def async(*arguments, parent: (@parent or Task.current), **options, &block)
|
15
|
+
wait
|
16
|
+
|
17
|
+
# It is crucial that we optimistically execute the child task, so that we prevent a tight loop invoking this method from consuming all available resources.
|
18
|
+
parent.async(*arguments, **options, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def wait
|
22
|
+
scheduler = Fiber.scheduler
|
23
|
+
backoff = nil
|
24
|
+
|
25
|
+
while true
|
26
|
+
load = scheduler.load
|
27
|
+
break if load < @maximum_load
|
28
|
+
|
29
|
+
if backoff
|
30
|
+
sleep(backoff)
|
31
|
+
backoff *= 2.0
|
32
|
+
else
|
33
|
+
scheduler.yield
|
34
|
+
backoff = @backoff
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/async/scheduler.rb
CHANGED
@@ -37,9 +37,33 @@ module Async
|
|
37
37
|
|
38
38
|
@blocked = 0
|
39
39
|
|
40
|
+
@busy_time = 0.0
|
41
|
+
@idle_time = 0.0
|
42
|
+
|
40
43
|
@timers = ::Timers::Group.new
|
41
44
|
end
|
42
45
|
|
46
|
+
# Compute the scheduler load according to the busy and idle times that are updated by the run loop.
|
47
|
+
# @returns [Float] The load of the scheduler. 0.0 means no load, 1.0 means fully loaded or over-loaded.
|
48
|
+
def load
|
49
|
+
total_time = @busy_time + @idle_time
|
50
|
+
|
51
|
+
# If the total time is zero, then the load is zero:
|
52
|
+
return 0.0 if total_time.zero?
|
53
|
+
|
54
|
+
# We normalize to a 1 second window:
|
55
|
+
if total_time > 1.0
|
56
|
+
ratio = 1.0 / total_time
|
57
|
+
@busy_time *= ratio
|
58
|
+
@idle_time *= ratio
|
59
|
+
|
60
|
+
# We don't need to divide here as we've already normalised it to a 1s window:
|
61
|
+
return @busy_time
|
62
|
+
else
|
63
|
+
return @busy_time / total_time
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
43
67
|
def scheduler_close
|
44
68
|
# If the execution context (thread) was handling an exception, we want to exit as quickly as possible:
|
45
69
|
unless $!
|
@@ -267,6 +291,8 @@ module Async
|
|
267
291
|
# @parameter timeout [Float | Nil] The maximum timeout, or if nil, indefinite.
|
268
292
|
# @returns [Boolean] Whether there is more work to do.
|
269
293
|
private def run_once!(timeout = 0)
|
294
|
+
start_time = Async::Clock.now
|
295
|
+
|
270
296
|
interval = @timers.wait_interval
|
271
297
|
|
272
298
|
# If there is no interval to wait (thus no timers), and no tasks, we could be done:
|
@@ -288,6 +314,15 @@ module Async
|
|
288
314
|
|
289
315
|
@timers.fire
|
290
316
|
|
317
|
+
# Compute load:
|
318
|
+
end_time = Async::Clock.now
|
319
|
+
total_duration = end_time - start_time
|
320
|
+
idle_duration = @selector.idle_duration
|
321
|
+
busy_duration = total_duration - idle_duration
|
322
|
+
|
323
|
+
@busy_time += busy_duration
|
324
|
+
@idle_time += idle_duration
|
325
|
+
|
291
326
|
# The reactor still has work to do:
|
292
327
|
return true
|
293
328
|
end
|
data/lib/async/task.rb
CHANGED
@@ -208,7 +208,7 @@ module Async
|
|
208
208
|
# @parameter later [Boolean] Whether to stop the task later, or immediately.
|
209
209
|
def stop(later = false)
|
210
210
|
if self.stopped?
|
211
|
-
# If
|
211
|
+
# If the task is already stopped, a `stop` state transition re-enters the same state which is a no-op. However, we will also attempt to stop any running children too. This can happen if the children did not stop correctly the first time around. Doing this should probably be considered a bug, but it's better to be safe than sorry.
|
212
212
|
return stopped!
|
213
213
|
end
|
214
214
|
|
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.
|
4
|
+
version: 2.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -61,7 +61,7 @@ cert_chain:
|
|
61
61
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
62
62
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
63
63
|
-----END CERTIFICATE-----
|
64
|
-
date: 2024-
|
64
|
+
date: 2024-03-05 00:00:00.000000000 Z
|
65
65
|
dependencies:
|
66
66
|
- !ruby/object:Gem::Dependency
|
67
67
|
name: console
|
@@ -97,14 +97,20 @@ dependencies:
|
|
97
97
|
requirements:
|
98
98
|
- - "~>"
|
99
99
|
- !ruby/object:Gem::Version
|
100
|
-
version: '1.
|
100
|
+
version: '1.5'
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.5.1
|
101
104
|
type: :runtime
|
102
105
|
prerelease: false
|
103
106
|
version_requirements: !ruby/object:Gem::Requirement
|
104
107
|
requirements:
|
105
108
|
- - "~>"
|
106
109
|
- !ruby/object:Gem::Version
|
107
|
-
version: '1.
|
110
|
+
version: '1.5'
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: 1.5.1
|
108
114
|
- !ruby/object:Gem::Dependency
|
109
115
|
name: timers
|
110
116
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,6 +137,7 @@ files:
|
|
131
137
|
- lib/async/clock.rb
|
132
138
|
- lib/async/condition.md
|
133
139
|
- lib/async/condition.rb
|
140
|
+
- lib/async/idler.rb
|
134
141
|
- lib/async/list.rb
|
135
142
|
- lib/async/node.rb
|
136
143
|
- lib/async/notification.rb
|
metadata.gz.sig
CHANGED
Binary file
|