async 2.3.0 → 2.4.0
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/barrier.md +4 -2
- data/lib/async/list.rb +154 -27
- data/lib/async/node.rb +3 -4
- data/lib/async/semaphore.rb +20 -1
- data/lib/async/task.rb +1 -1
- data/lib/async/version.rb +1 -1
- data/license.md +4 -1
- data/readme.md +0 -24
- data.tar.gz.sig +0 -0
- metadata +10 -8
- 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: '0496bec665a4c9cb59cc9f52e0f75e8c122ff66b2daddaa0aa6e83022e5e8928'
|
4
|
+
data.tar.gz: 2e0c3995dc1de72fee48942eecf96b14fa08f8e0d78083fba96be455a0ffdeab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cac34c61bf2bde2775d0abbf4185fdecc07f6540ba18017c90ce38ef6d72d95397e09c65b8d9f25f8e3a1ead9635180b38d6666525c00384810c796c6c92d629
|
7
|
+
data.tar.gz: 39778867ad4784cf5f44d164f2d97f52d2cc43b869f267242ef5d9d588f626cc656bb01d7f935a8237f9f83ff50bf9b1371032f50ffb5bc39a1af80e2be89adc
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/async/barrier.md
CHANGED
@@ -7,6 +7,7 @@ require 'async'
|
|
7
7
|
require 'async/barrier'
|
8
8
|
|
9
9
|
Sync do
|
10
|
+
Console.logger.info("Barrier Example: sleep sort.")
|
10
11
|
barrier = Async::Barrier.new
|
11
12
|
|
12
13
|
# Generate an array of 10 numbers:
|
@@ -31,6 +32,7 @@ end
|
|
31
32
|
### Output
|
32
33
|
|
33
34
|
~~~
|
34
|
-
0.0s info:
|
35
|
-
|
35
|
+
0.0s info: Barrier Example: sleep sort.
|
36
|
+
9.0s info: Sorted
|
37
|
+
| [3, 3, 3, 4, 4, 5, 5, 5, 8, 9]
|
36
38
|
~~~
|
data/lib/async/list.rb
CHANGED
@@ -15,11 +15,27 @@ module Async
|
|
15
15
|
|
16
16
|
# Print a short summary of the list.
|
17
17
|
def to_s
|
18
|
-
"
|
18
|
+
sprintf("#<%s:0x%x size=%d>", self.class.name, object_id, @size)
|
19
19
|
end
|
20
20
|
|
21
21
|
alias inspect to_s
|
22
22
|
|
23
|
+
# Fast, safe, unbounded accumulation of children.
|
24
|
+
def to_a
|
25
|
+
items = []
|
26
|
+
current = self
|
27
|
+
|
28
|
+
while current.tail != self
|
29
|
+
unless current.tail.is_a?(Iterator)
|
30
|
+
items << current.tail
|
31
|
+
end
|
32
|
+
|
33
|
+
current = current.tail
|
34
|
+
end
|
35
|
+
|
36
|
+
return items
|
37
|
+
end
|
38
|
+
|
23
39
|
# Points at the end of the list.
|
24
40
|
attr_accessor :head
|
25
41
|
|
@@ -118,30 +134,46 @@ module Async
|
|
118
134
|
|
119
135
|
# @returns [Boolean] Returns true if the list is empty.
|
120
136
|
def empty?
|
121
|
-
@
|
137
|
+
@size == 0
|
122
138
|
end
|
123
139
|
|
140
|
+
# def validate!(node = nil)
|
141
|
+
# previous = self
|
142
|
+
# current = @tail
|
143
|
+
# found = node.equal?(self)
|
144
|
+
|
145
|
+
# while true
|
146
|
+
# break if current.equal?(self)
|
147
|
+
|
148
|
+
# if current.head != previous
|
149
|
+
# raise "Invalid previous linked list node!"
|
150
|
+
# end
|
151
|
+
|
152
|
+
# if current.is_a?(List) and !current.equal?(self)
|
153
|
+
# raise "Invalid list in list node!"
|
154
|
+
# end
|
155
|
+
|
156
|
+
# if node
|
157
|
+
# found ||= current.equal?(node)
|
158
|
+
# end
|
159
|
+
|
160
|
+
# previous = current
|
161
|
+
# current = current.tail
|
162
|
+
# end
|
163
|
+
|
164
|
+
# if node and !found
|
165
|
+
# raise "Node not found in list!"
|
166
|
+
# end
|
167
|
+
# end
|
168
|
+
|
124
169
|
# Iterate over each node in the linked list. It is generally safe to remove the current node, any previous node or any future node during iteration.
|
125
170
|
#
|
126
171
|
# @yields {|node| ...} Yields each node in the list.
|
127
172
|
# @returns [List] Returns self.
|
128
|
-
def each
|
173
|
+
def each(&block)
|
129
174
|
return to_enum unless block_given?
|
130
175
|
|
131
|
-
|
132
|
-
|
133
|
-
while true
|
134
|
-
node = current.tail
|
135
|
-
# binding.irb if node.nil? && !node.equal?(self)
|
136
|
-
break if node.equal?(self)
|
137
|
-
|
138
|
-
yield node
|
139
|
-
|
140
|
-
# If the node has deleted itself or any subsequent node, it will no longer be the next node, so don't use it for continued traversal:
|
141
|
-
if current.tail.equal?(node)
|
142
|
-
current = node
|
143
|
-
end
|
144
|
-
end
|
176
|
+
Iterator.each(self, &block)
|
145
177
|
|
146
178
|
return self
|
147
179
|
end
|
@@ -160,22 +192,117 @@ module Async
|
|
160
192
|
|
161
193
|
# @returns [Node] Returns the first node in the list, if it is not empty.
|
162
194
|
def first
|
163
|
-
|
164
|
-
|
195
|
+
# validate!
|
196
|
+
|
197
|
+
current = @tail
|
198
|
+
|
199
|
+
while !current.equal?(self)
|
200
|
+
if current.is_a?(Iterator)
|
201
|
+
current = current.tail
|
202
|
+
else
|
203
|
+
return current
|
204
|
+
end
|
165
205
|
end
|
206
|
+
|
207
|
+
return nil
|
166
208
|
end
|
167
209
|
|
168
210
|
# @returns [Node] Returns the last node in the list, if it is not empty.
|
169
211
|
def last
|
170
|
-
|
171
|
-
|
212
|
+
# validate!
|
213
|
+
|
214
|
+
current = @head
|
215
|
+
|
216
|
+
while !current.equal?(self)
|
217
|
+
if current.is_a?(Iterator)
|
218
|
+
current = current.head
|
219
|
+
else
|
220
|
+
return current
|
221
|
+
end
|
172
222
|
end
|
223
|
+
|
224
|
+
return nil
|
173
225
|
end
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
226
|
+
|
227
|
+
def shift
|
228
|
+
if node = first
|
229
|
+
remove!(node)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# A linked list Node.
|
234
|
+
class Node
|
235
|
+
attr_accessor :head
|
236
|
+
attr_accessor :tail
|
237
|
+
|
238
|
+
alias inspect to_s
|
239
|
+
end
|
240
|
+
|
241
|
+
class Iterator < Node
|
242
|
+
def initialize(list)
|
243
|
+
@list = list
|
244
|
+
|
245
|
+
# Insert the iterator as the first item in the list:
|
246
|
+
@tail = list.tail
|
247
|
+
@tail.head = self
|
248
|
+
list.tail = self
|
249
|
+
@head = list
|
250
|
+
end
|
251
|
+
|
252
|
+
def remove!
|
253
|
+
@head.tail = @tail
|
254
|
+
@tail.head = @head
|
255
|
+
@head = nil
|
256
|
+
@tail = nil
|
257
|
+
@list = nil
|
258
|
+
end
|
259
|
+
|
260
|
+
def move_next
|
261
|
+
# Move to the next item (which could be an iterator or the end):
|
262
|
+
@tail.head = @head
|
263
|
+
@head.tail = @tail
|
264
|
+
@head = @tail
|
265
|
+
@tail = @tail.tail
|
266
|
+
@head.tail = self
|
267
|
+
@tail.head = self
|
268
|
+
end
|
269
|
+
|
270
|
+
def move_current
|
271
|
+
while true
|
272
|
+
# Are we at the end of the list?
|
273
|
+
if @tail.equal?(@list)
|
274
|
+
return nil
|
275
|
+
end
|
276
|
+
|
277
|
+
if @tail.is_a?(Iterator)
|
278
|
+
move_next
|
279
|
+
else
|
280
|
+
return @tail
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def each
|
286
|
+
while current = move_current
|
287
|
+
yield current
|
288
|
+
|
289
|
+
if current.equal?(@tail)
|
290
|
+
move_next
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def self.each(list, &block)
|
296
|
+
return if list.empty?
|
297
|
+
|
298
|
+
iterator = Iterator.new(list)
|
299
|
+
|
300
|
+
iterator.each(&block)
|
301
|
+
ensure
|
302
|
+
iterator&.remove!
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
private_constant :Iterator
|
180
307
|
end
|
181
308
|
end
|
data/lib/async/node.rb
CHANGED
@@ -187,13 +187,12 @@ module Async
|
|
187
187
|
if parent = @parent and finished?
|
188
188
|
parent.remove_child(self)
|
189
189
|
|
190
|
+
# If we have children, then we need to move them to our the parent if they are not finished:
|
190
191
|
if @children
|
191
|
-
@children.
|
192
|
+
while child = @children.shift
|
192
193
|
if child.finished?
|
193
|
-
|
194
|
+
child.set_parent(nil)
|
194
195
|
else
|
195
|
-
# In theory we don't need to do this... because we are throwing away the list. However, if you don't correctly update the list when moving the child to the parent, it foobars the enumeration, and subsequent nodes will be skipped, or in the worst case you might start enumerating the parents nodes.
|
196
|
-
remove_child(child)
|
197
196
|
parent.add_child(child)
|
198
197
|
end
|
199
198
|
end
|
data/lib/async/semaphore.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2023, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative 'list'
|
7
7
|
|
@@ -28,6 +28,25 @@ module Async
|
|
28
28
|
# The tasks waiting on this semaphore.
|
29
29
|
attr :waiting
|
30
30
|
|
31
|
+
# Allow setting the limit. This is useful for cases where the semaphore is used to limit the number of concurrent tasks, but the number of tasks is not known in advance or needs to be modified.
|
32
|
+
#
|
33
|
+
# On increasing the limit, some tasks may be immediately resumed. On decreasing the limit, some tasks may execute until the count is < than the limit.
|
34
|
+
#
|
35
|
+
# @parameter limit [Integer] The new limit.
|
36
|
+
def limit= limit
|
37
|
+
difference = limit - @limit
|
38
|
+
@limit = limit
|
39
|
+
|
40
|
+
# We can't suspend
|
41
|
+
if difference > 0
|
42
|
+
difference.times do
|
43
|
+
break unless node = @waiting.first
|
44
|
+
|
45
|
+
node.resume
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
31
50
|
# Is the semaphore currently acquired?
|
32
51
|
def empty?
|
33
52
|
@count.zero?
|
data/lib/async/task.rb
CHANGED
@@ -263,7 +263,7 @@ module Async
|
|
263
263
|
self.root.resume(@fiber)
|
264
264
|
end
|
265
265
|
|
266
|
-
# Finish the current task,
|
266
|
+
# Finish the current task, moving any children to the parent.
|
267
267
|
def finish!
|
268
268
|
# Allow the fiber to be recycled.
|
269
269
|
@fiber = nil
|
data/lib/async/version.rb
CHANGED
data/license.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# MIT License
|
2
2
|
|
3
|
-
Copyright, 2017-
|
3
|
+
Copyright, 2017-2023, by Samuel Williams.
|
4
4
|
Copyright, 2017, by Kent Gruber.
|
5
5
|
Copyright, 2017, by Devin Christensen.
|
6
6
|
Copyright, 2018, by Sokolov Yura.
|
@@ -17,6 +17,9 @@ Copyright, 2020, by Jun Jiang.
|
|
17
17
|
Copyright, 2020-2022, by Bruno Sutic.
|
18
18
|
Copyright, 2021, by Julien Portalier.
|
19
19
|
Copyright, 2022, by Shannon Skipper.
|
20
|
+
Copyright, 2022, by Masafumi Okura.
|
21
|
+
Copyright, 2022, by Trevor Turk.
|
22
|
+
Copyright, 2022, by Masayuki Yamamoto.
|
20
23
|
|
21
24
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
22
25
|
of this software and associated documentation files (the "Software"), to deal
|
data/readme.md
CHANGED
@@ -42,27 +42,3 @@ We welcome contributions to this project.
|
|
42
42
|
- [falcon](https://github.com/socketry/falcon) — A rack compatible server built on top of `async-http`.
|
43
43
|
- [rubydns](https://github.com/ioquatix/rubydns) — An easy to use Ruby DNS server.
|
44
44
|
- [slack-ruby-bot](https://github.com/slack-ruby/slack-ruby-bot) — A client for making slack bots.
|
45
|
-
|
46
|
-
## License
|
47
|
-
|
48
|
-
Released under the MIT license.
|
49
|
-
|
50
|
-
Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com).
|
51
|
-
|
52
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
53
|
-
of this software and associated documentation files (the "Software"), to deal
|
54
|
-
in the Software without restriction, including without limitation the rights
|
55
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
56
|
-
copies of the Software, and to permit persons to whom the Software is
|
57
|
-
furnished to do so, subject to the following conditions:
|
58
|
-
|
59
|
-
The above copyright notice and this permission notice shall be included in
|
60
|
-
all copies or substantial portions of the Software.
|
61
|
-
|
62
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
63
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
64
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
65
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
66
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
67
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
68
|
-
THE SOFTWARE.
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,27 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
- Bruno Sutic
|
9
|
-
- Devin Christensen
|
10
9
|
- Jeremy Jung
|
10
|
+
- Devin Christensen
|
11
11
|
- Kent Gruber
|
12
|
-
- jeremyjung
|
13
12
|
- Brian Morearty
|
14
13
|
- Jiang Jinyang
|
15
14
|
- Julien Portalier
|
15
|
+
- Jun Jiang
|
16
|
+
- Ken Muryoi
|
17
|
+
- Masafumi Okura
|
18
|
+
- Masayuki Yamamoto
|
16
19
|
- Olle Jonsson
|
17
20
|
- Patrik Wenger
|
18
21
|
- Ryan Musgrave
|
19
22
|
- Salim Semaoune
|
20
23
|
- Shannon Skipper
|
21
|
-
- Sokolov Yura
|
24
|
+
- Sokolov Yura
|
22
25
|
- Stefan Wrobel
|
23
|
-
-
|
24
|
-
- muryoimpl
|
26
|
+
- Trevor Turk
|
25
27
|
autorequire:
|
26
28
|
bindir: bin
|
27
29
|
cert_chain:
|
@@ -54,7 +56,7 @@ cert_chain:
|
|
54
56
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
55
57
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
56
58
|
-----END CERTIFICATE-----
|
57
|
-
date:
|
59
|
+
date: 2023-03-01 00:00:00.000000000 Z
|
58
60
|
dependencies:
|
59
61
|
- !ruby/object:Gem::Dependency
|
60
62
|
name: console
|
@@ -259,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
259
261
|
- !ruby/object:Gem::Version
|
260
262
|
version: '0'
|
261
263
|
requirements: []
|
262
|
-
rubygems_version: 3.
|
264
|
+
rubygems_version: 3.4.7
|
263
265
|
signing_key:
|
264
266
|
specification_version: 4
|
265
267
|
summary: A concurrency framework for Ruby.
|
metadata.gz.sig
CHANGED
Binary file
|