async 1.25.2 → 1.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/async/barrier.rb +1 -1
  3. data/lib/async/clock.rb +33 -1
  4. data/lib/async/logger.rb +1 -6
  5. data/lib/async/node.rb +20 -2
  6. data/lib/async/queue.rb +5 -1
  7. data/lib/async/reactor.rb +73 -12
  8. data/lib/async/scheduler.rb +112 -0
  9. data/lib/async/task.rb +11 -3
  10. data/lib/async/version.rb +1 -1
  11. metadata +46 -104
  12. data/.editorconfig +0 -6
  13. data/.github/workflows/development.yml +0 -55
  14. data/.gitignore +0 -14
  15. data/.rspec +0 -3
  16. data/.yardopts +0 -1
  17. data/Gemfile +0 -20
  18. data/Guardfile +0 -14
  19. data/README.md +0 -385
  20. data/Rakefile +0 -40
  21. data/async.gemspec +0 -34
  22. data/bake.rb +0 -33
  23. data/benchmark/async_vs_lightio.rb +0 -84
  24. data/benchmark/fiber_count.rb +0 -10
  25. data/benchmark/rubies/README.md +0 -51
  26. data/benchmark/rubies/benchmark.rb +0 -220
  27. data/benchmark/thread_count.rb +0 -9
  28. data/benchmark/thread_vs_fiber.rb +0 -45
  29. data/examples/async_method.rb +0 -60
  30. data/examples/callback/loop.rb +0 -44
  31. data/examples/capture/README.md +0 -59
  32. data/examples/capture/capture.rb +0 -116
  33. data/examples/fibers.rb +0 -178
  34. data/examples/queue/producer.rb +0 -28
  35. data/examples/sleep_sort.rb +0 -40
  36. data/examples/stop/condition.rb +0 -31
  37. data/examples/stop/sleep.rb +0 -42
  38. data/gems/event.gemfile +0 -4
  39. data/logo.png +0 -0
  40. data/logo.svg +0 -64
  41. data/papers/1982 Grossman.pdf +0 -0
  42. data/papers/1987 ODell.pdf +0 -0
  43. data/spec/async/barrier_spec.rb +0 -116
  44. data/spec/async/chainable_async_examples.rb +0 -13
  45. data/spec/async/clock_spec.rb +0 -37
  46. data/spec/async/condition_examples.rb +0 -105
  47. data/spec/async/condition_spec.rb +0 -72
  48. data/spec/async/logger_spec.rb +0 -65
  49. data/spec/async/node_spec.rb +0 -193
  50. data/spec/async/notification_spec.rb +0 -66
  51. data/spec/async/performance_spec.rb +0 -72
  52. data/spec/async/queue_spec.rb +0 -129
  53. data/spec/async/reactor/nested_spec.rb +0 -52
  54. data/spec/async/reactor_spec.rb +0 -253
  55. data/spec/async/semaphore_spec.rb +0 -169
  56. data/spec/async/task_spec.rb +0 -476
  57. data/spec/async/wrapper_spec.rb +0 -203
  58. data/spec/async_spec.rb +0 -33
  59. data/spec/enumerator_spec.rb +0 -83
  60. data/spec/kernel/async_spec.rb +0 -33
  61. data/spec/kernel/sync_spec.rb +0 -54
  62. data/spec/spec_helper.rb +0 -18
@@ -1,72 +0,0 @@
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 'async/rspec'
24
- require 'async/condition'
25
-
26
- require_relative 'condition_examples'
27
-
28
- RSpec.describe Async::Condition do
29
- include_context Async::RSpec::Reactor
30
-
31
- it 'should continue after condition is signalled' do
32
- task = reactor.async do
33
- subject.wait
34
- end
35
-
36
- expect(task.status).to be :running
37
-
38
- # This will cause the task to exit:
39
- subject.signal
40
-
41
- expect(task.status).to be :complete
42
-
43
- task.stop
44
- end
45
-
46
- it 'can stop nested task' do
47
- producer = nil
48
-
49
- consumer = reactor.async do |task|
50
- condition = Async::Condition.new
51
-
52
- producer = task.async do |subtask|
53
- subtask.yield
54
- condition.signal
55
- subtask.sleep(10)
56
- end
57
-
58
- condition.wait
59
- expect do
60
- producer.stop
61
- end.to_not raise_error
62
- end
63
-
64
- consumer.wait
65
- producer.wait
66
-
67
- expect(producer.status).to be :stopped
68
- expect(consumer.status).to be :complete
69
- end
70
-
71
- it_behaves_like Async::Condition
72
- end
@@ -1,65 +0,0 @@
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 'async'
24
- require 'async/logger'
25
- require 'console/capture'
26
-
27
- RSpec.describe 'Async.logger' do
28
- let(:name) {"nested"}
29
- let(:message) {"Talk is cheap. Show me the code."}
30
-
31
- let(:capture) {Console::Capture.new}
32
- let(:logger) {Console::Logger.new(capture, name: name)}
33
-
34
- it "can use nested logger" do
35
- Async(logger: logger) do |task|
36
- expect(task.logger).to be == logger
37
- logger.warn message
38
- end.wait
39
-
40
- expect(capture.events.last).to include({
41
- severity: :warn,
42
- name: name,
43
- subject: message,
44
- })
45
- end
46
-
47
- it "can change nested logger" do
48
- Async do |parent|
49
- parent.async(logger: logger) do |task|
50
- expect(task.logger).to be == logger
51
- expect(Async.logger).to be == logger
52
- end.wait
53
- end.wait
54
- end
55
-
56
- it "can use parent logger" do
57
- Async(logger: logger) do |parent|
58
- child = parent.async{|task| task.yield}
59
-
60
- expect(parent.logger).to be == logger
61
- expect(child.logger).to be == logger
62
- expect(Async.logger).to be == logger
63
- end.wait
64
- end
65
- end
@@ -1,193 +0,0 @@
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 'async/node'
24
-
25
- RSpec.describe Async::Node do
26
- describe '#parent=' do
27
- let(:child) {Async::Node.new(subject)}
28
-
29
- it "should construct nested tree" do
30
- expect(child.parent).to be subject
31
- expect(subject.children).to include(child)
32
- end
33
-
34
- it "should break nested tree" do
35
- child.parent = nil
36
-
37
- expect(child.parent).to be_nil
38
- expect(subject.children).to be_nil
39
- end
40
-
41
- it "can consume bottom to top" do
42
- child.consume
43
-
44
- expect(child.parent).to be_nil
45
- expect(subject.children).to be_nil
46
- end
47
- end
48
-
49
- describe '#print_hierarchy' do
50
- let(:buffer) {StringIO.new}
51
- let(:output) {buffer.string}
52
- let(:lines) {output.lines}
53
-
54
- let!(:child) {Async::Node.new(subject)}
55
-
56
- it "can print hierarchy to bufffer" do
57
- subject.print_hierarchy(buffer)
58
-
59
- expect(lines.size).to be 2
60
-
61
- expect(lines[0]).to be =~ /#<Async::Node:0x\h+>\n/
62
- expect(lines[1]).to be =~ /\t#<Async::Node:0x\h+>\n/
63
- end
64
- end
65
-
66
- describe '#consume' do
67
- it "can't consume middle node" do
68
- middle = Async::Node.new(subject)
69
- bottom = Async::Node.new(middle)
70
-
71
- expect(bottom.parent).to be middle
72
-
73
- middle.consume
74
-
75
- expect(bottom.parent).to be middle
76
- end
77
-
78
- it "can consume node while enumerating children" do
79
- 3.times do
80
- Async::Node.new(subject)
81
- end
82
-
83
- children = subject.children.each.to_a
84
- expect(subject.children.size).to be 3
85
-
86
- enumerated = []
87
-
88
- subject.children.each do |child|
89
- child.consume
90
- enumerated << child
91
- end
92
-
93
- expect(enumerated).to be == children
94
- end
95
- end
96
-
97
- describe '#annotate' do
98
- let(:annotation) {'reticulating splines'}
99
-
100
- it "should have no annotation by default" do
101
- expect(subject.annotation).to be_nil
102
- end
103
-
104
- it 'should output annotation when invoking #to_s' do
105
- subject.annotate(annotation) do
106
- expect(subject.to_s).to include(annotation)
107
- end
108
- end
109
-
110
- it 'can assign annotation' do
111
- subject.annotate(annotation)
112
-
113
- expect(subject.annotation).to be == annotation
114
- end
115
- end
116
-
117
- describe '#transient' do
118
- it 'can move transient child to parent' do
119
- # This example represents a persistent web connection (middle) with a background reader (child). We look at how when that connection goes out of scope, what happens to the child.
120
-
121
- # subject -> middle -> child (transient)
122
-
123
- middle = Async::Node.new(subject)
124
- child = Async::Node.new(middle, transient: true)
125
-
126
- expect(child).to be_transient
127
- expect(middle).to be_finished
128
-
129
- allow(child).to receive(:finished?).and_return(false)
130
-
131
- middle.consume
132
-
133
- # subject -> child (transient)
134
- expect(child.parent).to be subject
135
- expect(subject.children).to include(child)
136
- expect(subject.children).to_not include(middle)
137
-
138
- expect(child).to_not be_finished
139
- expect(subject).to be_finished
140
-
141
- expect(child).to receive(:stop)
142
- subject.stop
143
- end
144
-
145
- it 'can move transient sibling to parent' do
146
- # This example represents a server task (middle) which has a single task listening on incoming connections (child2), and a transient task which is monitoring those connections/some shared resource (child1). We look at what happens when the server listener finishes.
147
-
148
- # subject -> middle -> child1 (transient)
149
- # -> child2
150
- middle = Async::Node.new(subject, annotation: "middle")
151
- child1 = Async::Node.new(middle, transient: true, annotation: "child1")
152
- child2 = Async::Node.new(middle, annotation: "child2")
153
-
154
- allow(child1).to receive(:finished?).and_return(false)
155
-
156
- middle.consume
157
-
158
- # subject -> middle -> child1 (transient)
159
- # -> child2
160
- expect(child1.parent).to be middle
161
- expect(child2.parent).to be middle
162
- expect(middle.parent).to be subject
163
- expect(subject.children).to include(middle)
164
- expect(middle.children).to include(child1)
165
- expect(middle.children).to include(child2)
166
-
167
- child2.consume
168
-
169
- # subject -> child1 (transient)
170
- expect(child1.parent).to be subject
171
- expect(child2.parent).to be_nil
172
- expect(middle.parent).to be_nil
173
- expect(subject.children).to include(child1)
174
- expect(middle.children).to be_nil
175
- end
176
-
177
- it 'ignores non-transient children of transient parent' do
178
- # subject -> middle (transient) -> child
179
- middle = Async::Node.new(subject, transient: true)
180
- child = Async::Node.new(middle)
181
-
182
- allow(middle).to receive(:finished?).and_return(false)
183
-
184
- child.consume
185
-
186
- # subject -> middle (transient)
187
- expect(child.parent).to be_nil
188
- expect(middle.parent).to be subject
189
- expect(subject.children).to include(middle)
190
- expect(middle.children).to be_nil
191
- end
192
- end
193
- end
@@ -1,66 +0,0 @@
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 'async/rspec'
24
- require 'async/notification'
25
-
26
- require_relative 'condition_examples'
27
-
28
- RSpec.describe Async::Notification do
29
- include_context Async::RSpec::Reactor
30
-
31
- it 'should continue after notification is signalled' do
32
- sequence = []
33
-
34
- task = reactor.async do
35
- sequence << :waiting
36
- subject.wait
37
- sequence << :resumed
38
- end
39
-
40
- expect(task.status).to be :running
41
-
42
- sequence << :running
43
- # This will cause the task to exit:
44
- subject.signal
45
- sequence << :signalled
46
-
47
- expect(task.status).to be :running
48
-
49
- sequence << :yielding
50
- reactor.yield
51
- sequence << :finished
52
-
53
- expect(task.status).to be :complete
54
-
55
- expect(sequence).to be == [
56
- :waiting,
57
- :running,
58
- :signalled,
59
- :yielding,
60
- :resumed,
61
- :finished
62
- ]
63
- end
64
-
65
- it_behaves_like Async::Condition
66
- end
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright, 2019, 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 'benchmark/ips'
24
- require 'async'
25
-
26
- RSpec.describe Async::Wrapper do
27
- let(:pipe) {IO.pipe}
28
-
29
- after do
30
- pipe.each(&:close)
31
- end
32
-
33
- let(:input) {described_class.new(pipe.first)}
34
- let(:output) {described_class.new(pipe.last)}
35
-
36
- it "should be fast to wait until readable" do
37
- Benchmark.ips do |x|
38
- x.report('Wrapper#wait_readable') do |repeats|
39
- Async do |task|
40
- input = Async::Wrapper.new(pipe.first, task.reactor)
41
- output = pipe.last
42
-
43
- repeats.times do
44
- output.write(".")
45
- input.wait_readable
46
- input.io.read(1)
47
- end
48
-
49
- input.reactor = nil
50
- end
51
- end
52
-
53
- x.report('Reactor#register') do |repeats|
54
- Async do |task|
55
- input = pipe.first
56
- monitor = task.reactor.register(input, :r)
57
- output = pipe.last
58
-
59
- repeats.times do
60
- output.write(".")
61
- Async::Task.yield
62
- input.read(1)
63
- end
64
-
65
- monitor.close
66
- end
67
- end
68
-
69
- x.compare!
70
- end
71
- end
72
- end