async 1.30.0 → 1.30.3

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: e5d9fe2eaa3012c11c39abb23dc7482ec2a224123ed4ef4424bb630b50f8d462
4
- data.tar.gz: 113adfafc25504e6f330f36dbd46707dc883e197c36d8530f0a58555ac55b8d4
3
+ metadata.gz: f7bcca0b0eba6eebe85dd32baa0ffd67059bcdb0623416b818182bf779e38809
4
+ data.tar.gz: 061a086ae31c238f1d2c3d17598400f3efc01a500de746105255f7582b90251c
5
5
  SHA512:
6
- metadata.gz: 973e99f9ff361ad1cdf62f074fd6897c6691304ea004dae58aece3309fddd713c5921bf02ff42bd748999f18e2ebf172bd1505a8af318e9cb5c70e23a858145c
7
- data.tar.gz: 88001bc4a38cd8a7fec4748ee89ee4b779c77eb925ed6e93923807fd57d4bc0227feffe43e54de55056c48b1705c1b551b1d26529525318d70a61986788919c0
6
+ metadata.gz: 455f569e561177f4f2e11e5f5713c6e04c5b30b54b01e860bca5e84770095b7f80c0d05d6afa7865773fbfb58c4170103a905ce9c3517c08fb9eec32f5a191a9
7
+ data.tar.gz: b142a77817fcf868fa68f117d68fe05cf3d0ce34329855a2ef19be198924604b366deaa0ac0ec7bcaa151eaf244bb1e521908515aca44b5be1d82f794288f313
data/lib/async/barrier.rb CHANGED
@@ -50,17 +50,29 @@ module Async
50
50
  @tasks.empty?
51
51
  end
52
52
 
53
- # Wait for tasks in FIFO order.
53
+ # Wait for all tasks.
54
+ # @asynchronous Will wait for tasks to finish executing.
54
55
  def wait
55
- while task = @tasks.shift
56
- task.wait
56
+ # TODO: This would be better with linked list.
57
+ while @tasks.any?
58
+ task = @tasks.first
59
+
60
+ begin
61
+ task.wait
62
+ ensure
63
+ # We don't know for sure that the exception was due to the task completion.
64
+ unless task.running?
65
+ # Remove the task from the waiting list if it's finished:
66
+ @tasks.shift if @tasks.first == task
67
+ end
68
+ end
57
69
  end
58
70
  end
59
71
 
60
72
  def stop
61
- while task = @tasks.shift
62
- task.stop
63
- end
73
+ # We have to be careful to avoid enumerating tasks while adding/removing to it:
74
+ tasks = @tasks.dup
75
+ tasks.each(&:stop)
64
76
  end
65
77
  end
66
78
  end
@@ -21,7 +21,6 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  require 'fiber'
24
- require 'forwardable'
25
24
  require_relative 'node'
26
25
 
27
26
  module Async
data/lib/async/queue.rb CHANGED
@@ -42,13 +42,17 @@ module Async
42
42
  @items.empty?
43
43
  end
44
44
 
45
- def enqueue(item)
46
- @items.push(item)
45
+ def <<(item)
46
+ @items << item
47
47
 
48
48
  self.signal unless self.empty?
49
49
  end
50
50
 
51
- alias << enqueue
51
+ def enqueue(*items)
52
+ @items.concat(items)
53
+
54
+ self.signal unless self.empty?
55
+ end
52
56
 
53
57
  def dequeue
54
58
  while @items.empty?
@@ -87,7 +91,7 @@ module Async
87
91
  @items.size >= @limit
88
92
  end
89
93
 
90
- def enqueue item
94
+ def <<(item)
91
95
  while limited?
92
96
  @full.wait
93
97
  end
@@ -95,6 +99,19 @@ module Async
95
99
  super
96
100
  end
97
101
 
102
+ def enqueue *items
103
+ while !items.empty?
104
+ while limited?
105
+ @full.wait
106
+ end
107
+
108
+ available = @limit - @items.size
109
+ @items.concat(items.shift(available))
110
+
111
+ self.signal unless self.empty?
112
+ end
113
+ end
114
+
98
115
  def dequeue
99
116
  item = super
100
117
 
data/lib/async/task.rb CHANGED
@@ -230,18 +230,19 @@ module Async
230
230
  private
231
231
 
232
232
  # This is a very tricky aspect of tasks to get right. I've modelled it after `Thread` but it's slightly different in that the exception can propagate back up through the reactor. If the user writes code which raises an exception, that exception should always be visible, i.e. cause a failure. If it's not visible, such code fails silently and can be very difficult to debug.
233
- # As an explcit choice, the user can start a task which doesn't propagate exceptions. This only applies to `StandardError` and derived tasks. This allows tasks to internally capture their error state which is raised when invoking `Task#result` similar to how `Thread#join` works. This mode makes {ruby Async::Task} behave more like a promise, and you would need to ensure that someone calls `Task#result` otherwise you might miss important errors.
234
- def fail!(exception = nil, propagate = true)
233
+ def fail!(exception = false, propagate = true)
235
234
  @status = :failed
236
235
  @result = exception
237
236
 
238
- if propagate
239
- raise
240
- elsif @finished.nil?
241
- # If no one has called wait, we log this as an error:
242
- Console.logger.error(self) {$!}
243
- else
244
- Console.logger.debug(self) {$!}
237
+ if exception
238
+ if propagate
239
+ raise exception
240
+ elsif @finished.nil?
241
+ # If no one has called wait, we log this as a warning:
242
+ Console.logger.warn(self, "Task may have ended with unhandled exception.", exception)
243
+ else
244
+ Console.logger.debug(self, exception)
245
+ end
245
246
  end
246
247
  end
247
248
 
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative 'condition'
24
+
25
+ module Async
26
+ class Variable
27
+ def initialize(condition = Condition.new)
28
+ @condition = condition
29
+ @value = nil
30
+ end
31
+
32
+ def resolve(value = true)
33
+ @value = value
34
+ condition = @condition
35
+ @condition = nil
36
+
37
+ self.freeze
38
+
39
+ condition.signal(value)
40
+ end
41
+
42
+ def resolved?
43
+ @condition.nil?
44
+ end
45
+
46
+ def value
47
+ @condition&.wait
48
+ return @value
49
+ end
50
+
51
+ def wait
52
+ self.value
53
+ end
54
+ end
55
+ end
data/lib/async/version.rb CHANGED
@@ -21,5 +21,5 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  module Async
24
- VERSION = "1.30.0"
24
+ VERSION = "1.30.3"
25
25
  end
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.30.0
4
+ version: 1.30.3
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-07-21 00:00:00.000000000 Z
11
+ date: 2022-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: console
@@ -156,6 +156,7 @@ files:
156
156
  - lib/async/scheduler.rb
157
157
  - lib/async/semaphore.rb
158
158
  - lib/async/task.rb
159
+ - lib/async/variable.rb
159
160
  - lib/async/version.rb
160
161
  - lib/async/wrapper.rb
161
162
  - lib/kernel/async.rb
@@ -179,7 +180,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
180
  - !ruby/object:Gem::Version
180
181
  version: '0'
181
182
  requirements: []
182
- rubygems_version: 3.2.22
183
+ rubygems_version: 3.3.7
183
184
  signing_key:
184
185
  specification_version: 4
185
186
  summary: A concurrency framework for Ruby.