async 2.3.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d60db4d677d9cb4ed92f654f19ca17a4dab336002ba44290a80545b1f25e9154
4
- data.tar.gz: 9e84c874ef477cd0de6a86022c87a3fe92ae9276ddd3c4f4ccfd9d6600be0672
3
+ metadata.gz: 042a45792628d56b89e02200e38d6d00fb16c5311b95c3dae7d52607aef8108a
4
+ data.tar.gz: 6e7b3271d484ee3aabe395996ca987b1e0043d6d8710b3b706688993df43c916
5
5
  SHA512:
6
- metadata.gz: 7dd4367c1abb5cc79bf635a34b5819522e7f8363c385f69c995fe23d6fd4d7f6fc6a07784c789afbad0ff1ff6726d6d11899dd9b0a87ae582e9f78711c0ab346
7
- data.tar.gz: 0cbef57bb4896a06b11a95f318ad8a0d87435b70f591abc73bb8c7bf76773a341aba47399ef59a813f3d87f32f57112d070081db8598d4d58967f13ac26b4c61
6
+ metadata.gz: 49ea21f4f81b9e566119265b834ecbfb4de8db83788370e18d3d27b14e7a2ec972960f67301139dd61111f13843325264412bf096b5b33cafff910630b1663cb
7
+ data.tar.gz: 151eee11c70bf263c72cae52142168449ba38cd68a00ad302c2c9fcf53088de65784f35193971628e6c1ddb9d7efab9677359040ed19e13cde1f846670fd9b3e
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: Sorted
35
- | [0, 0, 0, 0, 1, 2, 2, 3, 6, 6]
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
- "#<#{self.class.name} size=#{@size}>"
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
- @tail.equal?(self)
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
- current = self
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
- unless @tail.equal?(self)
164
- @tail
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
- unless @head.equal?(self)
171
- @head
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
- end
175
-
176
- # A linked list Node.
177
- class List::Node
178
- attr_accessor :head
179
- attr_accessor :tail
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.each do |child|
192
+ while child = @children.shift
192
193
  if child.finished?
193
- remove_child(child)
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/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, and all bound bound IO objects.
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
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2017-2022, by Samuel Williams.
5
5
 
6
6
  module Async
7
- VERSION = "2.3.0"
7
+ VERSION = "2.3.1"
8
8
  end
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.3.0
4
+ version: 2.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -54,7 +54,7 @@ cert_chain:
54
54
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
55
55
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
56
56
  -----END CERTIFICATE-----
57
- date: 2022-12-04 00:00:00.000000000 Z
57
+ date: 2022-12-28 00:00:00.000000000 Z
58
58
  dependencies:
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: console
@@ -259,7 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
259
259
  - !ruby/object:Gem::Version
260
260
  version: '0'
261
261
  requirements: []
262
- rubygems_version: 3.3.7
262
+ rubygems_version: 3.4.1
263
263
  signing_key:
264
264
  specification_version: 4
265
265
  summary: A concurrency framework for Ruby.
metadata.gz.sig CHANGED
Binary file