concurrent-ruby 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -21
- data/README.md +276 -275
- data/lib/concurrent.rb +28 -28
- data/lib/concurrent/agent.rb +114 -114
- data/lib/concurrent/cached_thread_pool.rb +131 -131
- data/lib/concurrent/defer.rb +65 -65
- data/lib/concurrent/event.rb +60 -60
- data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
- data/lib/concurrent/executor.rb +96 -96
- data/lib/concurrent/fixed_thread_pool.rb +99 -99
- data/lib/concurrent/functions.rb +120 -120
- data/lib/concurrent/future.rb +42 -42
- data/lib/concurrent/global_thread_pool.rb +24 -16
- data/lib/concurrent/goroutine.rb +29 -29
- data/lib/concurrent/null_thread_pool.rb +22 -22
- data/lib/concurrent/obligation.rb +67 -67
- data/lib/concurrent/promise.rb +174 -174
- data/lib/concurrent/reactor.rb +166 -166
- data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
- data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
- data/lib/concurrent/supervisor.rb +105 -105
- data/lib/concurrent/thread_pool.rb +76 -76
- data/lib/concurrent/utilities.rb +32 -32
- data/lib/concurrent/version.rb +3 -3
- data/lib/concurrent_ruby.rb +1 -1
- data/md/agent.md +123 -123
- data/md/defer.md +174 -174
- data/md/event.md +32 -32
- data/md/executor.md +187 -187
- data/md/future.md +83 -83
- data/md/goroutine.md +52 -52
- data/md/obligation.md +32 -32
- data/md/promise.md +227 -227
- data/md/thread_pool.md +224 -224
- data/spec/concurrent/agent_spec.rb +390 -386
- data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
- data/spec/concurrent/defer_spec.rb +199 -195
- data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
- data/spec/concurrent/event_spec.rb +134 -134
- data/spec/concurrent/executor_spec.rb +200 -200
- data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
- data/spec/concurrent/functions_spec.rb +217 -217
- data/spec/concurrent/future_spec.rb +112 -108
- data/spec/concurrent/global_thread_pool_spec.rb +11 -38
- data/spec/concurrent/goroutine_spec.rb +67 -67
- data/spec/concurrent/null_thread_pool_spec.rb +57 -57
- data/spec/concurrent/obligation_shared.rb +132 -132
- data/spec/concurrent/promise_spec.rb +316 -312
- data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
- data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
- data/spec/concurrent/reactor_spec.rb +364 -364
- data/spec/concurrent/supervisor_spec.rb +269 -269
- data/spec/concurrent/thread_pool_shared.rb +204 -204
- data/spec/concurrent/uses_global_thread_pool_shared.rb +64 -0
- data/spec/concurrent/utilities_spec.rb +74 -74
- data/spec/spec_helper.rb +32 -32
- metadata +17 -19
@@ -1,256 +1,256 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require 'concurrent/agent'
|
4
|
-
require 'concurrent/future'
|
5
|
-
require 'concurrent/goroutine'
|
6
|
-
require 'concurrent/promise'
|
7
|
-
|
8
|
-
if Functional::PLATFORM.mri?
|
9
|
-
|
10
|
-
module Concurrent
|
11
|
-
|
12
|
-
describe EventMachineDeferProxy do
|
13
|
-
|
14
|
-
subject { EventMachineDeferProxy.new }
|
15
|
-
|
16
|
-
after(:all) do
|
17
|
-
$GLOBAL_THREAD_POOL = FixedThreadPool.new(1)
|
18
|
-
end
|
19
|
-
|
20
|
-
context '#post' do
|
21
|
-
|
22
|
-
it 'proxies a call without arguments' do
|
23
|
-
@expected = false
|
24
|
-
EventMachine.run do
|
25
|
-
subject.post{ @expected = true }
|
26
|
-
sleep(0.1)
|
27
|
-
EventMachine.stop
|
28
|
-
end
|
29
|
-
@expected.should eq true
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'proxies a call with arguments' do
|
33
|
-
@expected = []
|
34
|
-
EventMachine.run do
|
35
|
-
subject.post(1,2,3){|*args| @expected = args }
|
36
|
-
sleep(0.1)
|
37
|
-
EventMachine.stop
|
38
|
-
end
|
39
|
-
@expected.should eq [1,2,3]
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'aliases #<<' do
|
43
|
-
@expected = false
|
44
|
-
EventMachine.run do
|
45
|
-
subject << proc{ @expected = true }
|
46
|
-
sleep(0.1)
|
47
|
-
EventMachine.stop
|
48
|
-
end
|
49
|
-
@expected.should eq true
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'operation' do
|
54
|
-
|
55
|
-
context 'goroutine' do
|
56
|
-
|
57
|
-
it 'passes all arguments to the block' do
|
58
|
-
$GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
|
59
|
-
|
60
|
-
EventMachine.run do
|
61
|
-
|
62
|
-
@expected = nil
|
63
|
-
go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
|
64
|
-
sleep(0.1)
|
65
|
-
@expected.should eq [3, 2, 1]
|
66
|
-
|
67
|
-
EventMachine.stop
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context Agent do
|
73
|
-
|
74
|
-
subject { Agent.new(0) }
|
75
|
-
|
76
|
-
before(:each) do
|
77
|
-
Agent.thread_pool = EventMachineDeferProxy.new
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'supports fulfillment' do
|
81
|
-
|
82
|
-
EventMachine.run do
|
83
|
-
|
84
|
-
@expected = []
|
85
|
-
subject.post{ @expected << 1 }
|
86
|
-
subject.post{ @expected << 2 }
|
87
|
-
subject.post{ @expected << 3 }
|
88
|
-
sleep(0.1)
|
89
|
-
@expected.should eq [1,2,3]
|
90
|
-
|
91
|
-
EventMachine.stop
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'supports validation' do
|
96
|
-
|
97
|
-
EventMachine.run do
|
98
|
-
|
99
|
-
@expected = nil
|
100
|
-
subject.validate{ @expected = 10; true }
|
101
|
-
subject.post{ nil }
|
102
|
-
sleep(0.1)
|
103
|
-
@expected.should eq 10
|
104
|
-
|
105
|
-
EventMachine.stop
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'supports rejection' do
|
110
|
-
|
111
|
-
EventMachine.run do
|
112
|
-
|
113
|
-
@expected = nil
|
114
|
-
subject.
|
115
|
-
on_error(StandardError){|ex| @expected = 1 }.
|
116
|
-
on_error(StandardError){|ex| @expected = 2 }.
|
117
|
-
on_error(StandardError){|ex| @expected = 3 }
|
118
|
-
subject.post{ raise StandardError }
|
119
|
-
sleep(0.1)
|
120
|
-
@expected.should eq 1
|
121
|
-
|
122
|
-
EventMachine.stop
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
context Future do
|
128
|
-
|
129
|
-
before(:each) do
|
130
|
-
Future.thread_pool = EventMachineDeferProxy.new
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'supports fulfillment' do
|
134
|
-
|
135
|
-
EventMachine.run do
|
136
|
-
|
137
|
-
@a = @b = @c = nil
|
138
|
-
f = Future.new(1, 2, 3) do |a, b, c|
|
139
|
-
@a, @b, @c = a, b, c
|
140
|
-
end
|
141
|
-
sleep(0.1)
|
142
|
-
[@a, @b, @c].should eq [1, 2, 3]
|
143
|
-
|
144
|
-
sleep(0.1)
|
145
|
-
EventMachine.stop
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
context Promise do
|
151
|
-
|
152
|
-
before(:each) do
|
153
|
-
Promise.thread_pool = EventMachineDeferProxy.new
|
154
|
-
end
|
155
|
-
|
156
|
-
context 'fulfillment' do
|
157
|
-
|
158
|
-
it 'passes all arguments to the first promise in the chain' do
|
159
|
-
|
160
|
-
EventMachine.run do
|
161
|
-
|
162
|
-
@a = @b = @c = nil
|
163
|
-
p = Promise.new(1, 2, 3) do |a, b, c|
|
164
|
-
@a, @b, @c = a, b, c
|
165
|
-
end
|
166
|
-
sleep(0.1)
|
167
|
-
[@a, @b, @c].should eq [1, 2, 3]
|
168
|
-
|
169
|
-
sleep(0.1)
|
170
|
-
EventMachine.stop
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
it 'passes the result of each block to all its children' do
|
175
|
-
|
176
|
-
EventMachine.run do
|
177
|
-
@expected = nil
|
178
|
-
Promise.new(10){|a| a * 2 }.then{|result| @expected = result}
|
179
|
-
sleep(0.1)
|
180
|
-
@expected.should eq 20
|
181
|
-
|
182
|
-
sleep(0.1)
|
183
|
-
EventMachine.stop
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
it 'sets the promise value to the result if its block' do
|
188
|
-
|
189
|
-
EventMachine.run do
|
190
|
-
|
191
|
-
p = Promise.new(10){|a| a * 2 }.then{|result| result * 2}
|
192
|
-
sleep(0.1)
|
193
|
-
p.value.should eq 40
|
194
|
-
|
195
|
-
sleep(0.1)
|
196
|
-
EventMachine.stop
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
context 'rejection' do
|
202
|
-
|
203
|
-
it 'sets the promise reason and error on exception' do
|
204
|
-
|
205
|
-
EventMachine.run do
|
206
|
-
|
207
|
-
p = Promise.new{ raise StandardError.new('Boom!') }
|
208
|
-
sleep(0.1)
|
209
|
-
p.reason.should be_a(Exception)
|
210
|
-
p.reason.should.to_s =~ /Boom!/
|
211
|
-
p.should be_rejected
|
212
|
-
|
213
|
-
sleep(0.1)
|
214
|
-
EventMachine.stop
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'calls the first exception block with a matching class' do
|
219
|
-
|
220
|
-
EventMachine.run do
|
221
|
-
|
222
|
-
@expected = nil
|
223
|
-
Promise.new{ raise StandardError }.
|
224
|
-
on_error(StandardError){|ex| @expected = 1 }.
|
225
|
-
on_error(StandardError){|ex| @expected = 2 }.
|
226
|
-
on_error(StandardError){|ex| @expected = 3 }
|
227
|
-
sleep(0.1)
|
228
|
-
@expected.should eq 1
|
229
|
-
|
230
|
-
sleep(0.1)
|
231
|
-
EventMachine.stop
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
it 'passes the exception object to the matched block' do
|
236
|
-
|
237
|
-
EventMachine.run do
|
238
|
-
|
239
|
-
@expected = nil
|
240
|
-
Promise.new{ raise StandardError }.
|
241
|
-
on_error(ArgumentError){|ex| @expected = ex }.
|
242
|
-
on_error(LoadError){|ex| @expected = ex }.
|
243
|
-
on_error(Exception){|ex| @expected = ex }
|
244
|
-
sleep(0.1)
|
245
|
-
@expected.should be_a(StandardError)
|
246
|
-
|
247
|
-
sleep(0.1)
|
248
|
-
EventMachine.stop
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'concurrent/agent'
|
4
|
+
require 'concurrent/future'
|
5
|
+
require 'concurrent/goroutine'
|
6
|
+
require 'concurrent/promise'
|
7
|
+
|
8
|
+
if Functional::PLATFORM.mri?
|
9
|
+
|
10
|
+
module Concurrent
|
11
|
+
|
12
|
+
describe EventMachineDeferProxy do
|
13
|
+
|
14
|
+
subject { EventMachineDeferProxy.new }
|
15
|
+
|
16
|
+
after(:all) do
|
17
|
+
$GLOBAL_THREAD_POOL = FixedThreadPool.new(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
context '#post' do
|
21
|
+
|
22
|
+
it 'proxies a call without arguments' do
|
23
|
+
@expected = false
|
24
|
+
EventMachine.run do
|
25
|
+
subject.post{ @expected = true }
|
26
|
+
sleep(0.1)
|
27
|
+
EventMachine.stop
|
28
|
+
end
|
29
|
+
@expected.should eq true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'proxies a call with arguments' do
|
33
|
+
@expected = []
|
34
|
+
EventMachine.run do
|
35
|
+
subject.post(1,2,3){|*args| @expected = args }
|
36
|
+
sleep(0.1)
|
37
|
+
EventMachine.stop
|
38
|
+
end
|
39
|
+
@expected.should eq [1,2,3]
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'aliases #<<' do
|
43
|
+
@expected = false
|
44
|
+
EventMachine.run do
|
45
|
+
subject << proc{ @expected = true }
|
46
|
+
sleep(0.1)
|
47
|
+
EventMachine.stop
|
48
|
+
end
|
49
|
+
@expected.should eq true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'operation' do
|
54
|
+
|
55
|
+
context 'goroutine' do
|
56
|
+
|
57
|
+
it 'passes all arguments to the block' do
|
58
|
+
$GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
|
59
|
+
|
60
|
+
EventMachine.run do
|
61
|
+
|
62
|
+
@expected = nil
|
63
|
+
go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
|
64
|
+
sleep(0.1)
|
65
|
+
@expected.should eq [3, 2, 1]
|
66
|
+
|
67
|
+
EventMachine.stop
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context Agent do
|
73
|
+
|
74
|
+
subject { Agent.new(0) }
|
75
|
+
|
76
|
+
before(:each) do
|
77
|
+
Agent.thread_pool = EventMachineDeferProxy.new
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'supports fulfillment' do
|
81
|
+
|
82
|
+
EventMachine.run do
|
83
|
+
|
84
|
+
@expected = []
|
85
|
+
subject.post{ @expected << 1 }
|
86
|
+
subject.post{ @expected << 2 }
|
87
|
+
subject.post{ @expected << 3 }
|
88
|
+
sleep(0.1)
|
89
|
+
@expected.should eq [1,2,3]
|
90
|
+
|
91
|
+
EventMachine.stop
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'supports validation' do
|
96
|
+
|
97
|
+
EventMachine.run do
|
98
|
+
|
99
|
+
@expected = nil
|
100
|
+
subject.validate{ @expected = 10; true }
|
101
|
+
subject.post{ nil }
|
102
|
+
sleep(0.1)
|
103
|
+
@expected.should eq 10
|
104
|
+
|
105
|
+
EventMachine.stop
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'supports rejection' do
|
110
|
+
|
111
|
+
EventMachine.run do
|
112
|
+
|
113
|
+
@expected = nil
|
114
|
+
subject.
|
115
|
+
on_error(StandardError){|ex| @expected = 1 }.
|
116
|
+
on_error(StandardError){|ex| @expected = 2 }.
|
117
|
+
on_error(StandardError){|ex| @expected = 3 }
|
118
|
+
subject.post{ raise StandardError }
|
119
|
+
sleep(0.1)
|
120
|
+
@expected.should eq 1
|
121
|
+
|
122
|
+
EventMachine.stop
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context Future do
|
128
|
+
|
129
|
+
before(:each) do
|
130
|
+
Future.thread_pool = EventMachineDeferProxy.new
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'supports fulfillment' do
|
134
|
+
|
135
|
+
EventMachine.run do
|
136
|
+
|
137
|
+
@a = @b = @c = nil
|
138
|
+
f = Future.new(1, 2, 3) do |a, b, c|
|
139
|
+
@a, @b, @c = a, b, c
|
140
|
+
end
|
141
|
+
sleep(0.1)
|
142
|
+
[@a, @b, @c].should eq [1, 2, 3]
|
143
|
+
|
144
|
+
sleep(0.1)
|
145
|
+
EventMachine.stop
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context Promise do
|
151
|
+
|
152
|
+
before(:each) do
|
153
|
+
Promise.thread_pool = EventMachineDeferProxy.new
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'fulfillment' do
|
157
|
+
|
158
|
+
it 'passes all arguments to the first promise in the chain' do
|
159
|
+
|
160
|
+
EventMachine.run do
|
161
|
+
|
162
|
+
@a = @b = @c = nil
|
163
|
+
p = Promise.new(1, 2, 3) do |a, b, c|
|
164
|
+
@a, @b, @c = a, b, c
|
165
|
+
end
|
166
|
+
sleep(0.1)
|
167
|
+
[@a, @b, @c].should eq [1, 2, 3]
|
168
|
+
|
169
|
+
sleep(0.1)
|
170
|
+
EventMachine.stop
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'passes the result of each block to all its children' do
|
175
|
+
|
176
|
+
EventMachine.run do
|
177
|
+
@expected = nil
|
178
|
+
Promise.new(10){|a| a * 2 }.then{|result| @expected = result}
|
179
|
+
sleep(0.1)
|
180
|
+
@expected.should eq 20
|
181
|
+
|
182
|
+
sleep(0.1)
|
183
|
+
EventMachine.stop
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'sets the promise value to the result if its block' do
|
188
|
+
|
189
|
+
EventMachine.run do
|
190
|
+
|
191
|
+
p = Promise.new(10){|a| a * 2 }.then{|result| result * 2}
|
192
|
+
sleep(0.1)
|
193
|
+
p.value.should eq 40
|
194
|
+
|
195
|
+
sleep(0.1)
|
196
|
+
EventMachine.stop
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'rejection' do
|
202
|
+
|
203
|
+
it 'sets the promise reason and error on exception' do
|
204
|
+
|
205
|
+
EventMachine.run do
|
206
|
+
|
207
|
+
p = Promise.new{ raise StandardError.new('Boom!') }
|
208
|
+
sleep(0.1)
|
209
|
+
p.reason.should be_a(Exception)
|
210
|
+
p.reason.should.to_s =~ /Boom!/
|
211
|
+
p.should be_rejected
|
212
|
+
|
213
|
+
sleep(0.1)
|
214
|
+
EventMachine.stop
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'calls the first exception block with a matching class' do
|
219
|
+
|
220
|
+
EventMachine.run do
|
221
|
+
|
222
|
+
@expected = nil
|
223
|
+
Promise.new{ raise StandardError }.
|
224
|
+
on_error(StandardError){|ex| @expected = 1 }.
|
225
|
+
on_error(StandardError){|ex| @expected = 2 }.
|
226
|
+
on_error(StandardError){|ex| @expected = 3 }
|
227
|
+
sleep(0.1)
|
228
|
+
@expected.should eq 1
|
229
|
+
|
230
|
+
sleep(0.1)
|
231
|
+
EventMachine.stop
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'passes the exception object to the matched block' do
|
236
|
+
|
237
|
+
EventMachine.run do
|
238
|
+
|
239
|
+
@expected = nil
|
240
|
+
Promise.new{ raise StandardError }.
|
241
|
+
on_error(ArgumentError){|ex| @expected = ex }.
|
242
|
+
on_error(LoadError){|ex| @expected = ex }.
|
243
|
+
on_error(Exception){|ex| @expected = ex }
|
244
|
+
sleep(0.1)
|
245
|
+
@expected.should be_a(StandardError)
|
246
|
+
|
247
|
+
sleep(0.1)
|
248
|
+
EventMachine.stop
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|