async 1.25.0 → 1.26.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/lib/async/barrier.rb +1 -1
  3. data/lib/async/node.rb +171 -49
  4. data/lib/async/queue.rb +5 -1
  5. data/lib/async/reactor.rb +16 -11
  6. data/lib/async/version.rb +1 -1
  7. metadata +54 -99
  8. data/.editorconfig +0 -6
  9. data/.github/workflows/development.yml +0 -55
  10. data/.gitignore +0 -14
  11. data/.rspec +0 -3
  12. data/.yardopts +0 -1
  13. data/Gemfile +0 -20
  14. data/Guardfile +0 -14
  15. data/README.md +0 -385
  16. data/Rakefile +0 -40
  17. data/async.gemspec +0 -34
  18. data/bake.rb +0 -33
  19. data/benchmark/async_vs_lightio.rb +0 -84
  20. data/benchmark/fiber_count.rb +0 -10
  21. data/benchmark/rubies/README.md +0 -51
  22. data/benchmark/rubies/benchmark.rb +0 -220
  23. data/benchmark/thread_count.rb +0 -9
  24. data/benchmark/thread_vs_fiber.rb +0 -45
  25. data/examples/async_method.rb +0 -60
  26. data/examples/callback/loop.rb +0 -44
  27. data/examples/capture/README.md +0 -59
  28. data/examples/capture/capture.rb +0 -116
  29. data/examples/fibers.rb +0 -178
  30. data/examples/queue/producer.rb +0 -28
  31. data/examples/sleep_sort.rb +0 -40
  32. data/examples/stop/condition.rb +0 -31
  33. data/examples/stop/sleep.rb +0 -42
  34. data/gems/event.gemfile +0 -4
  35. data/logo.png +0 -0
  36. data/logo.svg +0 -64
  37. data/papers/1982 Grossman.pdf +0 -0
  38. data/papers/1987 ODell.pdf +0 -0
  39. data/spec/async/barrier_spec.rb +0 -116
  40. data/spec/async/chainable_async_examples.rb +0 -13
  41. data/spec/async/clock_spec.rb +0 -37
  42. data/spec/async/condition_examples.rb +0 -105
  43. data/spec/async/condition_spec.rb +0 -72
  44. data/spec/async/logger_spec.rb +0 -65
  45. data/spec/async/node_spec.rb +0 -175
  46. data/spec/async/notification_spec.rb +0 -66
  47. data/spec/async/performance_spec.rb +0 -72
  48. data/spec/async/queue_spec.rb +0 -129
  49. data/spec/async/reactor/nested_spec.rb +0 -52
  50. data/spec/async/reactor_spec.rb +0 -233
  51. data/spec/async/semaphore_spec.rb +0 -169
  52. data/spec/async/task_spec.rb +0 -466
  53. data/spec/async/wrapper_spec.rb +0 -203
  54. data/spec/async_spec.rb +0 -33
  55. data/spec/enumerator_spec.rb +0 -83
  56. data/spec/kernel/async_spec.rb +0 -33
  57. data/spec/kernel/sync_spec.rb +0 -54
  58. data/spec/spec_helper.rb +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e483e124943c2ca198118249cfd157307afd86a6e9ead4b376be27ffc95b645
4
- data.tar.gz: c460b159f280389b26237c41fd20bac56d9e5b2c525f884402f6170b85fd5053
3
+ metadata.gz: 72c4f7456b611f436a18f0d143ba5b4c9bb4c7882ad241f3ba251a139c020945
4
+ data.tar.gz: 4270eef8e1de0d08b953eb373a665d3fb8c0b9348e13d99ac6c61e7aead63db5
5
5
  SHA512:
6
- metadata.gz: 482ff867811aa68736b37a50d83e5850f4a1f9a310274b8993898c5577136e7502f5c369a3c9bf4685380b88a71de2ff4ed04fbd92115e8918472522e92786ea
7
- data.tar.gz: 37584a2af7140b2a4efa0fb60879e97ddae99879f97b137add7fb62662139300e280a9126cf24f559172ecb7ba1f2a6c21eb77adc317df9ae54f9ddb8378f928
6
+ metadata.gz: 359f4bcd33b438eca0518a00b77d336c25ab49ed3346180013bc135743d9a5447c178416680e5289085cbd9d75718772d7a06e25d44a0b0303cd35086da0c8f5
7
+ data.tar.gz: 420f280a2ed6d2cb4d363c6a4f80a695a1ad963ead1b040daa16ce9a18ceab9b8f3f6bcee707658a946acba3656f54578df9ed36e2bf8ffc0e6d151cdbbc9e9e
@@ -23,7 +23,7 @@
23
23
  require_relative 'task'
24
24
 
25
25
  module Async
26
- # A semaphore is used to control access to a common resource in a concurrent system. A useful way to think of a semaphore as used in the real-world systems is as a record of how many units of a particular resource are available, coupled with operations to adjust that record safely (i.e. to avoid race conditions) as units are required or become free, and, if necessary, wait until a unit of the resource becomes available.
26
+ # A barrier is used to synchronize multiple tasks, waiting for them all to complete before continuing.
27
27
  class Barrier
28
28
  def initialize(parent: nil)
29
29
  @tasks = []
@@ -20,49 +20,182 @@
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 'set'
24
-
25
23
  module Async
24
+ # A double linked list.
25
+ class List
26
+ def initialize
27
+ @head = nil
28
+ @tail = nil
29
+ @size = 0
30
+ end
31
+
32
+ attr :size
33
+
34
+ attr_accessor :head
35
+ attr_accessor :tail
36
+
37
+ # Inserts an item at the end of the list.
38
+ def insert(item)
39
+ unless @head
40
+ @head = item
41
+ @tail = item
42
+
43
+ # Consistency:
44
+ item.head = nil
45
+ item.tail = nil
46
+ else
47
+ @tail.tail = item
48
+ item.head = @tail
49
+
50
+ # Consistency:
51
+ item.tail = nil
52
+
53
+ @tail = item
54
+ end
55
+
56
+ @size += 1
57
+
58
+ return self
59
+ end
60
+
61
+ def delete(item)
62
+ if @head.equal?(item)
63
+ @head = @head.tail
64
+ else
65
+ item.head.tail = item.tail
66
+ end
67
+
68
+ if @tail.equal?(item)
69
+ @tail = @tail.head
70
+ else
71
+ item.tail.head = item.head
72
+ end
73
+
74
+ item.head = nil
75
+ item.tail = nil
76
+
77
+ @size -= 1
78
+
79
+ return self
80
+ end
81
+
82
+ def each
83
+ return to_enum unless block_given?
84
+
85
+ item = @head
86
+ while item
87
+ # We store the tail pointer so we can remove the current item from the linked list:
88
+ tail = item.tail
89
+ yield item
90
+ item = tail
91
+ end
92
+ end
93
+
94
+ def include?(needle)
95
+ self.each do |item|
96
+ return true if needle.equal?(item)
97
+ end
98
+
99
+ return false
100
+ end
101
+
102
+ def first
103
+ @head
104
+ end
105
+
106
+ def last
107
+ @tail
108
+ end
109
+
110
+ def empty?
111
+ @head.nil?
112
+ end
113
+
114
+ def nil?
115
+ @head.nil?
116
+ end
117
+ end
118
+
119
+ private_constant :List
120
+
121
+ class Children < List
122
+ def initialize
123
+ super
124
+
125
+ @transient_count = 0
126
+ end
127
+
128
+ # Does this node have (direct) transient children?
129
+ def transients?
130
+ @transient_count > 0
131
+ end
132
+
133
+ def insert(item)
134
+ if item.transient?
135
+ @transient_count += 1
136
+ end
137
+
138
+ super
139
+ end
140
+
141
+ def delete(item)
142
+ if item.transient?
143
+ @transient_count -= 1
144
+ end
145
+
146
+ super
147
+ end
148
+
149
+ def finished?
150
+ @size == @transient_count
151
+ end
152
+ end
153
+
26
154
  # Represents a node in a tree, used for nested {Task} instances.
27
155
  class Node
28
156
  # Create a new node in the tree.
29
157
  # @param parent [Node, nil] This node will attach to the given parent.
30
158
  def initialize(parent = nil, annotation: nil, transient: false)
31
- @children = nil
32
159
  @parent = nil
33
-
34
- # The number of transient children:
35
- @transients = 0
160
+ @children = nil
36
161
 
37
162
  @annotation = annotation
38
163
  @object_name = nil
39
164
 
40
165
  @transient = transient
41
166
 
167
+ @head = nil
168
+ @tail = nil
169
+
42
170
  if parent
43
- self.parent = parent
171
+ parent.add_child(self)
44
172
  end
45
173
  end
46
174
 
175
+ # You should not directly rely on these pointers but instead use `#children`.
176
+ # List pointers:
177
+ attr_accessor :head
178
+ attr_accessor :tail
179
+
47
180
  # @attr parent [Node, nil]
48
181
  attr :parent
49
182
 
50
- # @attr children [Set<Node>] Optional list of children.
183
+ # @attr children [List<Node>] Optional list of children.
51
184
  attr :children
52
185
 
53
186
  # A useful identifier for the current node.
54
187
  attr :annotation
55
188
 
189
+ # Whether there are children?
190
+ def children?
191
+ @children != nil && !@children.empty?
192
+ end
193
+
56
194
  # Is this node transient?
57
195
  def transient?
58
196
  @transient
59
197
  end
60
198
 
61
- # Does this node have (direct) transient children?
62
- def transients?
63
- @transients > 0
64
- end
65
-
66
199
  def annotate(annotation)
67
200
  if block_given?
68
201
  previous_annotation = @annotation
@@ -95,13 +228,12 @@ module Async
95
228
  return if @parent.equal?(parent)
96
229
 
97
230
  if @parent
98
- @parent.reap(self)
231
+ @parent.delete_child(self)
99
232
  @parent = nil
100
233
  end
101
234
 
102
235
  if parent
103
- @parent = parent
104
- @parent.add_child(self)
236
+ parent.add_child(self)
105
237
  end
106
238
 
107
239
  return self
@@ -112,52 +244,42 @@ module Async
112
244
  end
113
245
 
114
246
  protected def add_child child
115
- @children ||= Set.new
116
- @children << child
117
-
118
- if child.transient?
119
- @transients += 1
120
- end
247
+ @children ||= Children.new
248
+ @children.insert(child)
249
+ child.set_parent(self)
250
+ end
251
+
252
+ protected def delete_child(child)
253
+ @children.delete(child)
254
+ child.set_parent(nil)
121
255
  end
122
256
 
123
257
  # Whether the node can be consumed safely. By default, checks if the
124
258
  # children set is empty.
125
259
  # @return [Boolean]
126
260
  def finished?
127
- @children.nil? || @children.empty? || (@children.size == @transients)
261
+ @children.nil? || @children.finished?
128
262
  end
129
263
 
130
264
  # If the node has a parent, and is {finished?}, then remove this node from
131
265
  # the parent.
132
266
  def consume
133
- if @parent && finished?
134
- @parent.reap(self)
267
+ if parent = @parent and finished?
268
+ parent.delete_child(self)
135
269
 
136
- # After reaping self, children are all moved elsewhere.
137
- @children = nil
138
- @transients = 0
139
-
140
- @parent.consume
141
- @parent = nil
142
- end
143
- end
144
-
145
- # Remove a given child node.
146
- # @param child [Node]
147
- def reap(child)
148
- @children.delete(child)
149
-
150
- if child.transient?
151
- @transients -= 1
152
- end
153
-
154
- child.children&.each do |grand_child|
155
- if grand_child.finished?
156
- grand_child.set_parent(nil)
157
- else
158
- grand_child.set_parent(self)
159
- add_child(grand_child)
270
+ if @children
271
+ @children.each do |child|
272
+ if child.finished?
273
+ delete_child(child)
274
+ else
275
+ parent.add_child(child)
276
+ end
277
+ end
278
+
279
+ @children = nil
160
280
  end
281
+
282
+ parent.consume
161
283
  end
162
284
  end
163
285
 
@@ -34,7 +34,11 @@ module Async
34
34
 
35
35
  attr :items
36
36
 
37
- def enqueue item
37
+ def empty?
38
+ @items.empty?
39
+ end
40
+
41
+ def enqueue(item)
38
42
  @items.push(item)
39
43
 
40
44
  self.signal unless self.empty?
@@ -50,10 +50,10 @@ module Async
50
50
 
51
51
  return reactor.async(*arguments, **options, &block)
52
52
  else
53
- reactor = self.new(**options)
53
+ reactor = self.new
54
54
 
55
55
  begin
56
- return reactor.run(*arguments, &block)
56
+ return reactor.run(*arguments, **options, &block)
57
57
  ensure
58
58
  reactor.close
59
59
  end
@@ -91,11 +91,11 @@ module Async
91
91
  end
92
92
 
93
93
  def to_s
94
- "\#<#{self.description} #{@children&.size || 0} children #{stopped? ? 'stopped' : 'running'}>"
94
+ "\#<#{self.description} #{@children&.size || 0} children (#{stopped? ? 'stopped' : 'running'})>"
95
95
  end
96
96
 
97
97
  def stopped?
98
- @children.nil? || @children.empty?
98
+ @children.nil?
99
99
  end
100
100
 
101
101
  # TODO Remove these in next major release. They are too confusing to use correctly.
@@ -222,13 +222,11 @@ module Async
222
222
  return true
223
223
  end
224
224
 
225
- # Run the reactor until either all tasks complete or {#pause} or {#stop} is
226
- # invoked. Proxies arguments to {#async} immediately before entering the
227
- # loop, if a block is provided.
228
- def run(*arguments, &block)
225
+ # Run the reactor until all tasks are finished. Proxies arguments to {#async} immediately before entering the loop, if a block is provided.
226
+ def run(*arguments, **options, &block)
229
227
  raise RuntimeError, 'Reactor has been closed' if @selector.nil?
230
228
 
231
- initial_task = self.async(*arguments, &block) if block_given?
229
+ initial_task = self.async(*arguments, **options, &block) if block_given?
232
230
 
233
231
  while self.run_once
234
232
  # Round and round we go!
@@ -239,12 +237,19 @@ module Async
239
237
  logger.debug(self) {"Exiting run-loop because #{$! ? $! : 'finished'}."}
240
238
  end
241
239
 
240
+ def stop(later = true)
241
+ @children&.each do |child|
242
+ # We don't want this process to propagate `Async::Stop` exceptions, so we schedule tasks to stop later.
243
+ child.stop(later)
244
+ end
245
+ end
246
+
242
247
  # Stop each of the children tasks and close the selector.
243
248
  #
244
249
  # @return [void]
245
250
  def close
246
251
  # 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.
247
- self.stop
252
+ self.stop(false)
248
253
 
249
254
  @selector.close
250
255
  @selector = nil
@@ -255,7 +260,7 @@ module Async
255
260
  def closed?
256
261
  @selector.nil?
257
262
  end
258
-
263
+
259
264
  # Put the calling fiber to sleep for a given ammount of time.
260
265
  # @param duration [Numeric] The time in seconds, to sleep for.
261
266
  def sleep(duration)
@@ -21,5 +21,5 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  module Async
24
- VERSION = "1.25.0"
24
+ VERSION = "1.26.2"
25
25
  end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.25.0
4
+ version: 1.26.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-23 00:00:00.000000000 Z
11
+ date: 2020-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: nio4r
14
+ name: console
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.3'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.3'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: timers
28
+ name: nio4r
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '4.1'
33
+ version: '2.3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '4.1'
40
+ version: '2.3'
41
41
  - !ruby/object:Gem::Dependency
42
- name: console
42
+ name: timers
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.0'
47
+ version: '4.1'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.0'
54
+ version: '4.1'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: async-rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -67,19 +67,33 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.1'
69
69
  - !ruby/object:Gem::Dependency
70
- name: covered
70
+ name: bake-bundler
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '0.10'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '0.10'
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bake-modernize
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -95,21 +109,21 @@ dependencies:
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
- name: rspec
112
+ name: covered
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: '3.6'
117
+ version: '0.10'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: '3.6'
124
+ version: '0.10'
111
125
  - !ruby/object:Gem::Dependency
112
- name: bake-bundler
126
+ name: benchmark-ips
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
@@ -122,41 +136,26 @@ dependencies:
122
136
  - - ">="
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
125
- description: "\t\tAsync is a modern concurrency framework for Ruby. It implements
126
- the\n\t\treactor pattern, providing both non-blocking I/O and timer events.\n"
139
+ - !ruby/object:Gem::Dependency
140
+ name: rspec
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '3.6'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '3.6'
153
+ description:
127
154
  email:
128
- - samuel.williams@oriontransfer.co.nz
129
155
  executables: []
130
156
  extensions: []
131
157
  extra_rdoc_files: []
132
158
  files:
133
- - ".editorconfig"
134
- - ".github/workflows/development.yml"
135
- - ".gitignore"
136
- - ".rspec"
137
- - ".yardopts"
138
- - Gemfile
139
- - Guardfile
140
- - README.md
141
- - Rakefile
142
- - async.gemspec
143
- - bake.rb
144
- - benchmark/async_vs_lightio.rb
145
- - benchmark/fiber_count.rb
146
- - benchmark/rubies/README.md
147
- - benchmark/rubies/benchmark.rb
148
- - benchmark/thread_count.rb
149
- - benchmark/thread_vs_fiber.rb
150
- - examples/async_method.rb
151
- - examples/callback/loop.rb
152
- - examples/capture/README.md
153
- - examples/capture/capture.rb
154
- - examples/fibers.rb
155
- - examples/queue/producer.rb
156
- - examples/sleep_sort.rb
157
- - examples/stop/condition.rb
158
- - examples/stop/sleep.rb
159
- - gems/event.gemfile
160
159
  - lib/async.rb
161
160
  - lib/async/barrier.rb
162
161
  - lib/async/clock.rb
@@ -174,35 +173,11 @@ files:
174
173
  - lib/async/wrapper.rb
175
174
  - lib/kernel/async.rb
176
175
  - lib/kernel/sync.rb
177
- - logo.png
178
- - logo.svg
179
- - papers/1982 Grossman.pdf
180
- - papers/1987 ODell.pdf
181
- - spec/async/barrier_spec.rb
182
- - spec/async/chainable_async_examples.rb
183
- - spec/async/clock_spec.rb
184
- - spec/async/condition_examples.rb
185
- - spec/async/condition_spec.rb
186
- - spec/async/logger_spec.rb
187
- - spec/async/node_spec.rb
188
- - spec/async/notification_spec.rb
189
- - spec/async/performance_spec.rb
190
- - spec/async/queue_spec.rb
191
- - spec/async/reactor/nested_spec.rb
192
- - spec/async/reactor_spec.rb
193
- - spec/async/semaphore_spec.rb
194
- - spec/async/task_spec.rb
195
- - spec/async/wrapper_spec.rb
196
- - spec/async_spec.rb
197
- - spec/enumerator_spec.rb
198
- - spec/kernel/async_spec.rb
199
- - spec/kernel/sync_spec.rb
200
- - spec/spec_helper.rb
201
176
  homepage: https://github.com/socketry/async
202
177
  licenses:
203
178
  - MIT
204
179
  metadata: {}
205
- post_install_message:
180
+ post_install_message:
206
181
  rdoc_options: []
207
182
  require_paths:
208
183
  - lib
@@ -218,27 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
193
  version: '0'
219
194
  requirements: []
220
195
  rubygems_version: 3.1.2
221
- signing_key:
196
+ signing_key:
222
197
  specification_version: 4
223
- summary: Async is an concurrency framework based for Ruby.
224
- test_files:
225
- - spec/async/barrier_spec.rb
226
- - spec/async/chainable_async_examples.rb
227
- - spec/async/clock_spec.rb
228
- - spec/async/condition_examples.rb
229
- - spec/async/condition_spec.rb
230
- - spec/async/logger_spec.rb
231
- - spec/async/node_spec.rb
232
- - spec/async/notification_spec.rb
233
- - spec/async/performance_spec.rb
234
- - spec/async/queue_spec.rb
235
- - spec/async/reactor/nested_spec.rb
236
- - spec/async/reactor_spec.rb
237
- - spec/async/semaphore_spec.rb
238
- - spec/async/task_spec.rb
239
- - spec/async/wrapper_spec.rb
240
- - spec/async_spec.rb
241
- - spec/enumerator_spec.rb
242
- - spec/kernel/async_spec.rb
243
- - spec/kernel/sync_spec.rb
244
- - spec/spec_helper.rb
198
+ summary: A concurrency framework for Ruby.
199
+ test_files: []